#+BEGIN_COMMENT .. title: Git! Branching and Merging .. date: 2019-08-01 .. slug: git-branching-and-merging .. updated: 2019-08-01 .. status: published .. tags: git, revision-control .. category: revision-control .. authors: Elia el Lazkani .. description: Explaining branches, branching and merging strategies. .. type: text #+END_COMMENT In the previous post about /git/, we had a look at what /git/ is and got our feet wet with a bit of it. In this post, I will be moving forward with the topic, I will be talking about branches, how to work with them and finally what merging is and how it works. {{{TEASER_END}}} * Requirements The same requirement we had from the last post, obviously /git/. * Branching and Merging ** What is a branch? /git/ [[https://git-scm.com/book/en/v1/Git-Branching-What-a-Branch-Is][documentation]] describes it as: #+BEGIN_QUOTE "A branch in Git is simply a lightweight movable pointer to one of the[se] commits." #+END_QUOTE Usually, people coming from /svn/ think of *branches* differently. In /git/, a branch is simply a pointer to a commit. So let's verify that claim to see if it's true. Remember our example repository from the last post ? We'll be using it here. First let's create a new branch. #+BEGIN_EXAMPLE $ git checkout -b mybranch Switched to a new branch 'mybranch' #+END_EXAMPLE That was simple, wasn't it ? Alright, let's test our hypothesis. #+BEGIN_EXAMPLE $ git log commit 643a353370d74c26d7cbf5c80a0d73988a75e09e (HEAD -> mybranch, master) Author: John Doe Date: Thu Aug 1 19:50:45 2019 +0200 Second commit #+END_EXAMPLE The commit is, of course, different because this is a different computer with a different repository from scratch. Anyway, it seems from the log message that both /mybranch/ and /master/ are pointing to same commit /SHA/. Technically they are pointing to *HEAD*. Now let's continue and add a new commit. #+BEGIN_EXAMPLE $ echo "" >> README.md $ git add README.md $ git commit -m "Adding an empty line" [mybranch b30f4e0] Adding an empty line 1 file changed, 1 insertion(+) #+END_EXAMPLE After this last commit, let's check the log #+BEGIN_EXAMPLE $ git log commit b30f4e0fa8f3b5c9f041c9ad1be982b2fed80851 (HEAD -> mybranch) Author: John Doe Date: Thu Aug 1 20:28:05 2019 +0200 Adding an empty line commit 643a353370d74c26d7cbf5c80a0d73988a75e09e (master) Author: John Doe Date: Thu Aug 1 19:50:45 2019 +0200 Second commit #+END_EXAMPLE From reading the output of log, we can see that the /master/ branch points to a different commit than /mybranch/. To visualize this, let's look at it in a different way. #+BEGIN_EXAMPLE $ git log --graph --oneline --all * b30f4e0 (HEAD -> mybranch) Adding an empty line * 643a353 (master) Second commit #+END_EXAMPLE What the above suggests is that our two branches have different contents at this stage. In other words, if I switch back to the /master/ branch what do you think we will find in =README.md= ? #+BEGIN_EXAMPLE $ git checkout master Switched to branch 'master' $ cat README.md # Example This is an example repository. This repository is trying to give you a hands on experience with git to complement the post. $ #+END_EXAMPLE And if we switch back to /mybranch/. #+BEGIN_EXAMPLE $ git checkout mybranch Switched to branch 'mybranch' $ cat README.md # Example This is an example repository. This repository is trying to give you a hands on experience with git to complement the post. $ #+END_EXAMPLE Let's add another commit to make easier to see the changes than an empty line. #+BEGIN_EXAMPLE $ echo "Let's add a line to mybranch." >> README.md $ git add README.md $ git commit -m "Adding more commits to mybranch" [mybranch f25dd5d] Adding more commits to mybranch 1 file changed, 1 insertion(+) #+END_EXAMPLE Now let's check the tree again. #+BEGIN_EXAMPLE $ git log --graph --oneline --all * f25dd5d (HEAD -> mybranch) Adding more commits to mybranch * b30f4e0 Adding an empty line * 643a353 (master) Second commit #+END_EXAMPLE Let's also check the difference between our /master/ branch and /mybranch/. #+BEGIN_EXAMPLE $ git diff master mybranch diff --git a/README.md b/README.md index b4734ad..f07e71e 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,5 @@ This is an example repository. This repository is trying to give you a hands on experience with git to complement the post. + +Let's add a line to mybranch. #+END_EXAMPLE The =+= suggests an addition and =-= suggests a deletion of a line. As we can see from the =+= shown before the two lines added to the =README.md= file, /mybranch/ has these additions. You can read more about /git/ branches in the /git/ [[https://git-scm.com/book/en/v1/Git-Branching-What-a-Branch-Is][documentation]] page. ** What is merging ? That's all fine so far, but how do I get these changes from /mybranch/ to the /master/ branch ? The answer to that is also as easy as all the steps taken so far. /git/ merges *from* a branch you specify *to* the branch you are currently on. #+BEGIN_EXAMPLE $ # Checking which branch we are on $ git branch master * mybranch $ # We are on mybranch and we need to put these changes into master $ # First we need to move to our master branch $ git checkout master Switched to branch 'master' $ # Now we can merge from mybranch $ git merge mybranch Updating 643a353..f25dd5d Fast-forward README.md | 2 ++ 1 file changed, 2 insertions(+) #+END_EXAMPLE As we can see. The changes in /mybranch/ have been merged into the /master/ branch. #+BEGIN_EXAMPLE $ git log commit f25dd5da3e6f91d117177782a5811d5086f66799 (HEAD -> master, mybranch) Author: John Doe Date: Thu Aug 1 20:43:57 2019 +0200 Adding more commits to mybranch commit b30f4e0fa8f3b5c9f041c9ad1be982b2fed80851 Author: John Doe Date: Thu Aug 1 20:28:05 2019 +0200 Adding an empty line commit 643a353370d74c26d7cbf5c80a0d73988a75e09e Author: John Doe Date: Thu Aug 1 19:50:45 2019 +0200 Second commit #+END_EXAMPLE * Merging Strategies I'll explain to you how I like to work and my personal merging strategy. I will keep out some details as they use concepts that are more advanced than what has been discussed so far. ** /master/ branch To me, the /master/ branch stays always up to date with the *remote* /master/ branch. In other words, I do not make commits against the /master/ branch in the project I'm working on. ** branch If I want to work on the project, I start by updating the /master/ branch and then branching it as we've seen before. The name of the branch is always indicative on what it holds, or what kind of work I am doing on it. As long as I am working on my dev branch, I keep updating the /master/ branch and then porting the changes into my dev branch. This way, at the end the code is compatible and I am testing with the latest version of the code. This is very helpful and makes merging later a breeze. ** merging After my work is done, I push my branch to the remote server and ask for the maintainer of the project to merge my changes into the /master/ branch after reviewing it, of course. To explain this in a very simple manner, all that mumbo jumpo talk previously simply means someone else did the merge into master. * Conclusion In this post, I talked about what are branches. We went ahead and worked a little bit with branches and then mentioned merging. At the end of the post I talked a bit about my merging strategy. In the next post, I will be talking about remotes.