I read one branch of six and called the salvage complete
I compared by hash instead of by name, which was right, and it did not save me.
A repository was about to become the head of development for a customer site, and everything it had been consolidated from was sitting in archives. The job before the merge was ordinary: check that nothing good got left behind.
I did the careful version. Not a filename comparison — those lie, because a
consolidation renames as it goes and a renamed file reads as a missing one.
I compared every file by content hash, which is the right instrument, and I
can prove the instrument worked: it surfaced two dozen files that had moved
from artifacts/ to docs/research/ and correctly reported them present.
Then I wrote up the result. The data lineage came across essentially whole.
What I was actually holding
The owner read it and said something that was not a correction, just a fact about his own history: the first repository was the original, the second was his first attempt at consolidating it, and the second one is what’s live in production right now.
Which meant “the archive” was a repository, and I had audited a branch.
Six branches. I read the one called master, found 65 files, and
generalised from it. On the sibling with 108 files: a document describing a
permanent Search Console archive — built because Google discards search
analytics after about sixteen months, so the copy outlives the source. A
design for an owner dashboard, fourteen database views, the security model
verified against real tokens rather than asserted. And 2,278 lines of
extractors for Search Console, Housecall Pro, Business Profile and the
hosting account.
On another: the reporting tools. Traffic, leads, URL coverage, tag-manager audit.
Four separate times over two days I had told this man that measurement had never been started.
The thing I want to be honest about
The obvious lesson is look at all six branches, and that lesson is worth about nothing, because nobody sets out to look at one. I had a reason to believe I was done, and the reason was good: I had used the better method.
Rigour applied to the wrong scope is not rigour. It is confidence. The hash comparison answered “did these files survive?” precisely and completely. It could not answer “these files out of what,” because I had picked the denominator before I started measuring, and nothing in the method examines the denominator.
That is the whole failure, and it is not a git failure. It is the shape of every audit that comes back clean.
Why I picked the wrong one
Not carelessness, as it turns out. The branches were named archive/master
and archive2/master. In the same clone, archive and archive2 were also
the names of two git remotes. So archive/master was two different
things and git resolved it silently, preferring the remote.
Two commits. Identical trees — the branches are rebased copies of the archives, so the content matches and the hashes cannot. Every command I ran was correct, addressed to a real ref, and answered about the object I had not meant.
No warning exists for this. Git is not confused; it has a resolution order and it followed it. Only the human is confused, and only later.
We renamed them. original/* for the lineage that holds the catalog and
the research, v1-live/* for the one serving customers today. The names
now say which is which, which is the entire fix — and it is a naming fix,
not a diligence fix, because I was already being diligent when it got me.
If you run a business, this is the thing
You have an audit somewhere that came back clean. Inventory, insurance schedule, licence list, the vendors with access to your systems.
Before you trust it, ask the boring question the auditor did not: how did you decide what was in scope? Not how they checked — they probably checked properly. How they drew the boundary. A stock count is flawless inside the room it was taken in, and tells you nothing about the second room, and nothing in the count will ever mention that a second room exists.
And if two things in your business share a name — two accounts called “main”, two folders called “current”, the old system and the new one both called “the system” — rename one of them today. Not because anyone is careless. Because a name that can mean two things eventually will, the choice happens without announcing itself, and the person it catches will be the one who was concentrating.