Code demo using git, part 2
Posted on Mon 17 October 2011 in Tools
In my first post about using Git for doing a code demo, I mentioned in passing that making local changes during the demo can mess things up. I thought I’d mentioned some more about cleaning up local changes.
The cherry-pick method
Cleaning up local changes when using the cherry-pick method is dead simple. Just run:
$ git reset --hard
$ git clean -fd
The first command effectively discards all unstaged modifications, restores deleted files and clears the staging area. The second command removes all untracked files, including directories thanks to the -d flag. (By the way, I assume you have a good .gitignore file so that no important files get removed by accident!)
The interactive rebase method
Resetting local changes, including newly added files, is done the same way as with the other method. However, if you have made local changes, then the rebase process has probably been aborted, and you are facing a message like the following one:
Aborting (2/3)
error: Your local changes to the following files would be overwritten by merge:
world.txt
Please, commit your changes or stash them before you can merge.
Could not apply fcf2240... Second part of the demo
The problem here is that git thinks that it is done with the second demo
commit already, despite the failure! Therefore, a
git rebase --continue
at this point (after cleaning up) tries to
apply the third demo commit, which is definitively not what you want!
An option is to use edit instead of reword in the interactive
rebase. That way, you can reset local changes all you want, and then
simply do git rebase --continue
to continue the demo. However, you
need to do git rebase --continue
in any case, so the simplicity of
the interactive rebase method as originally envisioned sort of
disappears…
Which method is best? - revisited
In the light of the possibly complications arising from local changes using the interactive rebase method, I’d lean towards the cherry-pick method! But perhaps we can automate it with a little script to make things simpler? Here’s one attempt (that mostly relies on git to do error-checking, so you might want to add some of that):
#!/bin/bash
set -o nounset
set -o errexit
if [[ $# -lt 1 ]]; then
echo "Please specify a demo template branch!"
exit 1
fi
branch=$1
bhead=$(git show -s --format=format:%H $branch)
mbase=$(git merge-base $bhead HEAD)
if [[ $mbase = $bhead ]]; then
echo "The demo template head is reachable from this branch. Please switch branch!"
exit 1
fi
for hash in $(git log --reverse --format=format:%H master..$branch); do
git show -s --format=format:"Applying %h (%s)..." $hash
echo "-- cleaning up..."
git reset --hard
git clean -fd
echo "-- cherry-picking..."
git cherry-pick $hash
echo
read -p "Press any key to continue..."
echo
done
(Note to self: Don’t store a script that removes untracked files in the directory where you test run the script! :-))
How does the script work? Well, first it checks that the head of the
specified demo template branch isn’t reachable from the current branch
head. If it is, then most likely the current branch is the demo
template branch. Next, it iterates over the list of commits in the demo
template branch (in order of oldest first, thus --reverse
). For each
commit, it performs some cleanup before cherry-picking the commit. Then
it waits for you to carry out the demo of that particular commit before
continuing. Simple, right?
A final note about the script: It assumes that the demo template branch is branched out from master. If that’s not the case, the demo ghost will hunt you. :-)