Simon's Musings

February 17, 2010

Git Tip 2: Splitting up existing changes

Filed under: Uncategorized — sxw @ 5:31 pm
Tags:

Today’s tip is pretty clearly spelled out in the manpage for git-rebase. But I find it so useful, I thought I would highlight it here.

From time to time, you end up with a patchset in your history that contains more than it should. It may be that it contains files (or chunks) that have been added incorrectly, or that a review comment has suggested would be better split into multiple changes. Git’s all purpose rewriter of history – git rebase – can help with doing this.

git rebase is a fantastic tool which can let you completely change the history of your project at the drop of a hat. I’ll be writing more about it in tips to come. As with all powerful tools, you need to use its power wisely. In effect, rebasing doesn’t rewrite your history, but creates an entirely new timeline, starting at some common point in the past. If you are working on a personal repository, then this isn’t an issue. If you are sharing your repository, you should think very carefully about rebasing it as your collaborators will have based their work on the old tip of your tree. When you rebase, you create a new branch, with a new tip, of which your collaborators will be completely unaware.

How to split a change is described in detail in the git rebase manpage, so we’ll just recap it here.

  • Find the SHA1 hash of the change you wish to split – this is probably easiest done by running
    git log –oneline
  • Start up an interactive rebase, with the start point being the parent of the commit you wish to split. The git notation HASH^ – for exampledeadbeef^ will give you the parent of a commit. So, run:
    git rebase -i HASH^
  • In the editor window that appears replace the word pick that appears beside the change you are picking with edit. This instructs git to stop the rebase operation at this point, and to allow you to modify this change.
  • Save the file, and exit your editor. Git will now start the rebase operation.
  • When it reaches the change you are modifying, git will pause the rebase, and return control. You can now modify this
    change – make a note of the SHA1 id it has stopped at, as this will come in handy later!
  • git reset HEAD^ will reset the index to the state of the parent commit. This gives you a working tree that contains the contents of the change you are splitting.
  • Use git add, and git commit to create as many commits as you wish from this tree. If you want your original commit message, then using git commit -C HASH will commit the current index, using the same message as that in HASH.
  • When you’re done, and have committed all of the fragments, use git rebase –continue to resume the rebasing process

Providing all goes well, you’ll end up with a modified history, and a change that has been split into multiple parts. You’ll note that every change after the split now has a new SHA1 – to git, these are completely new changes, as they have a different history, and this is the whole reason why rebases can be dangerous.

February 16, 2010

Git tip of the day #1

Filed under: Uncategorized — sxw @ 9:24 am
Tags:

This is the first of an occasional series of helpful hints and tips for the git revision control system – look for articles tagged with ‘git’

Cleaning your local commits

Many of the projects I submit to are picky about both trailing, and embedded, whitespace. git show and git diff will let you see these and if you are pulling in a patchset from elsewhere, git apply --whitespace=fix will tidy them up for you. But, I’d always thought that doing it in your own tree was harder. However …

git rebase -f --whitespace=fix origin/master

… will rebase your current working tree (assuming that the branch point was origin/master), and also clean up any embeded whitespace problems along the way. Obviously this has all of the caveats that rebasing carries – you don’t want to do it on a tree that others are working from. But as a way of cleaning up local changes before pushing them into gerrit, it’s remarkably useful.

Theme: Rubric.