A Better Git Flag Broke the Reproduction

The script looked wrong.
It searched for gone upstream branches with this pipeline.
git branch -v | grep '\[gone\]'
The reviewer knew that -vv showed upstream information.
So they made the command more informative before testing it.
git branch -vv | grep '\[gone\]'
It returned no match.
That appeared to prove the original detector was broken.
It proved something else.
The replacement command emitted a different string.
One extra v changed the evidence
The current git-branch(1) manual describes -v and -vv together.
In list mode, verbose output includes the commit and its relationship to the upstream branch.
When -v is given twice, Git also prints the upstream branch name and linked-worktree path where applicable.
That extra upstream name changes the text around gone.
In an isolated fixture, the single-verbose command printed this.
gone-demo ca5baa7 [gone] fixture initial state
* main ca5baa7 fixture initial state
The double-verbose command printed this.
gone-demo ca5baa7 [origin/gone-demo: gone] fixture initial state
* main ca5baa7 fixture initial state
Both outputs describe the same local branch with a missing upstream ref.
They do not expose the same substring.
The original pattern was shape-specific
The grep pattern did not ask whether the word gone appeared somewhere.
It asked for the exact bracketed token [gone].
\[gone\]
That token exists in the -v output.
It does not exist in the -vv output.
The second form contains a longer bracketed relationship.
[origin/gone-demo: gone]
Changing only the producer while keeping the old consumer created an incompatible pair.
The empty result belonged to that new pair.
It said nothing about the command in the script.
A local fixture made the difference visible
The inspected fixture used Apple Git 2.50.1 and a temporary local bare remote.
Its gone-demo branch retained origin/gone-demo as tracking configuration while both the local remote-tracking ref and the bare remote ref were absent.
A minimal recipe for that state is small.
Create an empty local repository.
Create a branch named gone-demo.
Push it to a local bare remote and set the upstream.
Delete the remote branch.
Fetch with pruning.
Then run both list commands against the same repository state.
The exact pipeline from the script succeeded.
git branch -v | grep '\[gone\]'
exit: 0
The substituted producer failed with the unchanged pattern.
git branch -vv | grep '\[gone\]'
exit: 1
Finally, a control pattern matching the double-verbose shape succeeded.
git branch -vv | grep '\[origin/gone-demo: gone\]'
exit: 0
That third check matters.
It shows that the branch state did not disappear from -vv.
Only its rendering changed.
The review fixed the command before reproducing it
“Use more verbose output” can be a reasonable improvement proposal.
It is not a valid first step in reproducing existing behavior.
A reproduction has to preserve the system under test.
That includes flags that look suboptimal.
It includes quoting that looks awkward.
It includes the exact input and environment that the original code receives.
Otherwise the review answers a counterfactual question.
Would this pattern work if the producer emitted a different format.
That can be useful later.
It cannot establish that the current code is broken.
A more correct flag can still be the wrong experiment
Reviewers routinely normalize commands while reading them.
Add a missing-looking verbosity flag.
Replace a short option with a familiar long option.
Move a filter earlier in the pipeline.
Run a formatter before inspecting a parser bug.
Each edit may improve the command in isolation.
Each edit can also change the behavior being investigated.
The phrase “I tested the same thing” needs a literal diff.
If the command changed, state what changed and why the result still answers the original claim.
Start with the untouched command
My review order is now strict.
First, copy the command exactly as written.
Second, construct the smallest fixture that can produce the target state.
Third, run the untouched command and record stdout, stderr, and exit status.
Fourth, prove the fixture really contains the state under discussion.
Fifth, change one variable at a time.
Only after that should the review propose a clearer flag or output format.
This separates diagnosis from redesign.
Make the fixture capable of saying gone
An empty branch list cannot test a gone-branch detector.
A local branch with no upstream cannot test it either.
The fixture needs a branch that still has tracking configuration while the referenced remote branch is absent.
That is why the local bare remote, push, delete, and prune steps matter.
Without them, a passing “no matches” result reads nothing.
Before trusting the detector's failure, make the fixture produce one positive [gone] line.
Output consumers inherit producer flags
This bug is not specific to Git.
Any text pipeline couples a producer's rendering to a consumer's pattern.
Changing a verbosity flag can add prefixes, labels, paths, colors, or context.
The downstream grep may be perfectly correct for the old shape and useless for the new one.
When a review changes the producer, it must re-evaluate the consumer as part of the same experiment.
The absence of a match is not proof until the expected match shape has been printed once.
The practical rule
Run the command as written before testing a variant.
git branch -v and git branch -vv do not produce interchangeable gone markers in the verified fixture.
Keep the producer and its grep pattern paired.
Build a fixture that can produce the positive state.
Treat an improved command as a new experiment, not evidence about the old one.
One last thing
The original pipeline looked suspicious.
The reviewer's version looked better.
Only one of them was actually in the script.
Debugging begins when we stop correcting the evidence before reading it.
Get the next post.
If you made it to the end, meet the next post in your inbox or RSS reader.