What does FETCH_HEAD in Git mean?
Asked Answered
S

8

298

git pull --help says:

In its default mode, git pull is shorthand for git fetch followed by git merge FETCH_HEAD.

What is this FETCH_HEAD and what is actually merged during git pull?

Shf answered 11/2, 2012 at 2:35 Comment(2)
Note: since git 1.8.4 (August 2013), git fetch origin master will actually update origin/master, not just FETCH_HEAD. See https://mcmap.net/q/13864/-git-fetch-fetch_head-and-origin-masterDianetics
For more on git merge FETCH_HEAD (since Git 2.5, Q2 2015), see https://mcmap.net/q/12587/-having-a-hard-time-understanding-git-fetchDianetics
S
282

FETCH_HEAD is a short-lived ref, to keep track of what has just been fetched from the remote repository. git pull first invokes git fetch, in normal cases fetching a branch from the remote; FETCH_HEAD points to the tip of this branch (it stores the SHA1 of the commit, just as branches do). git pull then invokes git merge, merging FETCH_HEAD into the current branch.

The result is exactly what you'd expect: the commit at the tip of the appropriate remote branch is merged into the commit at the tip of your current branch.

This is a bit like doing git fetch without arguments (or git remote update), updating all your remote branches, then running git merge origin/<branch>, but using FETCH_HEAD internally instead to refer to whatever single ref was fetched, instead of needing to name things.

Systematist answered 11/2, 2012 at 3:11 Comment(12)
Pull may do a rebase instead of a merge if you configure it that way.Guarantee
@AdamDymitruk: Sure. I described the default behavior, figuring that if someone modified it, they'd know they'd modified it. (For completeness, the behavior is identical, replacing merge FETCH_HEAD with rebase FETCH_HEAD).Systematist
@Jefromi: sorry, i think you are wrong: as far as i understand, git fetch updates (merges) all object data from the remote storage, not just a brunch. So i do not understand from your answer how git decides to the tip of which branch to point FETCH_HEAD. I also cannot find FETCH_HEAD in git documentation (the definition, not examples). The existence of FETCH_HEAD looks to me more like a workaround, to make git pull work somehow.Tala
Alexey: FETCH_HEAD corresponds to the tip of the remote branch specified by branch.<BRANCH>.merge in the local repository configuration. So while fetch does indeed fetch all object data from the remote storage, FETCH_HEAD is used to indicate to where the remote branch tracked by the local branch has advanced. So if you are on the local master branch and run git fetch, and branch.master.merge points to refs/heads/master, then FETCH_HEAD will have the same value as origin/master immediately after the fetch operation.Clynes
@alexy FETCH_HEAD is described in the second paragraph of the description of git fetch in its man page. My answer is correct. And git fetch without arguments does update all remote branches for the default remote... but this is definitely not the same as merging.Systematist
What is FETCH_HEAD if you fetch all remote branches via git fetch -a?Seneschal
@Seneschal The tip of the remote tracking branch your currently checkedout branch is pointing to in the git config. Please see larsks' answer in the comment above.Bunche
And what if you're detached and do a fetch? What if you have a local ref checked out but no remote tracking branch? How is FETCH_HEAD manipulated during git fetch in these circumstances?Concurrent
@Concurrent Doesn't seem like the local state would matter? FETCH_HEAD is for keeping track of the remote. So whatever you fetch, that's FETCH_HEAD. The local ref/commit that's checked out only matters when you get to the merge.Systematist
@jefromi according to the answers here local state does matter. FETCH_HEAD can only store one remote sha1. It does not track the remote like you say. So when fetch pulls down more than one ref, answers here state that the local remote tracking branch determines which of the remote refs becomes FETCH_HEAD. So my question still stands.Concurrent
@Alexey: your question may be addressed by my newly-added answer below: https://mcmap.net/q/13624/-what-does-fetch_head-in-git-mean.Albin
As @Tala suggests and @CarstenFührmann further clarifies, no, FETCH_HEAD does not just contain a single branch. It contains all the remote branch information that was last fetched.Iaria
K
35

The FETCH_HEAD 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.

So if I issue:

git fetch https://github.com/ryanmaxwell/Fragaria

FETCH_HEAD may contain

3cfda7cfdcf9fb78b44d991f8470df56723658d3        https://github.com/ryanmaxwell/Fragaria

If I have the remote repo configured as a remote tracking branch then I can follow my fetch with a merge of the tracking branch. If I don't I can merge the tip of the last fetch directly using FETCH_HEAD.

