Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Consider the following situation:

  • You have a clone of a git repository
  • You have some local commits (commits that have not yet been pushed anywhere)
  • The remote repository has new commits that you have not yet reconciled

So something like this:

Unmerged commits

If you execute git pull with the default settings, you'll get something like this:

merge commit

This is because git performed a merge.

There's an alternative, though. You can tell pull to do a rebase instead:

git pull --rebase

and you'll get this:

rebased

In my opinion, the rebased version has numerous advantages that mostly center around keeping both your code and the history clean, so I'm a little struck by the fact that git does the merge by default. Yes, the hashes of your local commits will get changed, but this seems like a small price to pay for the simpler history you get in return.

By no means am I suggesting that this is somehow a bad or a wrong default, though. I am just having trouble thinking of reasons why the merge might be preferred for the default. Do we have any insight into why it was chosen? Are there benefits that make it more suitable as a default?

The primary motivation for this question is that my company is trying to establish some baseline standards (hopefully, more like guidelines) for how we organize and manage our repositories to make it easier for developers to approach a repository they haven't worked with before. I am interested in making a case that we should usually rebase in this type of situation (and probably for recommending developers set their global config to rebase by default), but if I were opposed to that, I would certainly be asking why rebase isn't the default if it's so great. So I'm wondering if there is something I'm missing.

It has been suggested that this question is a duplicate of Why do so many websites prefer “git rebase” over “git merge”?; however, that question is somewhat the reverse of this one. It discusses the merits of rebase over merge, while this question asks about the benefits of merge over rebase. The answers there reflect this, focusing on problems with merge and benefits of rebase.

share|improve this question
6  
    
The other problem is that if you accidentally commit to master, then do a pull which merged, the two masters can be out of sync even though the merge looks normal. This is why my pull alias includes --ff-only. – Ixrec Jan 11 at 10:14
    
if sourcetree ever changes its graph view so it displays rebases/merges differently, will you switch to merging? – Ewan Jan 11 at 15:42
1  
@Ewan SourceTree shouldn't change its graph view of this. It accurately represents the graph. – jpmc26 Jan 11 at 19:56
4  
For dupe voters, please note that the content in the answer I accepted is most definitely not present in the question you're claiming is a duplicate. – jpmc26 Jan 12 at 3:28
up vote 46 down vote accepted

It is hard to know for sure why merge is the default without hearing from the person who made that decision.

Here is a theory...

Git cannot presume it is ok to --rebase every pull. Listen to how that sounds. "Rebase every pull." just sounds wrong if you use pull requests or similar. Would you rebase on a pull request?

In a team that is not just using Git for centralized source control...

  • You may pull from upstream and from downstream. Some people do a lot of pulling from downstream, from contributors, etc.

  • You may work on features in close collaboration with other developers, pulling from them or from a shared topic branch and still occasionally updated from upstream. If you always rebase then you end up changing shared history, not to mention fun conflict cycles.

Git was designed for a large highly distributed team where everyone does not pull and push to a single central repo. So the default makes sense.

  • Developers who do not know when it's ok to rebase will merge by default.
  • Developers can rebase when they want to.
  • Commiters who do a lot of pulls and have a lot of pull get the default that suits them best.

For evidence of intent, here's a link to a well known email from Linus Torvalds with his views on when they should not rebase. Dri-devel git pull email

If you follow the whole thread you can see that one developer is pulling from another developer and Linus is pulling from both of them. He makes his opinion pretty clear. Since he probably decided Git's defaults, this might explain why.

A lot of people now use Git in a centralized way, where everyone in a small team pulls only from an upstream central repo and pushes to that same remote. This scenario avoids some of the situations where a rebase is not good, but usually does not eliminate them.

Suggestion: Don't make a policy of changing the default. Any time you put Git together with a big group of developers some of the developers won't understand Git all that deeply (myself included). They will go to Google, SO, get cookbook advice and then wonder why some things don't work, e.g. why does git checkout --ours <path> get the wrong version of the file? You can always revise your local environment, make aliases, etc. to suit your taste.

share|improve this answer
5  
+1 for not changing the default - rather than rolling your own git workflow it's probably better to grab one that exists (e.g. any of the ones documented by Atlassian atlassian.com/git/tutorials/comparing-workflows/… ) – Rob Church Jan 11 at 13:17
    
Thanks for the answer. The info about pulling from downstream was what I was missing. Also, interestingly enough, the link you gave encourages exactly what I would like to achieve: "People can (and probably should) rebase their private trees (their own work)." – jpmc26 Jan 12 at 3:36
1  
@jpmc Great. Indeed. Rebasing private trees can keep a lot of distracting crud out of the shared history. I do it. It's the clarity on when not to do it that's important. – joshp Jan 12 at 4:06

