Checking out a Git branch further back than the head

February 6, 2022

Famously, if you want to check out a repository at some arbitrary commit back from the head of your current branch, you normally do this with just 'git checkout <commit>'. I do this periodically when making bug reports in order to verify that one specific commit is definitely the problem. Equally famously, this puts you into what Git calls a 'detached HEAD' state, where Git doesn't know what branch you're on even if the commit is part of a branch, or even part of 'main'.

It's possible to move a branch (including 'main') back to an older commit while staying on the branch. This avoids Git complaints about being in a detached HEAD state and makes 'git status' do useful things like report how many commits you are behind the upstream tip. As far as I know so far, the way you do this is:

git checkout -B main <commit>

As 'git status' will tell you, you can return to the tip from this state by doing 'git pull'. Equivalently, you can do 'git merge --ff-only origin/main', which avoids fetching anything new from your upstream. This second option gives away the limitation of this approach.

The limitation is that you can only do all of this if you don't have any local commits that you rebase on top of the upstream. If you do have local commits, I think that you want to live with being in the detached HEAD state unless you like doing a bunch of work (and I'm assuming here that you can live without your local changes; otherwise life gets more complicated). Doing all of this back and forth movement of what 'main' is smoothly relies on your normal main being the same as origin/main, and that's not the case if you're rebasing local commits on top of origin/main every time you pull it.

(Git has a syntax for 'N commits back from HEAD' as part of selecting revisions (also), but for almost everything I do what I care about is a specific commit I'm picking out of 'git log', not a number of commits back from the tip.)

It's a little bit annoying that you have to specify the branch name in 'git checkout' even though it's the current branch name. As far as I know, Git has no special name you can use for 'the current branch, whatever it's called', although it does have a variety of ways of getting the name of the current branch. If you're scripting this 'back up to a specific commit on a branch', you can use one of those commands, but for use on the fly I'll just remember to type 'main' or 'master' (depending on what the repository uses) or whatever.

(This is one of the Git things that I don't want to have to work out twice. Although Git being Git, it may in time acquire a better way to do this.)

Written on 06 February 2022.
« Go 1.18 won't have a 'constraints' package of generics helpers
What does it mean for a filesystem to perform well on modern hardware? »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Sun Feb 6 22:59:39 2022
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.