git merge FETCH_HEAD
Karonkaross answered 10/12, 2012 at 11:37 Comment(2)
To add my 5 cents. What confused me is, that my FETCH_HEAD was behind the latest commits, even if doing a new fetch that returned "no changes" (in eclipse). I Think the reason is, that all changes since my last fetch are from myself and were pushed to the server by me. So a subsequent fetch had nothing to do, and did not even update the FETCH_HEAD. I am not sure if this is a shortcoming of GIT or Eclipse Git implementation though.Burck
Great answer. Just a question: What happens if one does git pull without arguments? What would be the value of FETCH_HEAD? Without arguments, this command will update all the remote-tracking-branches right? But there is no one single branch that has been fetched. Now is it correct to say between those branches, the one with the name origin/current_branch will be merged in to our current_branch branch?Friend
I
23

As mentioned in Jonathan's answer, FETCH_HEAD corresponds to the file .git/FETCH_HEAD. Typically, the file will look like this:

71f026561ddb57063681109aadd0de5bac26ada9                        branch 'some-branch' of <remote URL>
669980e32769626587c5f3c45334fb81e5f44c34        not-for-merge   branch 'some-other-branch' of <remote URL>
b858c89278ab1469c71340eef8cf38cc4ef03fed        not-for-merge   branch 'yet-some-other-branch' of <remote URL>

Note how all branches but one are marked not-for-merge. The odd one out 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.

Iberian answered 7/8, 2017 at 9:36 Comment(2)
where is .git directory? could not find it. how to show the current FETCH_HEAD value? thanks.Eloiseloisa
The .git directory should be in the root folder of your local git repo. Because of the leading dot in the directory name, it may be hidden unless you enable seeing hidden files in whatever tool you use to view directories.Albin
G
11

I have just discovered and used FETCH_HEAD. I wanted a local copy of some software from a server and I did

git fetch gitserver release_1

gitserver is the name of my machine that stores git repositories. release_1 is a tag for a version of the software. To my surprise, release_1 was then nowhere to be found on my local machine. I had to type

 git tag release_1 FETCH_HEAD 

to complete the copy of the tagged chain of commits (release_1) from the remote repository to the local one. Fetch had found the remote tag, copied the commit to my local machine, had not created a local tag, but had set FETCH_HEAD to the value of the commit, so that I could find and use it. I then used FETCH_HEAD to create a local tag which matched the tag on the remote. That is a practical illustration of what FETCH_HEAD is and how it can be used, and might be useful to someone else wondering why git fetch doesn't do what you would naively expect.

In my opinion it is best avoided for that purpose and a better way to achieve what I was trying to do is

git fetch gitserver release_1:release_1