If you read the git manpage for rebase, it says:

Rebasing (or any other form of rewriting) a branch that others have based work on is a bad idea: anyone downstream of it is forced to manually fix their history. This section explains how to do the fix from the downstream’s point of view. The real fix, however, would be to avoid rebasing the upstream in the first place.

I think that says it well enough as a reason not to use rebase at all, let alone automatically do it for every pull. Some people consider rebase to be harmful. Perhaps it should never have been put into git at all, as all it appears to do is prettify the history, something that shouldn't be necessary in any SCM whose single essential job is to preserve history.

When you say 'keeping ... the history clean', think you're wrong. It may look nicer, but for a tool that is designed to keep history of revisions, it is much cleaner to keep every commit so you can see what happened. Sanitising the history afterwards is like polishing the patina away, making a rich antique look like a shiny repro :-)

share|improve this answer
2  
+9000, honestly, they should rewrite the graph display so rebasing is 'ugly' – Ewan Jan 11 at 15:41
3  
@Ewan IMHO "doesn't work but looks pretty" is something that should be solely reserved for the fashion industry not IT. IMHO git should remove it as it obviously encourages too many people to think style is more important than substance. – gbjbaanb Jan 11 at 16:03
4  
I would dispute your suggestion that keeping the history clean is useless. It's not. A repository history is intended for human consumption, and as such, there's a lot of value in making it readable. In my particular use case, we're even intending that non-developer Project Managers should be able to read the history. A clean history can only help with that, and it can help a new developer who has never seen the code base and has to dive in and fix a bug understand what happened in a particular area of code. – jpmc26 Jan 12 at 4:42
1  
@jpmc26 SCMs are there first and foremost to record your commits. If someone cannot read all the commits and work out what happened and needs them squashed into one, then you have problems that no amount of rebasing is going to solve. – gbjbaanb Jan 12 at 11:37
1  
Code exists first and foremost to be executed by a machine (possibly after being compiled). Applying you philosophy above, we would conclude that readability of the code doesn't matter because no amount of readability will solve the difficulty of understanding code. I never suggested that anything should be squashed. I am merely saying that a complex graph that diverges into a lot of crossing paths is difficult to follow, so it's worth investing a little into keeping your history fairly clean. Note also that a linear history is more conducive to leveraging git tools like blame and bisect. – jpmc26 Jan 23 at 21:12

You're correct, assuming you have only one local/changed repository. However, consider there being a second local PC, for example.

Once your local/modified copy is pushed somewhere else rebasing will screw up those copies. Of course, you could force pushing, but that quickly becomes complicated. What happens if one or more of these have another completely new commit?

As you can see, it's very situational, but the base strategy seems (to me) a lot more practical in non-special/collaboration cases.


A second difference: The merge strategy will keep a clear and time consistent structure. After rebases it's very likely that older commits might follow newer changes, making the whole history and its flow harder to understand.

share|improve this answer
    
"After rebases it's very likely that older commits might follow newer changes" -- that happens with merges too, though, which is why you (might) need the pretty graph to make sense of it. The time at which a commit was made might be long before the merge that brought it into this branch. – Steve Jessop Jan 12 at 15:33

The big reason is probably that the default behaviour should "just work" in public repos. Rebasing history that other people have already merged is going to cause them trouble. I know you're talking about your private repo, but generally speaking git doesn't know or care what's private or public, so the chosen default is going to be the default for both.

I use git pull --rebase quite a lot in my private repo, but even there it has a potential disadvantage, which is that the history of my HEAD no longer reflects the tree as I actually worked on it.

So for a big example, suppose that I always run tests and ensure they pass before doing a commit. This has less relevance after I do a git pull --rebase, because it is no longer true that the tree at each of my commits has passed the tests. As long as the changes don't interfere in any way, and the code I pull has been tested, then presumably it would pass the tests, but we don't know because I never tried it. If continuous integration is an important part of your workflow, then any kind of rebase in a repo that's being CIed is troubling.

I don't really mind this, but it does bother some people: they'd prefer that their history in git reflects the code they actually worked on (or perhaps by the time they push it, a simplified version of the truth after some use of "fixup").

I don't know whether this issue in particular is the reason that Linus chose to merge rather than rebasing by default. There could be other disadvantages I haven't encountered. But since he's not shy of expressing his opinion in code, I'm pretty sure it comes down to what he thinks is a suitable workflow for people who don't want to think about it too much (and especially those working in a public rather than a private repo). Avoiding parallel lines in the pretty graph, in favour of a clean straight line that doesn't represent the parallel development as it happened, is probably not his top priority even though it is yours :-)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.