{"id":418,"date":"2021-09-19T13:10:00","date_gmt":"2021-09-19T21:10:00","guid":{"rendered":"http:\/\/spacefold.com\/colin\/morethanfour\/?p=418"},"modified":"2021-09-19T13:31:20","modified_gmt":"2021-09-19T21:31:20","slug":"learning-git-2-branching","status":"publish","type":"post","link":"https:\/\/spacefold.com\/colin\/morethanfour\/2021\/09\/19\/learning-git-2-branching\/","title":{"rendered":"Learning Git &#8211; 2: Branching"},"content":{"rendered":"\n<p>(Previously: <a href=\"https:\/\/spacefold.com\/colin\/morethanfour\/2021\/09\/19\/learning-git-1-the-basics\/\">Part 1 &#8211; The Basics<\/a>)<\/p>\n\n\n\n<p>Remember that a Git repository is a sequence of commits, where each commit includes a pointer to its &#8220;parent&#8221;.<\/p>\n\n\n\n<p>A <strong>branch<\/strong> in Git is just a pointer to one of those commits. There is a default branch typically called &#8220;master&#8221;. As we make commits, the master branch pointer moves forward along the sequence.<\/p>\n\n\n\n<p>We can create a second branch pointer named, say, &#8220;secundo&#8221;:<\/p>\n\n\n\n<pre>$ git branch secundo<\/pre>\n\n\n\n<p>Now we have a new named pointer (branch), which currently also points to the same commit as &#8220;master&#8221;.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Switching branches<\/h3>\n\n\n\n<p>We can switch to this branch, and continue making commits on it:<\/p>\n\n\n\n<pre>$ git checkout secundo\n$ git switch secundo<\/pre>\n\n\n\n<p>Either of these commands will change the current branch to be &#8220;secundo&#8221; instead of &#8220;master&#8221;. switch is more recent syntax and I think it is clear in intent.<\/p>\n\n\n\n<p>As we make more commits, the &#8220;secundo&#8221; branch pointer advances to keep up. Meanwhile, &#8220;master&#8221; remains unchanged. We can switch back to it:<\/p>\n\n\n\n<pre>$ git switch master<\/pre>\n\n\n\n<p>When we do this, the source files revert to what they were at the commit point that the &#8220;master&#8221; branch is pointing to. Any commits made now will advance the &#8220;master&#8221; branch pointer independently from the &#8220;secundo&#8221; branch: they will be pointing to different commit points in the repository history tree.<\/p>\n\n\n\n<p><strong>Note:<\/strong> Git refers to the current state of the source directory as &#8220;HEAD&#8221;. It marks the current branch, and advances forward as commits are made on the current branch.<\/p>\n\n\n\n<p>So, when we switch back to &#8220;secundo&#8221;, HEAD is moving to that branch, and (naturally) the source files are restored to reflect the latest state of &#8220;secundo&#8221;.<\/p>\n\n\n\n<p>If you have files open in an editor, be alert for &#8220;file has changed outside the editor; reload?&#8221; warnings. And if your editor isn&#8217;t smart enough to warn you about file system changes, I recommend you find another editor.<\/p>\n\n\n\n<p><strong>Important<\/strong>: any staged files are discarded when you switch branches. Also, any edits in the working tree will be discarded as the version from the switched-to branch is placed into the working tree.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Branch management<\/h3>\n\n\n\n<p>Creating branches in Git is a very low impact operation. We can create and switch to a new brand in one step:<\/p>\n\n\n\n<pre>$ git switch -c temp_stuff<\/pre>\n\n\n\n<p>Delete it when we&#8217;re done experimenting (you can&#8217;t delete the currently checked-out branch):<\/p>\n\n\n\n<pre>$ git switch master\n$ git branch -d temp_stuff<\/pre>\n\n\n\n<p>Or rename it, if it turns out our experiments are worth keeping for later:<\/p>\n\n\n\n<pre>$ git branch --move temp_stuff keep_stuff<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Merging<\/h3>\n\n\n\n<p>So, I&#8217;ve made some changes in my &#8220;secundo&#8221; branch and I want to keep them and move them into the &#8220;master&#8221; branch. I could do this manually but one of the powerful features of using Git is that it can do this for us: <strong>Merging<\/strong> combines source file changes made in one branch with existing and possibly different changes made in another branch.<\/p>\n\n\n\n<p>First, we need to switch to the target branch, and then perform the merge:<\/p>\n\n\n\n<pre>$ git switch master\n$ git merge secundo<\/pre>\n<pre class=\"console-output\">Updating 82c55cb..fba73e5\nFast-forward\n README.md     |  4 ++--\n cow_tipper.py | 14 +++++++++++++-\n 2 files changed, 15 insertions(+), 3 deletions(-)<\/pre>\n\n\n\n<p>The source files in the directory have been updated, and contain the changes from the &#8220;secundo&#8221; branch. We end up with changes made in both branches.<\/p>\n\n\n\n<p>I could now delete the &#8220;secundo&#8221; branch if I wanted.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Resolving conflicts<\/h3>\n\n\n\n<p>What happens if different changes are made to the same section of code in both branches? Let&#8217;s try it:<\/p>\n\n\n\n<pre>$ git merge secundo<\/pre>\n<pre class=\"console-output\">Auto-merging cow_tipper.py\nCONFLICT (content): Merge conflict in cow_tipper.py\nAutomatic merge failed; fix conflicts and then commit the result.<\/pre>\n\n\n\n<p>We can get some more advice from git status:<\/p>\n\n\n\n<pre>$ git status<\/pre> \n<pre class=\"console-output\">On branch master \nYou have unmerged paths.\n  (fix conflicts and run \"git commit\")\n  (use \"git merge --abort\" to abort the merge) \n\nUnmerged paths: \n  (use \"git add &lt;file&gt;...\" to mark resolution) \n     both modified: cow_tipper.py \n\nno changes added to commit (use \"git add\" and\/or \"git commit -a\")<\/pre>\n\n\n\n<p>Git is telling us that it couldn&#8217;t perform the merge automatically, and that we&#8217;ll have to correct it manually. Here&#8217;s what <strong>cow_tipper.py<\/strong> looks like in the &#8220;master&#8221; branch now:<\/p>\n\n\n\n<pre>&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD\noutput_text = \"Cow Tipping For Beginners\"\nprint( output_text )\n=======\nfirst_cut = \"Cow Tipping: A Beginners Guide\"\nprint( first_cut )\n&gt;&gt;&gt;&gt;&gt;&gt;&gt; secundo<\/pre>\n\n\n\n<p>I&#8217;ll have to decide which variable name is best, and which output text string is correct, and make the edits, and then commit the changes into &#8220;master&#8221;.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How do I&#8230;?<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Return to the previously checked-out branch<\/h4>\n\n\n\n<pre>$ git switch -<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Retrieve files by tag<\/h4>\n\n\n\n<p>Probably the best way is to use a temporary branch and then checkout the tag:<\/p>\n\n\n\n<pre>$ git branch tmp_v0_0_0\n$ git switch tmp_v0_0_0\n$ git checkout v0.0.0<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Further reading<\/h4>\n\n\n\n<p>There&#8217;s a whole chapter on this and it is worth digging into:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/git-scm.com\/book\/en\/v2\/Git-Branching-Branches-in-a-Nutshell\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/git-scm.com\/book\/en\/v2\/Git-Branching-Branches-in-a-Nutshell<\/a><\/li><li>Merging: <a href=\"https:\/\/git-scm.com\/docs\/git-merge\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/git-scm.com\/docs\/git-merge<\/a><\/li><\/ul>\n\n\n\n<p>That&#8217;s all for this chapter. Next: <a href=\"https:\/\/spacefold.com\/colin\/morethanfour\/2021\/09\/19\/learning-git-3-remotes\/\">Part 3: Remotes<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>(Previously: Part 1 &#8211; The Basics) Remember that a Git repository is a sequence of commits, where each commit includes a pointer to its &#8220;parent&#8221;. A branch in Git is just a pointer to one of those commits. There is a default branch typically called &#8220;master&#8221;. As we make commits, the master branch pointer moves [&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-418","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\/418","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=418"}],"version-history":[{"count":0,"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/posts\/418\/revisions"}],"wp:attachment":[{"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/media?parent=418"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/categories?post=418"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/spacefold.com\/colin\/morethanfour\/wp-json\/wp\/v2\/tags?post=418"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}