[Original] What's HEAD, FETCH_HEAD and ORIG_HEAD in Git

hustnzj發表於2022-09-06

There are many heads in Git: head, HEAD, ORIG_HEAD, FETCH_HEAD, MERGE_HEAD and CHERRY_PICK_HEAD.

The most common ones are head, HEAD, ORIG_HEAD, FETCH_HEAD.

Let me elaborate them one by one.

head

head: A named reference to the commit at the tip of a branch. Heads are stored in a file in $GIT_DIR/refs/heads/ directory.

In the top level of your project, show the branches in your repo:

$ ls .git/refs/heads
daily main

Show the commit hash of each branch:

$ cat .git/refs/heads/main
26555cbab836f2b1e1a45d93e9b53b0ccbe48c2f
$ cat .git/refs/heads/daily
254036f1d9c2ecee235cae198c822d9209a2ca7c

Verify the commit hash by git log

$ git log --online
254036f (HEAD -> daily) Go about learning Git' heads
26555cb (main) publish the translation post

The matched hash proved that head is a pointer to the commit at the tip of a branch.

HEAD

$ cat .git/HEAD
ref: refs/heads/daily

We can see HEAD -> daily which means that HEAD is pointing to the daily branch, if you run git checkout main, you will see that HEAD is pointing to the main branch at this moment:

$ git checkout main
$ git log --online
26555cb (HEAD -> main) publish the translation post
24a679c do some stuff
$ cat .git/HEAD
ref: refs/heads/main

HEAD is like a pointer that points to the current branch. When you checkout a different branch, HEAD changes to point to the new one.

But keep in mind that HEAD is not the current branch, otherwise is the name given to the commit from which the working tree’s current state was initialized. In more practical terms, it can be thought of as a symbolic reference to the checked-out commit.

FETCH_HEAD

FETCH_HEAD is a short-lived ref, to keep track of what has just been fetched from the remote repository. It does not just contain a single branch but all the remote branch information that was last fetched. It is a reference to the tip of the last fetch, whether that fetch was initiated directly using the fetch command or as part of a pull. The current value of FETCH_HEAD is stored in the .git folder in a file named, you guessed it, FETCH_HEAD which looks like this typically:

e03ef7e18694ff33ac61ba3ee927228f75d9b634        branch 'main' of https://github.com/hustnzj/<my-repo-name>
079d80cfbe4988317858e5509c322f5b61b9b26c    not-for-merge    branch 'test' of https://github.com/hustnzj/<my-repo-name>
dfb32906005c40ca709772ed45de68c25b56b07a    not-for-merge    branch 'daily' of https://github.com/hustnzj/<my-repo-name>

Note how all branches but one are marked not-for-merge. The odd one is the branch that was checked out before the fetch. In summary: FETCH_HEAD essentially corresponds to the remote version of the branch that’s currently checked out.

If you merge now, the commit at the tip of the remote branch main is merged into the commit at the tip of your current local branch main in this case.

ORIG_HEAD

ORIG_HEAD is created by commands that move your HEAD in a drastic way, to record the position of the HEAD before their operation, so that you can easily change the tip of the branch back to the state before you ran them.
For example, you use git reset to go to the specified state. The --hard mode is so dangerous that you are likely to lose data.

$ git reset --hard HEAD~5

ORIG_HEAD comes into its own when you mess up and want to return the previous position.

$ git reset ORIG_HEAD

That’s all! Hope the article clear up some doubts and uncertainties in your daily work!

References

Git - gitglossary Documentation
What is HEAD in Git? - Stack Overflow
What does FETCH_HEAD in Git mean? - Stack Overflow.)
Git - gitrevisions Documentation

本作品採用《CC 協議》,轉載必須註明作者和本文連結
日拱一卒

相關文章