3
  1. I read here that git FETCH_HEAD is a short lived reference . What is the life of git FETCH_HEAD reference ?

  2. When I do git fetch origin , in such cases many remote tracking branch are updated. Where will FETCH_HEAD point to ?

melpomene
  • 84,125
  • 8
  • 85
  • 148
Number945
  • 4,631
  • 8
  • 45
  • 83

2 Answers2

5
  1. It's not really a true reference at all; a reference is a pointer to a single commit (or, in the case of HEAD, a branch name). FETCH_HEAD instead is git metadata about the branches that were last fetched. It lives until it's rewritten by another fetch

  2. It's not a true reference, and contains all the information about the remote tracking information that was fetched.

When you run git merge FETCH_HEAD (or do so implicitly, by running git pull), git treats this specially, and not like a normal reference. Instead, the FETCH_HEAD file will be consulted, and git will look for a branch that does not have the special token not-for-merge given to it. That branch will be the one used for the merge. (Git determined this branch based on the remote tracking branch corresponding to your git fetch invocation or the branch that you were on when you ran it.)

Note that in FETCH_HEAD, the details about the remote branch are also included, which allows git to create a message for the merge commit that details where that branch came from. (eg, "Merge of branch 'master' of https://my.visualstudio.com/my/repository").

FETCH_HEAD, like much of the git repository metadata, is just a text file; reading it to see how it changes after each fetch is incredibly illuminating. (You can see, for example, that the answer that you link to is terribly incorrect, and that FETCH_HEAD does not contain a single branch's information, it contains all the branches on the remote.)

Edward Thomson
  • 74,857
  • 14
  • 158
  • 187
  • "in the case of `HEAD`, a branch name". What about detached-HEAD state? – jub0bs May 28 '18 at 14:36
  • as far as I read , `git pull origin master` does a fetch and then merge. While doing merge , it does `git merge FETCH_HEAD`. If FETCH_HEAD contains metadata abt all branches fetched , then why does git pull uses FETCH_HEAD to do merges ? https://git-scm.com/docs/git-pull – Number945 May 28 '18 at 14:46
  • 2
    Yes, you're right, that's exactly what `git pull` does. `FETCH_HEAD` includes tab-separated fields, and one of those is an indication about which of the branches fetched should be merged. (The branch to be merged has a field with the value `for-merge`, in all other branches it will be empty.) `git merge FETCH_HEAD` resolves this information specially and does not treat `FETCH_HEAD` as if it were a normal branch. – Edward Thomson May 28 '18 at 14:55
  • Pardon me, I had that backwards. All but one will be labeled `not-for-merge`. – Edward Thomson May 28 '18 at 14:59
  • So, we cannot call git fetch_head reference. what is this entity called ? Shud I just say fetch_head is a file in my git directory ? – Number945 May 28 '18 at 15:05
  • Yes, I suppose if you want a description, that's a correct one. – Edward Thomson May 28 '18 at 15:35
2

As it says in gitrevisions,

FETCH_HEAD records the branch which you fetched from a remote repository with your last git fetch invocation.

FETCH_HEAD is created by the first git fetch and will be updated by git fetch. By git fetch, it also means git pull because git pull can be git fetch + git merge or git fetch + git rebase.

For git fetch origin foo, undoubtedly FETCH_HEAD points to the tip of foo. foo is a valid ref that can be fetched from the remote repository. In some rare cases, foo can be the hash of a specific object (commit, tree, blob or tag) if uploadpack.allowTipSHA1InWant is set true in the remote repository, and then FETCH_HEAD will point to the object.

It becomes complicated when it comes to git fetch or git fetch origin. What will FETCH_HEAD be updated to? There are many cases. For example, the local repository is in detached HEAD, on a specific branch that has an upstream, on a branch that doesn't have an upstream, or in some other cases. If not digging that deep, we can know the result from the output of git fetch. Here is a sample,

remote: Counting objects: 11, done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 11 (delta 7), reused 0 (delta 0)
Unpacking objects: 100% (11/11), done.
From D:/hello
   ca2d63e..38d365c  ost        -> origin/ost
 * [new branch]      a          -> origin/a
   8fe4b12..db5a0d9  aaa        -> origin/aaa
   36ca690..e00229b  haha       -> origin/haha
   c96b459..5ab6097  master     -> origin/master
   283a081..004375e  mist       -> origin/mist

We can see the output says which refs are updated by git fetch. FETCH_HEAD always points to the first ref's tip. In this sample, FETCH_HEAD is origin/ost's tip, 38d365c. It's also true when fetching only one ref or one object.

If a git fetch process fails, FETCH_HEAD will become an unknown revision. The file .git/FETCH_HEAD still exists and it's just empty.

ElpieKay
  • 27,194
  • 6
  • 32
  • 53
  • How does git decide that FETCH_HEAD should point to `origin/ost` as in the example ? Is not it dangerous if some one does `git pull origin` ? As we never know what might get merged ? – Number945 May 28 '18 at 15:48
  • 1
    @BreakingBenjamin When no specific ref is given, Git just infers from some facts. In my sample, the local repo is right on the branch `ost` which has `origin/ost` as its tracking branch, so it knows the upstream should be updated and merged and therefore `FETCH_HEAD` points to `origin/ost`. If it was in detached HEAD or another branch that doesn't have an upstream, `FETCH_HEAD` would point to `origin/a` because it would be the first in the alphabet order, and the following `git merge` or `git rebase` would just fail to avoid getting dangerous. – ElpieKay May 28 '18 at 15:54