git ready

learn git one commit at a time
by Nick Quaranto

intro to rebase

committed 31 Jan 2009

Git’s rebase command is hard to understand for newcomers, and the manpage’s description doesn’t help at all:

git-rebase – Forward-port local commits to the updated upstream head

Um, what? This is helpful if you know how Git works, but not at all if you’re just starting out. Thanks to Travis Swicegood, we have a better metaphor:

A cleaver. Rebase helps to cut up commits and slice them into any way that you want them served up, and placed exactly where you want them. You can actually rewrite history with this command, be it reordering commits, squashing them into bigger ones, or completely ignoring them if you so desire.

Why is this helpful? One of the most common use cases is that you’ve been working on your own features/fixes/etc in separate branches. Instead of creating ugly merge commits for every change that is brought back into the master branch, you could create one big commit and let rebase handle attaching it. Another frequent use of rebase is to pull in changes from a project and keep your own modifications in line. Usually by doing merges, you’ll end up with a history in which commits are interleaved between upstream and your own. Doing a rebase prevents this and keeps the order in a more sane state. For some examples of how this looks graphically, visit the end of Git for Computer Scientists or James Bowes’ post on the subject.

So let’s go through a simple example of using rebase. I’m going to check out a new branch for my feature, and hack on it for a bit, and commit my changes.

$ git checkout -b newfeature 
Switched to a new branch "newfeature"

[.. changed some files, made a few commits ..]

$ git checkout master
Switched to branch "master"

[.. changed one file, committed ..]

So right now, our history looks like this (screenshots taken from gitx):

Now I want to bring the changes back into the master branch. Now, from here I could merge my changes in with git merge newfeature. If I did that, here’s how the commit history would look:

If we did a git rebase newfeature instead, our commit history would look like:

So you can see how it ends up a lot cleaner and compact. Since these changes were relatively simple, merging was really simple and didn’t require any work to do. Future tips will cover resolving merge problems, the different merging algorithms available, and of course rebase’s interactive mode. This post was meant mostly for getting the basics down of what the command does. If you have any neat tricks that you usually do with rebase, submit a tip!