Introduction
One of the most important features of GIT is branching. The development of multiple functionalities can be done parallel, independently of each other.
In the end of course a version will be needed which includes functionalities from multiple branches. The article is a brief overview on the methods about how you can create such a version.
Overview on GIT branches
In GIT every commit knows its parent. So the list of your GIT commits is a one-way linked list, representing the order of the commits. By default you are working on a branch named master. A branch is always stored as a simple hash id, which is the hash id of the latest commit on the branch. You can anytime start a new branch based on the current HEAD commit by the command git branch branch_name. This command creates a new branch, pointing to the current commit. Then you can change to this branch by git checkout branch_name. This will change your HEAD to your branch. Or you can do these steps together by typing git checkout -b branch_name.
On a branch you can work independently from the master branch. You can implement a new functionality, fix a bug or do some refactoring. In the meanwhile others are working on the master branch or on some other branches. Until you are working on your functionality new functionalities will be added to the master branch. At this point you have to create a version which has all the content of the current master plus your changes from your branch. There are three ways to do it. Letβs see the details.
Merge
The first, very classical way is git merge. While being on master branch (you can always check your current branch by typing git branch) type git merge your_branch. This command will create a new merge commit to the master branch.
What is a merge commit?
In GIT every commit has one single parent commit, except merge commits which have two or even more parents. The command git merge master creates a merge commit with two parents: the last commit of your branch and the last commit of master. So that by checking out this commit you will have both the changes on the master and on your branch. During merging conflicts can appear if the same lines have been modified on the two branches. In this case these conflicts have to be manually resolved.
Before merging always make sure that your branches are up to date with the remote branch.
The big advantage of git merge is that the history of the commit stays clear and unchanged.
The disadvantage is that large amount of merge commits can make the branch history unreadable.
Rebase
The second option is git rebase. Git rebase is changing the parent of the first commit on your branch. So git rebase master will change the parent of the first commit of your branch to the latest commit on the master branch.
To be able to do it all commits on the branch needs to be modified, because in this way they will contain the change being done on the master. Since you are changing the commits, their hash id will also change. So technically they will be new commits. That also means that multiple instances of the same commit (rebased and non-rebased) can appear in the git log. You really have to pay attention!
Furthermore git rebase is being done commit by commit, so the same conflicts can appear again and again.
The advantage of this method is that your history will stay one straight line, on the other hand it wonβt be possible to figure out later, that a git rebase happened.
You should especially pay attention to rebasing if multiple developers are working on the same branch.
Cherry-pick
Git cherry-pick is the best command if you want to move only one (or some) commit from different branches to the current branch.
For example you have a bugfix commit on one of your branches and you donβt want to merge the whole branch to the master, only the one commit which is fixing the bug. You should checkout the master branch and type git cherry-pick commit_id, where commit_id is the hash id of the bugfix branch. This command will create a new commit (with a new commit id) on the master branch, which has the very same changes as the cherry-picked commit. The cherry-picked commit will stay untouched.
Summary of merge, rebase and cherry-pick
To summarize the topic: git merge doesnβt change any existing commit, it just creates a new merge commit, which has two or more parents.
Git rebase changes the parent of the one commit (usually the root of the branch, or the commit given as a parameter). With other words it is rewriting the history of the branch (or commit). The commits get a new hash id.
Git cherry-pick reapplies one dedicated topic on the current branch, with a new commit id. The cherry-picked commit stays untouched.
Top comments (2)
Hi Marcell!
Very good explanatory article, though perhaps it may be worth to add (perhaps in future post) about using
squash
. As sometimes, when merging commits from feature-branch, we see several auxiliary changes like "code cleanup to make lint/stylecheck happy" - and we don't want these in the master history either as is, or rebased.(on the other hand if feature consists of logically separated steps, it may be better to leave them separate without squashing - though perhaps this means we needed separate merges properly)
Hi,
Thanks for the feedback. I'm preparing a next part which focuses on the features of interactive rebase. Squash will be part of that.