Monday, October 5, 2009

Splitting patches with git

Continuing on my trend of learning new things with git, I've now learned how to split already committed patches into multiple sub-patches. I'll explain that here, along with some cool other commands I learned along the way.

First, the concept for splitting patches is fairly well explained in the man page for rebase (man git-rebase, search for "SPLITTING COMMITS"). Basically, you start an interactive rebase (git rebase -i), then mark the commit you want to split with "edit". When the rebase hits that point, it will stop and allow you to modify things. The important point is that at an interactive rebase point, you can add as many (or as few) commits as you want before resuming the rebase. This is what makes splitting commits possible.

Now you should run "git reset HEAD^", which will put your source tree in a state right *before* the current commit would have been applied, and then applies the current commit. It's equivalent to checking out the changeset right before this commit, and then applying the current commit by hand (with, patch -p1). With this in place, you can now use "git add -p" to add hunks of patches into particular commits. Again, the man page for "git-add" explains this pretty well, but using the -p flag makes "git add" interactive and allows you to choose, hunk-by-hunk, which hunks of patches you want in the current commit. It even has this really cool feature called "s", where it will split patch hunks into smaller patch hunks for you.

Once you've git add'ed all of the hunks for the current commit, commit it with "git commit -s". You can repeat the git-add/git-commit cycle as many times as you want, creating a number of different commits. Once you've split up your commit how you like it, you just run "git rebase --continue" to continue the rebase, and you are on your way!

UPDATE: fixed up bogus reference to git rebase HEAD^; it should have read git reset HEAD^