Commit graph from the lens of different git operations
As developers, we have all used git at one point or another. In this article, I am going to explain the commit graph through various kinds of merge we can do.
There are three types of merging. We have basic merge, squash & merge and rebase.
Before going through each git operations, I wanted to explain the base commit graph I will be using throughout.
NOTE: I have used the below git command to see the graph
git log --graph --abbrev-commit --decorate --date=relative --all
If you understood the image above, You can skip this part and go to merge directly.
So, initially, we have a master branch after running the command git init in our empty project folder. We made 2 commits in master(340175c, 55b9887), and for the ease of understanding, I have given commit message as ‘1 master’, ‘2 master’ which means the number of the commit and the branch. After that, I checked out a branch ‘feature’ and made 2 more commits there(1222581, 009bd98). Then coming back to master again. And made one more commit(76d6b19). From that, I checkout another branch that is release and made 3 more commits in this branch (db09a1b, 2a94511, 3cfc723). And finally, checkout to master for the last time ( I promise), and made 2 more commits (a7ad6e5, 12f14eb).
I hope we are on the same page until now.
So What’s next?
Now our goal is to have all the features of ‘feature’ branch into our ‘master’ branch.
Let’s go then.
- Merge
Currently, the HEAD or the tip of the branch we are on is master as you can see in the above figure also. In master, we need to run a git operation
git merge feature
As you can see in the above diagram, the latest commit of feature is showing an arrow or a merge kind of sign into the latest master branch. Before merging, git will ask you to have a merge commit asking why this merge is required. It gives us a default commit message or we can change it according to our convenience.
If we see the git log now, it will show all the commits of master and feature branch included pointing out that it has been descended from both of the branches. I will tell you why am I focussing on git log when we cover squash & merge. And with that, we have finished merging for this part. Let’s go-to squash and merge.
2. Squash & merge
Squash and merge, as the name suggests, squash all the commits of feature branch into one and put it on top of the master branch.
Why we need squash and merge?
Imagine you are working on a feature and made 10 commits in your local branch. When you merge the code with the master branch (let’s say), where your other teammates also merge their code, they don’t need to know how many commits you have made. They just need one commit that will represent all of commits of ‘feature’ branch.
So for squash, you need to run
git merge --squash feature
Here the commits of feature (1222581, 009bd98) are squashed into one (dc195d1) and put on top of ‘master’ branch
This will also prompt you to have a commit message. As you can see, there is no merging sign from feature to master. If you see the git log here, you won’t see the commits 1222581, 009bd98 which you were able to see in git log when we have done basic merge. This is because squash and merge don’t actually merge the feature branch into the commit, rather it squashes the feature branch commits and puts it on top of the master. The HEAD ( dc195d1) will have no relation to the feature branch. It has not been descended from the feature branch, unlike in basic merge. It will just show a new squashed commit (dc195d1) which will have feature branch squashed commits.
With this, we have completed our squash and merge as well. Let’s now head to rebase
3) Rebase
NOTE: We are assuming no conflicts while rebasing for now. In the last two-part, we could have just resolved the conflicts and committed them. It’s different for rebase. I will cover that in a separate blog.
So what is Rebase?
As the name suggests, it merges by changing the base of a branch🙄. Okay, I will try again.
What we will try to do is to change the base of feature branch form 2nd commit of master (55b9887) to make it look like it is checked out from latest commit of master (12f14eb). Okay, let’s deal with it from graph perspective.
The HEAD now is at the feature branch.
From here, we need to run
git rebase master
Initially, we had,
We can see here that the feature branch is checked out from the 2nd commit of master(55b9887).
After running ‘git rebase master` on feature branch, we will get,
Note: I have checked out into ‘master’ branch.
We can see the HEAD is at master and the feature is not checked out from the 2nd commit of ‘master’ branch (55b9887) as before but from our latest commit on master (12f14eb). And you can also notice that the commit IDs also changed for the two commits made in ‘feature’ branch which was previously 1222581, 009bd98 and now it is 8d122f6, 27d0291
So we can say now, the base for the feature branch has changed.
That’s how rebase works.
But our work here is not done. ‘master’ branch still doesn't have the changes from feature since the HEAD is at 12f14eb.
Now we are going to do exactly the same thing in ‘master’ branch which we did in ‘feature’ branch.
Let’s go.
Now we are at ‘master’ branch. Now we would run
git rebase feature
Now we would be able to see ‘feature’ commits in master. The master and feature branch are both pointing to the same commit.
And finally, that’s how rebase works.
There might be many cases in rebase where things can go haywire while rebasing.
One case might be when you will try to initially do rebase in master before doing it in ‘feature’ branch. Try it out. The result would be fun😅 and I will not even go for conflicts. It would be a real delight.
I will cover other eccentricities of rebase in another blog.
So why to use rebase over merge or squash & merge?
- So as we can see in the above image, it is giving us a linear picture while preserving our commits, yes with different commit IDs, but we are getting all our commits. So when more developers merge their code in a single branch, the project history would be cleaner when rebase is used compared to merge.
- We don't have to do unnecessary merge commit while rebasing.
So this is all about different git operations and their respective graphs look. And all the merge operations have their own advantages and complications. So choose wisely for your team.
Happy Blogging!