When using git, going back in history to examine the state of things at some previous commit is a really standard task. And as such, this is fairly easy to do, since in git each commit has a link to its parent, and the syntax has been optimised for precisely this sort of thing.
# Go back one commit
git checkout HEAD~
# Go back 5 commits
git checkout HEAD~5
But after doing this, going back to where you were, going forward in history, is much more difficult. Because while git commits have links to their parents, they know nothing of their children.
I’m sure there is a perfectly good reason for all of this somewhere, but I often feel like being able to move back and forth between some points in a project’s history. So I made myself a set of aliases1 to do just that.
You can find the definition of these aliases on GitLab.
Here’s how I use them:
Setting a reference point
In order to move forward in git, you need to be able to specify
a direction. This is done with
git save, which will store the
current position (the
HEAD) into a persistent storage2. You can
then see what you’ve saved with
Once you’ve saved a position, you can clear it with
or jump back to it with
git load. The trick here is that
can detect whether
HEAD was on a branch (in which case it stores the
name of the branch) or detached at some other point (in which case
it stores the commit SHA). So using
git load means you’ll go back
to being on the branch if that’s where you were when you used
Moving back and forth
With a reference point set, you can move back with
git back, which
will move you to the previous commit, or give it a number to move back
the specified number of steps (as in
git back 5).
Moving forward is simply a case of using
git next, which will go one
step towards the saved position (or
git next 5, which will do what you
Making things a little more automatic
When I started using this, I kept forgetting to save a position before
git back, which would leave me stranded at some older commit.
Since I’m too lazy for this,
git back now detects whether a position
has been saved, and if none has, it saves the current one before moving.
Likewise, when moving forward,
git next will detect when you’ve reached
the target position, and automatically use
git forget. This means that
you can use
git back and
git next without ever having to manually
save or forget anything.
Needless to say, there are probably countless pitfalls that I haven’t considered when writing this, and I’m sure that there are others who have written similar tools that do this much better. But this scratches a personal itch, and was a lot of fun to write.
Time will tell whether I keep using it or not. But for now, at least, it’s just what I wanted.
If you haven’t used aliases yet, you’re in for a treat: you can assign global or project-specific aliases to specific commands, which makes customising git to fit your own particular workflow much easier. ↩
The storage I’ve mentioned is nothing but a file. By default, this file is
.git/MY_SAVED_HEAD, but it can be modified by changing the value of the
MY_GIT_SAVED_HEAD_FILEenvironment variable. You can see what this resolves to with
git saved-head-file. ↩