The only differences between a rebase and a merge are:
The resulting tree structure of the history (generally only noticeable when looking at a commit graph) is different (one will have branches, the other won't).
Merge will generally create an extra commit (e.g. node in the tree).
Merge and rebase will handle conflicts differently. Rebase will present conflicts one commit at a time where merge will present them all at once.
So the short answer is to pick rebase or merge based on what you want your history to look like.
Long Answer
There are a few factors you should consider when choosing which operation to use.
Is the branch you are getting changes from shared with other developers outside your team (e.g. open source, public)?
If so, don't rebase. Rebase destroys the branch and those developers will have broken/inconsistent repositories unless they use git pull --rebase. This is a good way to upset other developers quickly.
How skilled is your development team?
Rebase is a destructive operation. That means, if you do not apply it correctly, you could lose committed work and/or break the consistency of other developer's repositories.
I've worked on teams where the developers all came from a time when companies could afford dedicated staff to deal with branching and merging. Those developers don't know much about Git and don't want to know much. In these teams I wouldn't risk recommending rebasing for any reason.
Does the branch itself represent useful information
Some teams use the branch-per-feature model where each branch represents a feature (or bugfix, or sub-feature, etc.) In this model the branch helps identify sets of related commits. For example, one can quickly revert a feature by reverting the merge of that branch (to be fair, this is a rare operation). Or diff a feature by comparing two branches (more common). Rebase would destroy the branch and this would not be straightforward.
I've also worked on teams that used the branch-per-developer model (we've all been there). In this case the branch itself doesn't convey any additional information (the commit already has the author). There would be no harm in rebasing.
Might you want to revert the merge for any reason?
Reverting (as in undoing) a rebase is considerably difficult and/or impossible (if the rebase had conflicts) compared to reverting a merge. If you think there is a chance you will want to revert then use merge.
Do you work on a team? If so, are you willing to take an all or nothing approach on this branch?
Rebase operations need to be pulled with a corresponding git pull --rebase. If you are working by yourself you may be able to remember which you should use at the appropriate time. If you are working on a team this will be very difficult to coordinate. This is why most rebase workflows recommend using rebase for all merges (and git pull --rebase for all pulls).
Common Myths
Merge destroys history (squashes commits)
Assuming you have the following merge:
B -- C
/ \
A--------D
Some people will state that the merge "destroys" the commit history because if you were to look at the log of only the master branch (A -- D) you would miss the important commit messages contained in B and C.
If this were true we wouldn't have questions like this. Basically, you will see B and C unless you explicitly ask not to see them (using --first-parent). This is very easy to try for yourself.
Rebase allows for safer/simpler merges
The two approaches merge differently, but it is not clear that one is always better than the other and it may depend on the developer workflow. For example, if a developer tends to commit regularly (e.g. maybe they commit twice a day as they transition from work to home) then there could be a lot of commits for a given branch. Many of those commits might not look anything like the final product (I tend to refactor my approach once or twice per feature). If someone else was working on a related area of code and they tried to rebase my changes it could be a fairly tedious operation.
Rebase is cooler / sexier / more professional
If you like to alias rm to rm -rf to "save time" then maybe rebase is for you.
My Two Cents
I always think that someday I will come across a scenario where git rebase is the awesome tool that solves the problem. Much like I think I will come across a scenario where git reflog is an awesome tool that solves my problem. I have worked with git for over five years now. It hasn't happened.
Messy histories have never really been a problem for me. I don't ever just read my commit history like an exciting novel. A majority of the time I need a history I am going to use git blame or git bisect anyways. In that case having the merge commit is actually useful to me because if the merge introduced the issue that is meaningful information to me.
Update (4/2017)
I feel obligated to mention that I have personally softened on using rebase although my general advice still stands. I have recently been interacting a lot with the Angular 2 Material project. They have used rebase to keep a very clean commit history. This has allowed me to very easily see what commit fixed a given defect and whether or not that commit was included in a release. It serves as a great example of using rebase correctly.
While merging is definitely the easiest and most common way to integrate changes, it's not the only one: Rebase is an alternative means of integration.
Understanding Merge a Little Better
When Git performs a merge, it looks for three commits:
(1) Common ancestor commit If you follow the history of two branches in a project, they always have at least one commit in common: at this point in time, both branches had the same content and then evolved differently.
(2) + (3) Endpoints of each branch The goal of an integration is to combine the current states of two branches. Therefore, their respective latest revisions are of special interest.
Combining these three commits will result in the integration we're aiming for.
Fast-Forward or Merge Commit
In very simple cases, one of the two branches doesn't have any new commits since the branching happened - its latest commit is still the common ancestor.
In this case, performing the integration is dead simple: Git can just add all the commits of the other branch on top of the common ancestor commit. In Git, this simplest form of integration is called a "fast-forward" merge. Both branches then share the exact same history.
In a lot of cases, however, both branches moved forward individually.
To make an integration, Git will have to create a new commit that contains the differences between them - the merge commit.
Human Commits & Merge Commits
Normally, a commit is carefully created by a human being. It's a meaningful unit that wraps only related changes and annotates them with a comment.
A merge commit is a bit different: instead of being created by a developer, it gets created automatically by Git. And instead of wrapping a set of related changes, its purpose is to connect two branches, just like a knot. If you want to understand a merge operation later, you need to take a look at the history of both branches and the corresponding commit graph.
Integrating with Rebase
Some people prefer to go without such automatic merge commits. Instead, they want the project's history to look as if it had evolved in a single, straight line. No indication remains that it had been split into multiple branches at some point.
Let's walk through a rebase operation step by step. The scenario is the same as in the previous examples: we want to integrate the changes from branch-B into branch-A, but now by using rebase.
We will do this in three steps
git rebase branch-A // syncs the history with branch-A
git checkout branch-A // change the current branch to branch-A
git merge branch-B // merge/take the changes from branch-B to branch-A
First, Git will "undo" all commits on branch-A that happened after the lines began to branch out (after the common ancestor commit). However, of course, it won't discard them: instead you can think of those commits as being "saved away temporarily".
Next, it applies the commits from branch-B that we want to integrate. At this point, both branches look exactly the same.
In the final step, the new commits on branch-A are now reapplied - but on a new position, on top of the integrated commits from branch-B (they are re-based).
The result looks like development had happened in a straight line. Instead of a merge commit that contains all the combined changes, the original commit structure was preserved.
Finally you get a clean branch branch-A with no unwanted and auto generated commits.
Note: Taken from the awesome post by git-tower. The disadvantages of rebase is also a good read in the same post.
The pro git book as a really good explanation on the rebasing page.
Basically a merge will take 2 commits and combine them.
A rebase will go to the common ancestor on the 2 and incrementally apply the changes on top of each other. This makes for a 'cleaner' and more linear history.
But when you rebase you abandon previous commits and create new ones. So you should never rebase a repo that is public. The other people working on the repo will hate you.
For that reason alone I almost exclusively merge. 99% of the time my branches don’t differ that much, so if there are conflicts it's only in one or two places.
A lot of answers here say that merging turns all your commits into one, and therefore suggest to use rebase to preserve your commits. This is incorrect. And a bad idea if you have pushed your commits already.
Merge does not obliterate your commits. Merge preserves history! (just look at gitk) Rebase rewrites history, which is a Bad Thing after you've pushed it.
Use merge -- not rebase whenever you've already pushed.
provides an incorrect idea of how commits were created
pollutes master with a bunch of intermediate commits that may not have been well tested
could actually introduce build breaks on these intermediate commits because of changes that were made to master between when the original topic branch was created and when it was rebased.
makes finding good places in master to checkout difficult.
Causes the timestamps on commits to not align with their chronological order in the tree. So you would see that commit A precedes commit B in master, but commit B was authored first. (What?!)
Produces more conflicts because individual commits in the topic branch can each involve merge conflicts which must be individually resolved (Further lying in history about what happened in each commit).
is a rewrite of history. If the branch being rebased has been pushed anywhere (shared with anyone other than yourself) then you've screwed up everyone else who has that branch since you've rewritten history.
In contrast, merging a topic branch into master:
preserves history of where topic branches were created, including any merges from master to the topic branch to help keep it current. You really get an accurate idea of what code the developer was working with when they were building.
master is a branch made up mostly of merges, and each of those merge commits are typically 'good points' in history that are safe to check out because that's where the topic branch was ready to be integrated.
all the individual commits of the topic branch are preserved, including the fact that they were in a topic branch, so isolating those changes is natural and you can drill in where required.
merge conflicts only have to be resolved once (at the point of the merge) so intermediate commit changes made in the topic branch don't have to be resolved independently.
can be done multiple times smoothly. If you integrate your topic branch to master periodically, folks can keep building on the topic branch and it can keep being merged independently.
In general the way to get the best of both worlds is to rebase local
changes you’ve made but haven’t shared yet before you push them in
order to clean up your story, but never rebase anything you’ve pushed
somewhere.
TL;DR
If you have any doubt, use merge.
Short Answer
The only differences between a rebase and a merge are:
So the short answer is to pick rebase or merge based on what you want your history to look like.
Long Answer
There are a few factors you should consider when choosing which operation to use.
Is the branch you are getting changes from shared with other developers outside your team (e.g. open source, public)?
If so, don't rebase. Rebase destroys the branch and those developers will have broken/inconsistent repositories unless they use
git pull --rebase
. This is a good way to upset other developers quickly.How skilled is your development team?
Rebase is a destructive operation. That means, if you do not apply it correctly, you could lose committed work and/or break the consistency of other developer's repositories.
I've worked on teams where the developers all came from a time when companies could afford dedicated staff to deal with branching and merging. Those developers don't know much about Git and don't want to know much. In these teams I wouldn't risk recommending rebasing for any reason.
Does the branch itself represent useful information
Some teams use the branch-per-feature model where each branch represents a feature (or bugfix, or sub-feature, etc.) In this model the branch helps identify sets of related commits. For example, one can quickly revert a feature by reverting the merge of that branch (to be fair, this is a rare operation). Or diff a feature by comparing two branches (more common). Rebase would destroy the branch and this would not be straightforward.
I've also worked on teams that used the branch-per-developer model (we've all been there). In this case the branch itself doesn't convey any additional information (the commit already has the author). There would be no harm in rebasing.
Might you want to revert the merge for any reason?
Reverting (as in undoing) a rebase is considerably difficult and/or impossible (if the rebase had conflicts) compared to reverting a merge. If you think there is a chance you will want to revert then use merge.
Do you work on a team? If so, are you willing to take an all or nothing approach on this branch?
Rebase operations need to be pulled with a corresponding
git pull --rebase
. If you are working by yourself you may be able to remember which you should use at the appropriate time. If you are working on a team this will be very difficult to coordinate. This is why most rebase workflows recommend using rebase for all merges (andgit pull --rebase
for all pulls).Common Myths
Merge destroys history (squashes commits)
Assuming you have the following merge:
Some people will state that the merge "destroys" the commit history because if you were to look at the log of only the master branch (A -- D) you would miss the important commit messages contained in B and C.
If this were true we wouldn't have questions like this. Basically, you will see B and C unless you explicitly ask not to see them (using --first-parent). This is very easy to try for yourself.
Rebase allows for safer/simpler merges
The two approaches merge differently, but it is not clear that one is always better than the other and it may depend on the developer workflow. For example, if a developer tends to commit regularly (e.g. maybe they commit twice a day as they transition from work to home) then there could be a lot of commits for a given branch. Many of those commits might not look anything like the final product (I tend to refactor my approach once or twice per feature). If someone else was working on a related area of code and they tried to rebase my changes it could be a fairly tedious operation.
Rebase is cooler / sexier / more professional
If you like to alias
rm
torm -rf
to "save time" then maybe rebase is for you.My Two Cents
I always think that someday I will come across a scenario where git rebase is the awesome tool that solves the problem. Much like I think I will come across a scenario where git reflog is an awesome tool that solves my problem. I have worked with git for over five years now. It hasn't happened.
Messy histories have never really been a problem for me. I don't ever just read my commit history like an exciting novel. A majority of the time I need a history I am going to use git blame or git bisect anyways. In that case having the merge commit is actually useful to me because if the merge introduced the issue that is meaningful information to me.
Update (4/2017)
I feel obligated to mention that I have personally softened on using rebase although my general advice still stands. I have recently been interacting a lot with the Angular 2 Material project. They have used rebase to keep a very clean commit history. This has allowed me to very easily see what commit fixed a given defect and whether or not that commit was included in a release. It serves as a great example of using rebase correctly.
While merging is definitely the easiest and most common way to integrate changes, it's not the only one: Rebase is an alternative means of integration.
Understanding Merge a Little Better
When Git performs a merge, it looks for three commits:
Fast-Forward or Merge Commit
In very simple cases, one of the two branches doesn't have any new commits since the branching happened - its latest commit is still the common ancestor.
In this case, performing the integration is dead simple: Git can just add all the commits of the other branch on top of the common ancestor commit. In Git, this simplest form of integration is called a "fast-forward" merge. Both branches then share the exact same history.
In a lot of cases, however, both branches moved forward individually.
To make an integration, Git will have to create a new commit that contains the differences between them - the merge commit.
Human Commits & Merge Commits
Normally, a commit is carefully created by a human being. It's a meaningful unit that wraps only related changes and annotates them with a comment.
A merge commit is a bit different: instead of being created by a developer, it gets created automatically by Git. And instead of wrapping a set of related changes, its purpose is to connect two branches, just like a knot. If you want to understand a merge operation later, you need to take a look at the history of both branches and the corresponding commit graph.
Integrating with Rebase
Some people prefer to go without such automatic merge commits. Instead, they want the project's history to look as if it had evolved in a single, straight line. No indication remains that it had been split into multiple branches at some point.
Let's walk through a rebase operation step by step. The scenario is the same as in the previous examples: we want to integrate the changes from branch-B into branch-A, but now by using rebase.
We will do this in three steps
git rebase branch-A // syncs the history with branch-A
git checkout branch-A // change the current branch to branch-A
git merge branch-B // merge/take the changes from branch-B to branch-A
First, Git will "undo" all commits on branch-A that happened after the lines began to branch out (after the common ancestor commit). However, of course, it won't discard them: instead you can think of those commits as being "saved away temporarily".
Next, it applies the commits from branch-B that we want to integrate. At this point, both branches look exactly the same.
In the final step, the new commits on branch-A are now reapplied - but on a new position, on top of the integrated commits from branch-B (they are re-based). The result looks like development had happened in a straight line. Instead of a merge commit that contains all the combined changes, the original commit structure was preserved.
Finally you get a clean branch branch-A with no unwanted and auto generated commits.
Note: Taken from the awesome post by
git-tower
. The disadvantages ofrebase
is also a good read in the same post.before merge/rebase:
after
git merge master
:after
git rebase master
:(A, B, C, D, E and F are commits)
this example and much more well illustrated info about git can be found here: http://excess.org/article/2008/07/ogre-git-tutorial/
The pro git book as a really good explanation on the rebasing page.
Basically a merge will take 2 commits and combine them.
A rebase will go to the common ancestor on the 2 and incrementally apply the changes on top of each other. This makes for a 'cleaner' and more linear history.
But when you rebase you abandon previous commits and create new ones. So you should never rebase a repo that is public. The other people working on the repo will hate you.
For that reason alone I almost exclusively merge. 99% of the time my branches don’t differ that much, so if there are conflicts it's only in one or two places.
A lot of answers here say that merging turns all your commits into one, and therefore suggest to use rebase to preserve your commits. This is incorrect. And a bad idea if you have pushed your commits already.
Merge does not obliterate your commits. Merge preserves history! (just look at gitk) Rebase rewrites history, which is a Bad Thing after you've pushed it.
Use merge -- not rebase whenever you've already pushed.
Here is Linus' (author of git) take on it. It's a really good read. Or you can read my own version of the same idea below.
Rebasing a branch on master:
In contrast, merging a topic branch into master:
This sentence gets it:
Source: http://www.git-scm.com/book/en/v2/Git-Branching-Rebasing#Rebase-vs.-Merge