On Mon, Nov 2, 2026, at 2:47 PM, Andy Koppe wrote:
On Mon, 2 Nov 2026 at 18:20, Julia Evans wrote:
quoted
On Sun, Nov 1, 2026, at 6:03 PM, Andy Koppe wrote:
quoted
quoted
++[[root-refs]]
++root refs::
++ Git may also create references other than `HEAD` at the root
of the
++ hierarchy, for example `ORIG_HEAD` or `REBASE_HEAD`.
++
++[[pseudorefs]]
++pseudorefs::
++ linkgit:git-fetch[1] and linkgit:git-merge[1] create the
so-called
++ pseudorefs `FETCH_HEAD` and `MERGE_HEAD`. They are not
references as
++ such, as they are not stored in the same way, but they can
nevertheless
When I look at my .git directory during a merge conflict, I see these
files:
$ ls .git | grep HEAD
FETCH_HEAD
HEAD
MERGE_HEAD
ORIG_HEAD
From the above, it sounds like ORIG_HEAD is a "root ref" and
MERGE_HEAD is a "pseudoref", but naively it does look like
they're stored in the same way. What's the difference?
Good question. The differences certainly aren't obvious, and they
barely matter to users.
Root refs:
- Can be stored in reftables instead of files in .git.
- Contain either a single hash or a single symbolic ref such as 'ref:
refs/heads/main'.
- Can be modified with 'git update-ref' (generally a bad idea for
built-in root refs) and listed with 'git for-each-ref' and similar
commands.
Pseudorefs:
- Are always stored as files in .git.
- May contain multiple hashes, and in the case of FETCH_HEAD, carry
additional information about where each hash came from.
- Are only modified by the commands they serve (i.e. fetch, merge and
pull) and can't be listed.
The big thing they have in common, apart from the *_HEAD names, is
that you can pass both types to commands such as 'git log', 'git diff'
or 'git checkout' to refer to a commit or tree, just like any ref
under refs/.
That’s very helpful. I think it would make sense to include
“may contain multiple hashes” at least, that on its own
makes it very clear what the difference is.
My impression is that FETCH_HEAD specifically is a
relatively popular pseudoref and folks would be interested to
know that it can contain multiple hashes.
If a pseudoref contains multiple hashes and you pass it to
a command, will the command use the first hash?
Also are FETCH_HEAD and MERGE_HEAD the only
pseudorefs?