{"id":408,"date":"2021-09-19T13:12:04","date_gmt":"2021-09-19T21:12:04","guid":{"rendered":"http:\/\/spacefold.com\/colin\/morethanfour\/?p=408"},"modified":"2022-05-15T13:46:05","modified_gmt":"2022-05-15T21:46:05","slug":"learning-git-1-the-basics","status":"publish","type":"post","link":"https:\/\/spacefold.com\/colin\/morethanfour\/2021\/09\/19\/learning-git-1-the-basics\/","title":{"rendered":"Learning Git: 1: The Basics"},"content":{"rendered":"\n<p>(Previously: <a href=\"https:\/\/spacefold.com\/colin\/morethanfour\/2021\/09\/19\/learning-git-0-introduction\/\">Part 0 &#8211; Introduction<\/a>)<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Initializing a local repository<\/h3>\n\n\n\n<p>The <strong>git init<\/strong> command sets up a local repository in the current folder:<\/p>\n\n\n\n<pre>$ cd ~\/Projects\/cow_tipper\n$ git init<\/pre>\n<pre class=\"console-output\">Reinitialized existing Git repository in \/home\/buster\/Projects\/cow_tipper\/.git\/<\/pre>\n\n\n\n<p>Change history is stored in a <strong>.git<\/strong> sub-directory.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Tracking changes, Staging and Committing<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Tracked source files<\/h4>\n\n\n\n<p>A <strong>tracked<\/strong> source file is one that is understood by Git to require a change history to be saved in the repository. Our source directory may contain &#8220;tracked&#8221; and &#8220;untracked&#8221; files. We won&#8217;t be able to recover change history for an untracked file.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Committing<\/h4>\n\n\n\n<p>A <strong>commit<\/strong> saves a set of source file changes as a &#8220;snapshot&#8221; that can be recovered later. Commits are sequential, and have a pointer to their parent snapshot. A text message is saved along with the commit.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Staging<\/h4>\n\n\n\n<p><strong>Staging<\/strong> is the process of adding a file to the set of changes that will be included in the next commit operation.<\/p>\n\n\n\n<p>Now I need to stage my source files for the first commit:<\/p>\n\n\n\n<pre>$ git add README.md\n$ git add cow_tipper.py<\/pre>\n\n\n\n<p>The <strong>add<\/strong> command does two things:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>It marks a file as &#8220;tracked&#8221;;<\/li><li>It copies the file into a staging area<\/li><\/ul>\n\n\n\n<p>Alternatively, I could just add all the files in the directory in one go:<\/p>\n\n\n\n<pre>$ git add *<\/pre>\n\n\n\n<p>At this point, all files in the folder are &#8220;tracked&#8221; and ready to be committed. We can double-check where we are at any time by asking Git using the <strong>git status<\/strong> command:<\/p>\n\n\n\n<pre>$ git status<\/pre> \n<pre class=\"console-output\">On branch master \nChanges to be committed: (use \"git restore --staged &lt;file&gt;\" to unstage)\n   new file: README.md \n   new file: cow_tipper.py<\/pre>\n\n\n\n<p>Nice. Let&#8217;s save this (&#8220;commit&#8221; it) to a recoverable snapshot. We&#8217;ll use the <strong>-m<\/strong> switch to supply a text message directly on the command-line:<\/p>\n\n\n\n<pre>$ git commit -m \"First Commit\"<\/pre>\n<pre class=\"console-output\">* * * Please tell me who you are.\nRun   git config --global user.email \"you@example.com\"\n      git config --global user.name \"Your Name\"\nto set your account's default identity.\nOmit --global to set the identity only in this repository.\nfatal: unable to auto-detect email address<\/pre>\n\n\n\n<p>Oops! Of course Git needs to know who we are, and even tells us what commands we need to run to do this:<\/p>\n\n\n\n<pre>$ git config --global user.email \"buster@spacefold.com\"\n$ git config --global user.name \"Buster Kitten\"<\/pre>\n\n\n\n<p>Now let&#8217;s re-try that commit:<\/p>\n\n\n\n<pre>$ git commit -m \"First commit\"<\/pre>\n<pre class=\"console-output\">[master c9b7b58] First commit\n 2 files changed, 8 insertions(+)\n create mode 100644 README.md\n create mode 100644 cow_tipper.py<\/pre>\n\n\n\n<p>Success!  Note that we don&#8217;t have to use the <strong>-m &#8220;message&#8221;<\/strong> command-line switch. If we just <strong>git commit<\/strong> then the default text editor will be launched so that we can edit the message. We can customize what editor is used in the configuration: See <a href=\"https:\/\/spacefold.com\/colin\/morethanfour\/2021\/09\/19\/learning-git-appendix-b-customizing-the-message-editor\/\">Appendix B: Customizing the Message Editor<\/a>.<\/p>\n\n\n\n<p>If we&#8217;re really in a hurry we can Stage+Commit in one command:<\/p>\n\n\n\n<pre>$ git commit -a<\/pre>\n\n\n\n<p>Speaking of configuration parameters, at any time we can ask Git to show us the configuration it&#8217;s working with, using <strong>git config<\/strong>:<\/p>\n\n\n\n<pre>$ git config --list --show-origin<\/pre>\n<pre class=\"console-output\">file:\/home\/buster\/.gitconfig     user.email=buster@spacefold.com\nfile:\/home\/buster\/.gitconfig     user.name=Buster Kitten\nfile:.git\/config        core.repositoryformatversion=0\nfile:.git\/config        core.filemode=true\nfile:.git\/config        core.bare=false\nfile:.git\/config        core.logallrefupdates=true<\/pre>\n\n\n\n<p>Read more about Git configuration here: <a rel=\"noreferrer noopener\" href=\"https:\/\/git-scm.com\/book\/en\/v2\/Customizing-Git-Git-Configuration\" target=\"_blank\">https:\/\/git-scm.com\/book\/en\/v2\/Customizing-Git-Git-Configuration<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The Git Log<\/h3>\n\n\n\n<p>Note that each commit gets an identifying hash value assigned to it. We can see the first 7 characters &#8220;c9b7b58&#8221; in that commit message output above.<\/p>\n\n\n\n<p>The command <strong>git log<\/strong> will list recent commits along with their hash, author, date, and comment. The format of the output is very controllable, for example:<\/p>\n\n\n\n<pre>$ git log --pretty=format:\"%h - %an, %ar : %s\"<\/pre>\n<pre class=\"console-output\">e875278 - Buster Kitten, 36 minutes ago : trialling the secondary pump control block\n82c55cb - Buster Kitten, 14 hours ago : Working on the next problem.\nfc5fea3 - Buster Kitten, 22 hours ago : I just added a line for test purposes.\naaee8e5 - Buster Kitten, 24 hours ago : Removing files we don't need.\nc9b7b58 - Buster Kitten, 3 days ago : First commit<\/pre>\n\n\n\n<p>I&#8217;m not going to go into depth about the Git log, so for further reading I recommend: <a rel=\"noreferrer noopener\" href=\"https:\/\/git-scm.com\/book\/en\/v2\/Git-Basics-Viewing-the-Commit-History\" target=\"_blank\">Git Basics &#8211; Viewing the Commit History (The Git Book)<\/a><\/p>\n\n\n\n<p>(I&#8217;ve also written about git log before: <a rel=\"noreferrer noopener\" href=\"https:\/\/spacefold.com\/colin\/morethanfour\/2016\/07\/05\/git-obtaining-a-useful-log-of-recent-check-ins\/\" target=\"_blank\">Obtaining a useful log of recent check-ins<\/a>.)<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Tagging<\/h3>\n\n\n\n<p>One important feature of a source control system is to retrieve a known snapshot from the change history. Although we can use the unique hash identifier to retrieve a specific snapshot from the repository, it is easier if we use a <strong>Tag<\/strong> to mark important points in the history.<\/p>\n\n\n\n<p>Tags are named pointers to specific commit points in the repository change history. We can retrieve a copy of your tracked source files as they were at the time the tag was created. Typically tags are used to mark release points in a development process, such as &#8220;Beta 1&#8221;, &#8220;Beta 2&#8221;, &#8220;version 0.0.7&#8221;, etc.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Creating a tag<\/h4>\n\n\n\n<p>We use the <strong>git tag<\/strong> command to label the most recent commit:<\/p>\n\n\n\n<pre>$ git tag v.0.0.0<\/pre>\n\n\n\n<p>Or if we like, we can create an &#8220;annotated&#8221; tag complete with a text message:<\/p>\n\n\n\n<pre>$ git tag -a v.0.0.0 -m \"This is the initial state of my source code\"<\/pre>\n\n\n\n<p>For more on tagging, see <a rel=\"noreferrer noopener\" href=\"https:\/\/git-scm.com\/book\/en\/v2\/Git-Basics-Tagging\" target=\"_blank\">https:\/\/git-scm.com\/book\/en\/v2\/Git-Basics-Tagging<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How do I&#8230;?<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Protect files from being tracked (e.g. .log or .bak files)<\/h4>\n\n\n\n<p><strong>git add *<\/strong> is very convenient but if we want to prevent some files from being included in that broad scope, we can leverage the <strong>.gitignore<\/strong> file. <br>See <a rel=\"noreferrer noopener\" href=\"https:\/\/www.atlassian.com\/git\/tutorials\/saving-changes\/gitignore\" target=\"_blank\">https:\/\/www.atlassian.com\/git\/tutorials\/saving-changes\/gitignore<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Change a tracked file name<\/h4>\n\n\n\n<p>The <strong>mv<\/strong> command both renames a file in the file system and stages the change for the next commit:<\/p>\n\n\n\n<pre>$ git mv &lt;old&gt; &lt;new&gt;<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Delete a tracked file<\/h4>\n\n\n\n<p>The <strong>rm<\/strong> command stages a file for removal, and also deletes the file in the file system:<\/p>\n\n\n\n<pre>$ git rm &lt;file&gt;<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Unstage a file added incorrectly<\/h4>\n\n\n\n<p>To unstage a file, either of these commands work. &#8220;restore &#8211;staged&#8221; is the new way:<\/p>\n\n\n\n<pre>$ git reset HEAD &lt;file&gt;\n$ git restore --staged &lt;file&gt;<\/pre>\n\n\n\n<p>Or just unstage everything staged so far:<\/p>\n\n\n\n<pre>$ git reset<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Replace a staged file with a more up-to-date version<\/h4>\n\n\n\n<p>If you make a second edit to a file after you&#8217;ve already staged it, just stage it again to replaced the staged copy:<\/p>\n\n\n\n<pre>$ git add &lt;file&gt;<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Revert just one file<\/h4>\n\n\n\n<p>To discard changes in the working directory, either of these commands work:<\/p>\n\n\n\n<pre>$ git checkout -- &lt;file&gt;\n$ git restore &lt;file&gt; <\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Delete multiple files using a wildcard spec<\/h4>\n\n\n\n<p>This command removes files from staging, and also escapes the wildcard character, which is necessary:<\/p>\n\n\n\n<pre>$ git rm --cached \\*.log<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Find out what tags I have<\/h4>\n\n\n\n<pre>$ git tag<\/pre>\n<pre class=\"console-output\">v0.0.0\nv0.0.1<\/pre>\n\n\n\n<p>Next up, <a href=\"https:\/\/spacefold.com\/colin\/morethanfour\/2021\/09\/19\/learning-git-2-branching\/\">Part 2: Branching<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>(Previously: Part 0 &#8211; Introduction) Initializing a local repository The git init command sets up a local repository in the current folder: $ cd ~\/Projects\/cow_tipper $ git init Reinitialized existing Git repository in \/home\/buster\/Projects\/cow_tipper\/.git\/ Change history is stored in a .git sub-directory. Tracking changes, Staging and Committing Tracked source files A tracked source file is [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15],"tags":[],"class_list":["post-408","post","type-post","status-publish","format-standard","hentry","category-source-control","post-preview"],"_links":{"self":[{"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/posts\/408","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/comments?post=408"}],"version-history":[{"count":1,"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/posts\/408\/revisions"}],"predecessor-version":[{"id":486,"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/posts\/408\/revisions\/486"}],"wp:attachment":[{"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/media?parent=408"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/categories?post=408"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/tags?post=408"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}