Let us say that you are working on an application that is similar to Reddit, but specifically for code snippets. In such an application, you would likely have a
master branch which contains all the released features, a
dev branch which might contain features that have been coded, but not implemented yet. Every developer in the team will create his own branches off the
dev branch for individual features. The repository structure would look something like this:
--- Commit 3 --------- dev branch / --- Commit 1 ---- Commit 2 ---------------------------- master branch
If you decided to merge the 3rd commit (
Commit 3) into the
master branch from the
dev branch, then it would be as simple as running a
git merge command because the
dev branch is up-to-date with the
master branch: all of the commits in the
master branch exist in the
dev branch. You can merge the branches by running the following commands:
git checkout dev git merge master
The result would be something like this:
--------- dev branch / --- Commit 1 ---- Commit 2 ---- Commit 3 -------------- master branch
Now you decide to work on the authentication feature. To work on the authentication feature, you create another branch based on the
dev branch and decide to call it
auth. This is what the repo structure looks like:
------ auth branch / --------- dev branch / --- Commit 1 ---- Commit 2 ---- Commit 3 -------------- master branch
If you were to commit any changes to the
auth branch, merging them with the
dev branch would be trivial because it is up-to-date with the
dev branch. Now while you were working away on the authentication feature, one of the developers finished coding the syntax-highlighting feature, and decided to merge it with the
dev branch. The repo looks like this now:
--- Commit 5 --- auth branch / --- Commit 4 ------ dev branch / --- Commit 1 ---- Commit 2 ---- Commit 3 ------------------------ master branch
Your branch, in Git terminology, is now a commit behind the
dev branch. This means that you cannot simply merge the two branches: you must bring your
auth branch up-to-date with the
dev branch. This can be done with
auth branch with the
dev branch, or the
dev branch with the
master branch is straightforward and does what you expect, but merging the other way around has its own idiosyncrasies that are not intuitive at first blush. I can babble about it, or I can show you another great diagram of what would happen if you merged the
dev branch with the
auth branch at this moment:
--- Commit 5 ----------- auth branch / / --- Commit 4 -------------- dev branch / --- Commit 1 ---- Commit 2 ---- Commit 3 -------------------------------- master branch
See what I did there? Look at the diagram for a second and try to understand what is happening here before you move on. You essentially made another commit to the
auth branch with the commits in the
dev branch included. But that’s all right, right? After all, at the end of the day I wanted to bring my
auth branch up-to-date with the
dev branch, and now it is up-to-date? Yep. But let me show you a diagram to explicitly illustrate what the other diagram implies: Your
auth branch now looks like this:
--- Commit 5 ------- Commit 4 ------- auth branch / / ------ Commit 4 --- --------------------- dev branch
See it now? You copied the commit over. If you were to merge to the
dev branch now, it would look something like this:
--- Commit 5 ------- Commit 4 -------------------------------------- auth branch / / \ ------- Commit 4 ----------------------- Commit 5 ---- Commit 4 -------- dev branch
You merged the same commit twice! This will of course have no repercussions for your code itself, but if you one fine day decide to look at your
git logs, you will immediately realize how dirty your git history is, with some commits being made over and over. If you wanted to revert to a commit, it would be very difficult to decide which commit to revert to.
git merge command will merge any changes that were made to the code base on a separate branch to your current branch.
The command syntax is as follows:
git merge BRANCH-NAME
For example, if you are currently working in a branch named
dev and would like to merge any new changes that were made in a branch named
new-features , you would issue the following command:
git merge new-features
Please Note: If there are any uncommitted changes on your current branch, Git will not allow you to merge until all changes in your current branch have been committed. To handle those changes, you can either:
- Create a new branch and commit the changes
git checkout -b new-branch-name git add . git commit -m "<your commit message>"
- Stash them
git stash # add them to the stash git merge new-features # do your merge git stash pop # get the changes back into your working tree
- Abandon it all
git reset --hard # removes all pending changes
A merge conflict is when you make commits on separate branches that alter the same line in conflicting ways. Therefore Git will not know which version of the file to keep
resulting in the error message:
CONFLICT (content): Merge conflict in resumé.txt Automatic merge failed; fix conflicts and then commit the result.
In the code editor Git uses markings to indicate the HEAD (master) version of the file and the other version of the file.
From the code editor delete/update to resolve conflict and remove the special markings including the HEAD and OTHER file names, reload your file, then re add and recommit your changes.
Points to Note
Whenever a merge is done, an extra merge commit is created. Whenever you are working in your local repository, having too many merge commits can make the commit history look confusing. One way to avoid the merge commit is to use git rebase instead. Git rebase is covered in the git-rebase section.
Rebase is a great functionality but it has some issues as well. Rebase basically alters the commit history. So if rebase is used in the remote repository then it can create a lot of confusion. As much as possible, run rebase only on a local repository.
Both git merge and git rebase are very useful commands and one is not better than the other.