i.e. to fetch release_1 and call it release_1 locally. (It is source:dest, see https://git-scm.com/book/en/v2/Git-Internals-The-Refspec; just in case you'd like to give it a different name!)

You might want to use FETCH_HEAD at times though:-

git fetch gitserver bugfix1234
git cherry-pick FETCH_HEAD

might be a nice way of using bug fix number 1234 from your Git server, and leaving Git's garbage collection to dispose of the copy from the server once the fix has been cherry-picked onto your current branch. (I am assuming that there is a nice clean tagged commit containing the whole of the bug fix on the server!)

Gretel answered 8/9, 2014 at 9:30 Comment(3)
Interesting feedback. +1Dianetics
Thanks. I edited my original post, written when I first discovered FETCH_HEAD a couple of years ago, since it appeared to encourage copying a tag using FETCH_HEAD rather than the source:dest syntax for refspecs. Hopefully I have now given a better example of how FETCH_HEAD could be used.Gretel
git fetch gitserver source:dest. source is remote tag, dest is local tag? For git cherry-pick FETCH_HEAD, should it be git tag cherry-pick FETCH_HEAD? thanks.Eloiseloisa
D
5

FETCH_HEAD is a short-lived ref, to keep track of what has just been fetched from the remote repository.

Actually, ... not always considering that, with Git 2.29 (Q4 2020), "git fetch"(man) learned --no-write-fetch-head option to avoid writing the FETCH_HEAD file.

See commit 887952b (18 Aug 2020) by Junio C Hamano (gitster).
(Merged by Junio C Hamano -- gitster -- in commit b556050, 24 Aug 2020)

fetch: optionally allow disabling FETCH_HEAD update

Signed-off-by: Derrick Stolee

If you run fetch but record the result in remote-tracking branches, and either if you do nothing with the fetched refs (e.g. you are merely mirroring) or if you always work from the remote-tracking refs (e.g. you fetch and then merge origin/branchname separately), you can get away with having no FETCH_HEAD at all.

Teach "git fetch"(man) a command line option "--[no-]write-fetch-head".

  • The default is to write FETCH_HEAD, and the option is primarily meant to be used with the "--no-" prefix to override this default, because there is no matching fetch.writeFetchHEAD configuration variable to flip the default to off (in which case, the positive form may become necessary to defeat it).

Note that under "--dry-run" mode, FETCH_HEAD is never written; otherwise you'd see list of objects in the file that you do not actually have.

Passing --write-fetch-head does not force [git fetch](https://github.com/git/git/blob/887952b8c680626f4721cb5fa57704478801aca4/Documentation/git-fetch.txt)<sup>([man](https://git-scm.com/docs/git-fetch))</sup> to write the file.

fetch-options now includes in its man page:

--[no-]write-fetch-head

Write the list of remote refs fetched in the FETCH_HEAD file directly under $GIT_DIR.
This is the default.

Passing --no-write-fetch-head from the command line tells Git not to write the file.
Under --dry-run option, the file is never written.


Consider also, still with Git 2.29 (Q4 2020), the FETCH_HEAD is now always read from the filesystem regardless of the ref backend in use, as its format is much richer than the normal refs, and written directly by "git fetch"(man) as a plain file..

See commit e811530, commit 5085aef, commit 4877c6c, commit e39620f (19 Aug 2020) by Han-Wen Nienhuys (hanwen).
(Merged by Junio C Hamano -- gitster -- in commit 98df75b, 27 Aug 2020)

refs: read FETCH_HEAD and MERGE_HEAD generically

Signed-off-by: Han-Wen Nienhuys

The FETCH_HEAD and MERGE_HEAD refs must be stored in a file, regardless of the type of ref backend. This is because they can hold more than just a single ref.

To accomodate them for alternate ref backends, read them from a file generically in refs_read_raw_ref().


With Git 2.29 (Q4 2020), Updates to on-demand fetching code in lazily cloned repositories.

See commit db3c293 (02 Sep 2020), and commit 9dfa8db, commit 7ca3c0a, commit 5c3b801, commit abcb7ee, commit e5b9421, commit 2b713c2, commit cbe566a (17 Aug 2020) by Jonathan Tan (jhowtan).
(Merged by Junio C Hamano -- gitster -- in commit b4100f3, 03 Sep 2020)

fetch: no FETCH_HEAD display if --no-write-fetch-head

Signed-off-by: Jonathan Tan

887952b8c6 ("fetch: optionally allow disabling FETCH_HEAD update", 2020-08-18, Git v2.29.0 -- merge listed in batch #10) introduced the ability to disable writing to FETCH_HEAD during fetch, but did not suppress the "<source> -> FETCH_HEAD" message when this ability is used.

This message is misleading in this case, because FETCH_HEAD is not written.

Also, because "fetch" is used to lazy-fetch missing objects in a partial clone, this significantly clutters up the output in that case since the objects to be fetched are potentially numerous.

Therefore, suppress this message when --no-write-fetch-head is passed (but not when --dry-run is set).


With Git 2.41 (Q2 2023), this option is properly propagated:

See commit 15184ae (08 Mar 2023) by Eric Wong (ele828).
(Merged by Junio C Hamano -- gitster -- in commit 947604d, 19 Mar 2023)

fetch: pass --no-write-fetch-head to subprocesses

Signed-off-by: Eric Wong

It seems a user would expect this option would work regardless of whether it's fetching from a single remote, many remotes, or recursing into submodules.

Dianetics answered 31/8, 2020 at 16:6 Comment(0)
N
3

git pull is combination of a fetch followed by a merge. When git fetch happens it notes the head commit of what it fetched in FETCH_HEAD (just a file by that name in .git) And these commits are then merged into your working directory.

Noma answered 11/2, 2012 at 2:45 Comment(2)
@manjolds, what do you mean by "head commit of what it fetched"? Git fetches everything with fetch.Tala
@Tala from git manual: git-scm.com/docs/git-fetch: The names of refs that are fetched, together with the object names they point at, are written to .git/FETCH_HEADAstri
L
1

I was just trying to pull down a (patch) branch that I created from making changes directly from GitHub. The branch only appeared on GH. When I tried doing a git pull, the branch didn’t show up.

I was able to checkout the branch using:

git fetch origin pull/2/head
git checkout -b <desired-branch-name> FETCH_HEAD
Lienlienhard answered 1/3, 2022 at 19:23 Comment(0)
C
1

Let me contribute to this, if it is possible.

  1. On image I have asked to REMOTE if there is some change in the BRANCH i am working. FETCH has told me * branch back_end -> FETCH_HEAD

  2. THEN I've asked for PULL, trying to bring everithing NEW on REMOTE (GITHUB) to my local branch (it has the same name back_end)

GIT told me--->> FETCH_HEAD which means everything was already updated and there was anything to update from REMOTE BRANCH, the same information that FETCH instruction told me before.

enter image description here

Copulative answered 6/6, 2022 at 18:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.