Using git to borrow from the future

One of the great features of git is the ability to re-order commits, break commits into parts, and merge commits together.

Assuming that my master branch is a pristine copy of the site and an ancestor of mybranch we can re-order commits by running:

git rebase -i master

This will take all the commits in your current branch (mybranch) that are built upon master and allow you to reorder or edit them individually, remove them or squash them.

For example you might get:

pick 123abcd New feature supreme
pick 123abce Whitepsace fixes
pick 2222222 Rename functions.
pick 123abcf rebase me

The last commit listed is the latest commit and is where mybranch’s HEAD points to.

You can edit this like so:

pick 123abce Whitepsace fixes
pick 2222222 Rename functions.
pick 123abcd New feature supreme
f 123abcf rebase me

This will re-order history so the first three items happen and the “rebase me” commit just gets rolled into the “New feature supreme”. Note since this is a rebase the commit hashes will change. Let’s say history is now this (reverse chronological):

323abcd New feature supreme
3222222 Rename functions.
323abce Whitepsace fixes

Great? Almost.

There’s a likely hood that your apps’ unit tests will not pass after the commit “Rename functions”. Some functions may have been renamed somewhere later in mybranch possibly in “rebase me” which is now a part of “New feature supreme.”

This is a mess, but we can run git rebase -i master again and edit the “Rename functions.” commit. If you run a test-suite and things fail you can “borrow from the future”. You see at this point Rename functions is something that happened in the past. mybranch’s head is now New feature supreme which is the future. We can pick and choose little changes with some git-fu.

While rebasing in the Rename functions. we might notice that we forgot to rename a call, but we remembered to rename this call at some point in mybranch. We can simply do this:

git checkout -p mybranch [paths]

This will let you interactively select chunks of code from the head of mybranch and put it into your specific commit Rename functions..

You can narrow this down by specifying some paths.

Once we finish rebasing we’ll have a commit history that is logically ordered and have all tests passing tests.