Search code examples
gitgit-rebase

Why would I want to do git rebase?


I've seen lots of people talk about git rebase and what it does, e.g. Hg: How to do a rebase like git's rebase and people talk about what it achieves (gives linear history), e.g. here Git rebase loses history, then why rebase? But I can't fathom why you would want to do this.

It seems like a big expense, to go back and revise your commit history (which must surely involve some ugly merges with n-way conflicts). And I could imagine cases where it could be very misleading, (e.g. if two people solve the same problem in different ways, but the history doesn't show their work as having occurred in parallel; seems that could easily lead to criticism and resentment too in some high-pressure coding environments).

What you gain is an easier to understand, but incorrect, history graph. What makes that worth the effort?

Thanks in advance.


Solution

  • Rebase is most useful when pushing a single commit or a small number of commits developed in a short time frame (hours or minutes).

    Before pushing to a shared server, one must first pull the commits made to the origin's HEAD in the meantime—failing to do so would create a non-fast-forward push. In doing so, one can choose between a merge (git pull) or a rebase (git pull --rebase) operation. The merge option, while technically more appealing, creates an additional merge commit. For a small commit, the appearance of two commits per change actually makes the history less readable because the merge operation distracts from the commit's message.

    In a typical shared development tree, every developer ends up pushing to a shared branch by doing some variation of git pull; <resolve conflicts>; git push. If they are using git pull without --rebase, what happens is that almost every commit ends up being accompanied by a merge commit, even though no parallel development was really going on. This creates an intertwined history from what is in reality a linear sequence of commits. For this reason, git pull --rebase is a better option for small changes resulting from short development, while a merge is reserved for integration of long-lived feature branches.

    All this applies to rebasing local commits, or rebasing a short-lived feature branch shared by closely connected coworkers (sitting in the same room). Once a commit is pushed to a branch regularly followed by by others, it should never be rebased.