2

When I switch branches in git I use the checkout command. There often arises a situation in which I want to simply go back and view the state of a project at a certain commit. I've been using the git checkout <commit hash>. This almost always leaves me in a state with a detached HEAD.

I was wondering if someone might be able to explain to me why we can checkout branches without detaching the head, but cannot checkout a specific commit in the same way without detaching the HEAD pointer? I have made the mistake of doing a git reset to view an old commit and this of course deletes everything that came after that commit.

Why does git checkout <commit hash> detach the head? And if this isn't the right command for what I am trying to do what is?

9er
  • 1,604
  • 3
  • 20
  • 37
  • Possible duplicate of [Git: How can I reconcile detached HEAD with master/origin?](http://stackoverflow.com/questions/5772192/git-how-can-i-reconcile-detached-head-with-master-origin). –  Apr 04 '14 at 20:05

3 Answers3

3

One of the primary purposes for HEAD is that it becomes the parent commit of any new commits you create. Typically the HEAD reference takes one of two forms - either a symbolic reference to a branch tip (e.g. master) or the hash of a specific commit. The first is the "normal" mode of operation, and a new commit results in 1) the parent of the new commit being set to the hash represented by the current HEAD, and 2) the branch reference that is the current target of the HEAD reference being moved to point to the new commit. The second case is called "detached", because your HEAD reference is not currently attached to a branch, but to a specific commit that may or may not be a branch tip. This is not a problem, but is just a reminder to you that, because you do not have a branch to update if you create a new commit, any new commits you do make will have nothing except HEAD pointing at them. If you then check out a different branch, there is nothing at all pointing at the new commits, so you run the risk of losing them (there's still the HEAD reflog, so you can generally recover even then, though).

So, the short answer is, no, there is no way to check out an arbitrary non-branch-tip commit without either detaching the HEAD or creating a new branch (but if you're just wanting to look at something on an older commit, that doesn't make sense, because you'll end up with many not-useful branches cluttering up your namespace. There's no harm in having HEAD detached, and it's a normal way of working within git. It just reminds you when you do things like git status so that you can keep in mind what you're in the middle of...

twalberg
  • 59,951
  • 11
  • 89
  • 84
  • so say for example i checkout commit B in the sequence A -> B -> C -> D would git checkout D "reattach" the head to the branch? – 9er Apr 04 '14 at 18:46
  • If by `D` you mean `git checkout master` instead of `git checkout 34627fe6756d` or whatever, yes. Checking out a branch by name will get you out of "detached HEAD" state. Checking something out by hash (even if it happens to be a branch tip) is what causes you to become detached (other things can, though as well, like `git checkout master^3` or `git checkout master@{3 days ago}` - basically anything that isn't just a simple branch name...). – twalberg Apr 04 '14 at 18:52
1

You do use checkout correctly. In git commits are in specific order. For example, this would be your typical history:

A - B - C - D  <-- branch master
  \ E - F      <-- branch feature

Not sure what the design decision was, but it's convenient. Branches always point to the last commit in a branch. So checkout master will get commit D, when checkout feature will get F. Because when you check out a branch - you are interested in it's current state and you (probably) want to continue working starting from the last change.

When you check out a single commit - you look something up and usually revert back. You rarely want to start doing something with commit C, because it has commit D after it (so C is basically "outdated"). If you want to base work off a certain commit - you can start a new branch from it with git branch.

Ruslan Osipov
  • 5,655
  • 4
  • 29
  • 44
1

When you checkout a branch, you do detach the HEAD. You detach it from the branch you were working on. And you attach it immediatly to the branch you are going to. When you checkout a commit, there is nothing you can attach your HEAD to.

greg0ire
  • 22,714
  • 16
  • 72
  • 101