On the morning of October 23, I ran git status on our shared test VM and found two modified files I hadn't touched:

On branch PILOW_B107 Your branch is up to date with 'origin/PILOW_B107'. Changes not staged for commit: modified: common/lib/Goodbarber/Referral/Referral.php modified: common/models/CommandeRemise.php 

I asked Claude Code, which was writing the feature with me, whether that was its doing. It was: a first fix, posted straight onto the VM without a commit, so that my test payment could go through.

Some context. I run backend engineering at GoodBarber, an app platform, and that afternoon we shipped a referral program in our back office. The back office can only be tested end to end on that VM, which other people use too. Git saw the code. A good part of the release happened elsewhere.

Files on the VM

That morning, changes went onto the VM several times before they went into a commit: the layout of the code's Copy button, the first fix for a guard that blocked my test payment, the version that replaced it, and two fixes to the validator and the cron. Each time, it let me test the change before anyone committed it.

One of those versions went on while my payment was in progress. Claude wrote the new file next to the old one, linted it, then renamed it over the original, so that the request in flight couldn't load a half-written file.

After each commit and push, Claude realigned the VM. It compared the fingerprint of each modified file on the VM with the committed version, staged it, then fast-forwarded the VM's checkout. When the fingerprints match, the fast-forward rewrites nothing. Once, it didn't go through: restoring the files triggered the repository's Git LFS hook, which failed because the container has no git-lfs. The VM served the old page for a few seconds, and the fast-forward ran again without hooks. The commit touched no LFS file.

The VM was not always aligned. After a commit that only changed a SQL file of texts, it stayed one commit behind on purpose, because those texts had already been updated by hand in the dev database. And when master had to be merged into the branch, the merged files were linted in a temporary directory of the container, without touching the VM's checkout: 37 files, 22 from the merge and 15 from the feature.

Data in the test database

Testing a payment writes orders, invoices, vouchers, credits and payment traces for real dev apps. Before any change, a script took a photo of every row of the test apps in every table that has an id_webzine column, 421 tables, plus their orders and invoices with their lines. The apps were then prepared in one transaction, which rolled back if an app wasn't in the expected state.

When the test payment wouldn't go through, I suggested faking the invoice row. Claude used the code path that creates an invoice from an order instead, so the voucher's use switched to paid exactly as after a real payment. Then it moved the settlement date back 16 days to make the cron decide.

At the end, the restore script put the three test apps back, and a new comparison found zero differences with each photo. The restore also removed what the payment flow had written elsewhere: payment-provider traces, the billing address I had typed, short links, login traces. The photos don't cover what isn't attached to an app, such as consumed sequence numbers and global log lines. They are still on the VM, about 70 MB with the scripts, for the next test.

Texts in the database

The referral page's texts live in a table of the back office's database, in twenty languages. The repository has a SQL file that inserts them, 340 rows, and skips any row that already exists. That makes it safe to replay, and useless for changing a text that production already has.

The texts changed four times between October 23 and 26. The insert file in the repository got the new texts, for databases that don't have them yet. Production needed an UPDATE script of 20 or 40 lines, tested first on a database configured like production, with standard_conforming_strings = off. I copied each script with pbcopy, pasted it into psql on production, then flushed the texts' cache.

Those UPDATE scripts lived in Claude's scratchpad under /tmp. One of its messages warned that a reboot of my Mac would erase the next one, and that it would regenerate it from the insert file. That was a choice. The repository already has a precedent for versioning such update scripts next to their insert file. For this branch, my rule was code only: the feature's documentation was removed with git rm before production, and the update scripts never went in.

Production's texts have been changed four times by scripts that exist in no repository.

How do you know, on a shared test machine, which files on disk match a commit?