Git's tree sort has a famous quirk: a directory sorts as if its name ended in a slash. It only bites when a file and a directory share a prefix, but when it does, getting it wrong changes the hash. Today you pin this edge.
Sort tree entries so a directory is ordered as if its name had a trailing slash.
Here is the rule real Git uses and most reimplementations get wrong at first:
when comparing two entry names, a directory is treated as though its name ended
in a slash. So the file sub.txt and the directory sub are compared as
sub.txt against sub/. Byte by byte they agree on s, u, b, then differ:
. is 0x2E and / is 0x2F, so sub.txt sorts before sub. A naive sort by
the bare name would put sub first (a shorter string that is a prefix) and
produce a different, wrong hash.
Only the sort key gets the trailing slash; the name stored in the entry is unchanged. This is a refinement of the sort from the earlier tree lesson, and it leaves every all-files or non-colliding tree exactly as it was, so your previous tree ids still hold. It is the kind of boundary that a mid-range test never reaches: you need a file and a directory sharing a prefix to see it at all.
// a directory's sort key is its name with a trailing slash appendedfunc sortKey(e Entry) string {if e.Mode == "40000" {return e.Name + "/"}return e.Name}// sort by sortKey(a) < sortKey(b); the stored name itself is unchanged