git status Said We Were in Sync. It Was Quoting the Last Fetch.

git status Said We Were in Sync. It Was Quoting the Last Fetch.

git status Said We Were in Sync. It Was Quoting the Last Fetch.

I opened one of my sites, asked my assistant to add a feature, and it started the way a careful developer starts. It ran git status.

The answer was clean. On main, nothing ahead, nothing behind. My assistant told me the working tree matched GitLab.

It didn't. My collaborator had pushed twelve commits overnight.

What git status actually compares

This is the bit almost everyone gets wrong at least once, and an AI gets it wrong with total confidence.

git status does not talk to the server. It compares your branch against origin/main, which is a local copy of where the remote branch was the last time you fetched. If you haven't fetched since yesterday, "up to date with origin" means "up to date with what origin looked like yesterday."

So the output was true. It was just answering a different question from the one I thought I'd asked.

"Up to date with origin" is a statement about your last fetch, not about the server.

My assistant reported a cached answer as a live one. I accepted it, because it looked exactly like a live one.

Then it built a feature on top

Here is where it got expensive.

Those twelve commits were not small. My collaborator had put a free game on the front page, added a controller logo to the header, and added cache-busting to every script tag.

My assistant, working on the stale tree, added a hamburger menu to the header she had just changed. Then it wrote a Terms page. One of its sentences said the site "does not supply any games."

On the same day a game went up on the front page.

I caught it, not the assistant. I looked at what had come back and said the obvious thing: we forgot to pull before we made this change.

The merge was the easy part

Nothing had been pushed, so recovery was routine. Commit locally, fetch, merge origin/main, resolve two conflicts in the header by keeping both sides, test again.

Git flagged the header straight away. Two people edited the same lines, so the merge tool stopped and asked. That's what merge tools are good at.

What it could never have flagged was the Terms page.

That file didn't conflict with anything. My collaborator never touched it. Her change lived in a completely different file. But her feature made one of my sentences false, and no tool on earth compares a legal page against the front page and notices they disagree.

That is the real risk in this whole story. The code merge was safe. The copy merge was invisible.

Sentences about the whole product are the fragile ones

Some sentences describe one thing. "Click the menu to see more options." Those are pretty safe.

Other sentences make claims about the entire product:

  • "We don't supply any games."
  • "This site has no ads."
  • "Nothing you upload is stored."
  • "We don't use cookies."

Any teammate's feature, in any file, can quietly break those. And they tend to live in exactly the places nobody re-reads: terms, privacy, about, FAQ.

So after merging someone else's work, I now re-read my own prose, not just my diff. Specifically the sentences that start with "we never" or "there is no."

The third thing the stale tree hid

There was a smaller trap in there too.

My collaborator's cache-busting added a version number to each stylesheet link. The assistant had changed a stylesheet. Without a new version on that link, returning visitors would have loaded her new markup with my old cached CSS, and the header would have looked broken for hours.

That isn't a merge conflict either. It's a convention someone introduced while you weren't looking. Once you've pulled their work, follow the pattern they just set, even when it's new to you.

Why an assistant is especially exposed here

A human who has been away from a repo for a day has a nagging feeling. "Has anyone pushed?" An AI assistant starting a fresh session has no such feeling. Every session starts with a working tree that looks fine and a status command that agrees.

It also has no idea anyone else exists. It didn't know a second person committed to this repo. To the assistant, the only author was me, and I had told it nothing had changed.

That is why the fix has to be a rule, not a feeling.

What I do now

On any repo more than one person pushes to, the first command is git fetch. Before status, before reading a single line of code.

git fetch
git status -sb

That second line now tells the truth about the server, because the first line just asked it.

I put that rule into the instructions my assistant reads at the start of every session, so it doesn't depend on either of us remembering. "In sync" is never said without a fetch first.

And when it says we're behind, I pull before writing anything. Rebuilding a feature on top of fresh work is ten minutes. Finding out later that your Terms page contradicts your front page is a much worse afternoon.

The command didn't lie to us. We asked it the wrong question, and it answered the question we asked.