Building VTS

The Official VTS Engineering Blog

Finding Lost Git Commits

By Dan Ubilla

We move fast around here. As such, I’m usually juggling a number of branches at a given time. I usually have one branch building on a CI server, when I create a branch to start a new feature in. Sometimes, something even more pressing will come up, and I’ll have to drop that new feature to work on a bug. This leads to lots of git stashing, git popping, and hopping between branches as fast as my machine will let me. While I’m normally good about paying attention to the branch I’m on and committing work appropriately, I’ll occasionally lose a commit. Here’s how I go about finding it.

My first move is to check my Git stash. The best case scenario is that I stashed some work, and I just forgot it. If I run git stash list, I see a nice list of stashes by branch. Any time I change branches and I’m in the middle of work, I’ll stash the changes to come back to later, so I tend to find “lost” work in here. If I see two stashes for the same branch, that’s usually a solid sign that the work I’m looking for is in one of those. When it’s not, though, I need to do some more hunting.

Occasionally, I move a little too fast, and I accidentally make a commit to the wrong branch. I have an alias set up to run a quick Git command, (h/t to Chris Kim!) to list branches by last commit. It is extremely helpful to see the last few branches I was working on, and see what commits I have in each of those. If I find the commit there, I’ll grab the hash, switch to the branch I want the commit to be on, and run git cherry-pick to copy it to there.

1
alias branches="git for-each-ref --sort=-committerdate refs/heads/ --format='%1B[0;32m%(authorname)%09%1B[0;36m(%(committerdate:relative))%09%1B[0;33m%(refname:short)%09%1B[m%    (subject)' --count 10 | tail -r | column -t -s $'\t'"

Recently, however, none of these techniques worked for me. Did I daydream this work? Was my commit sacrificed to the Git gods? Thankfully, there’s one last recourse to take. It’s time to check the reflog. The reflog is short for “reference log”, and it’s a log of all the times branch tip references are updated. (It’s important to note that this list gets cleaned up by Git’s garbage collection, but hopefully, you’re looking for a commit that’s been lost recently.) When looking for a lost commit, the best command to run is:

1
cat .git/logs/HEAD --last 25 | grep commit

At the bottom of that output, you should hopefully find your lost, orphaned commit. Copy the hash, make sure you’re on the proper branch, and run a git-cherry pick on the hash to apply the commit.

Hopefully, one of these three techniques will help you hunt down that lost commit. Best of luck in your search!