One of the most important features of GIT is branching. The development of multiple functionalities can be done parallelly, 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 need 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). In 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.