What does FETCH_HEAD in Git mean?

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.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *