Git Rebasing

For me, ‘git rebase -i’ is perhaps git’s killer feature. I’m a big fan of small, self-contained commits both for ease of patch review and for the sake of useful commit history later. I used to do this on CVS using quilt but git takes a huge amount of the pain out of it.

Ever since I discovered the feature a few years ago, I’ve also been vaguely aware of kernel developers advice to people on rebase … often simplified to OMG no. Never rebase..

When pushed to elaborate, I guess most would say:

Once you share a commit with someone, never rebase it. They may base their work on your commit and by rebasing it, you’re screwing everything up.

One memorable comment from Linus on the subject was “Have the f*cking back-bone to be able to stand behind what you did!”.

In context, this all makes sense. If a kernel developer sends a pull request and it gets merged into one tree, then rebases and that gets merged into another tree and both get merged into Linus’s tree … then yes, you have a bit of a disaster on your hands.

However, I think the rules above are too simplistic for most git newbies. Such newbies are unlikely to see their trees pulled into the whirling vortex of kernel trees so there’s no need to terrify them about using rebase.

My advice is:

  1. If you’re learning git, take the time to understand the rebase command and, especially, the interactive option.
  2. If you’re working on a series of patches, it’s perfectly fine for you to share that series with others even if it’s not finished. That means later rebasing a commit you’ve shared with others.
  3. If you’re worried people might base their work on a commit you plan to rebase later, then you warn people by putting e.g. “v1”, “rebases” or “rebasing” in the repository or branch name.
  4. If someone does base their work on a commit you have rebased, then point them at the Recovering From Upstream Rebase part of git-rebase(1). It’s really not the end of the world, especially in the simpler cases.

5 thoughts on “Git Rebasing”

  1. Hey Mark… funny you post on this very topic… I’m a git newbie (as you know) and I got burned by this only recently (someone else rebasing pushed work).

    Seems to me that rebase is totally safe (and incredibly useful) if you haven’t already pushed the changes i.e. {commit, commit, commit… rebase -i, push} is totally safe.

    Once pushed into the wild, only ever change that pushed commit history (i.e. rebase) if you’re totally sure that commit history has not been pulled anywhere else… but be very very sure 🙂

  2. Okay, so a git newbie got screwed by someone rebasing a commit that the newbie had based work on. Not a fun situation, I grant you.

    I guess there’s a two way responsibility here – before basing your work on someone’s branch or repo, you should be confident they’re not going to rebase it or that you can easily recover if they do.

  3. At Tracker we allow rebasing in feature branches, but of course no rebasing in master. Teams that share a branch usually self-organize. So if such a team wants to screw itself by pushing a rebase, then usually self-organization makes people notify the others about a pending rebase.

    The server doesn’t allow rebasing so a rebase means deleting a branch and recreating it of course. We often have feature-name as branch-name and then a feature-name-rebased or feature-name-merge which then is the final version of the branch ready for review and later push to master.

    A review of many small commits means that within a commit change-requests by the reviewer sometimes exists. Ie. reviewer says: you have forgotten a free() at line X. So then we commit the free(), and we rebase-i and squash with the commit where the mistake was made. Hurray for rebase-i.

    We actually even strongly recommend rebase before merge to master. With all the commits of one feature grouped together this helps us with bisecting. Yet we don’t always want very big commits implementing the whole feature. The smaller the commits the easier the review and the easier it is to revert parts of a feature. And to understand the (progression of) changes.

    Unfortunate is that the date of a commit changes with the rebasing, though. Ideally it would be easy for the feature-developer to change these dates at for example interactive rebasing mode. Perhaps have a “commit date” and a “authored date”. Maybe I’m just insane?



Comments are closed.