Skip to content

Add coding agent Git safety post - #292

Open
martinfrancois wants to merge 2 commits into
masterfrom
francois/coding-agent-git-safety
Open

Add coding agent Git safety post#292
martinfrancois wants to merge 2 commits into
masterfrom
francois/coding-agent-git-safety

Conversation

@martinfrancois

Copy link
Copy Markdown
Contributor

No description provided.

@martinfrancois
martinfrancois requested a review from kress04 August 27, 2026 23:41
@martinfrancois martinfrancois self-assigned this Aug 27, 2026
@martinfrancois
martinfrancois force-pushed the francois/coding-agent-git-safety branch 14 times, most recently from f1e2ac3 to bd277e1 Compare August 29, 2026 00:44
Three diagrams carry the parts of the argument that prose struggles with: why
reverting in a shallow clone stages every file for deletion, why
--force-with-lease lets a rewrite through that --force-if-includes refuses, and
which safeguard stops which kind of push.

They are hand-authored SVG so they stay legible and editable, and each one is
capped at a fixed width, because an image scales as one piece and its labels
would otherwise be unreadable on a phone and oversized on a wide screen. The cap
is scoped to a class these three images carry, so no other image on the site
moves.

That class is listed in the styling guide next to the other classes a post can
use, so the next author can find it.

The rules code block is wrapped at 80 columns. One of its lines was 248
characters, which forced the whole article wider than the viewport at tablet
sizes.
@martinfrancois
martinfrancois force-pushed the francois/coding-agent-git-safety branch from bd277e1 to 3e2df46 Compare August 29, 2026 14:24

Both Claude Code and Codex have hooks that can refuse a command before it runs, and they are worth having. But they only see the text of the command the agent hands to the shell. They can spot an explicit `git push`. They cannot tell, from a command that runs a Python script, that the script pushes once it starts. That is exactly how my incident reached `main`.

Git sees it. Every `git push` runs the [`pre-push` hook](https://git-scm.com/docs/githooks#_pre_push), no matter what process started it, unless the caller passes `--no-verify`. Git has no idea who I am, of course, but the environment that the push runs in does, and a hook can read that.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

“Every git push runs the pre-push hook” is too absolute. Qualify it: ordinary Git CLI pushes invoke it unless bypassed (--no-verify), redirected via configuration such as core.hooksPath, or performed by a different Git implementation/library. Your later caveat helps, but it should appear at the first claim.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Qualified at the first claim: it now says any push made with the git command, names --no-verify and a redirected hooks folder as the ways past it, and states that a Git library never runs it. bf6f7f2


Because the clone did not contain the commit before it, Git treated that commit as if it had created the entire file tree. Reverting it therefore staged **every single file in the repository for deletion**. Claude then committed and pushed that to `main`.

![Two panels comparing the same revert. Each commit is a snapshot. In a full clone, which holds a parent and HEAD, git revert --no-commit HEAD undoes only HEAD's edit and one file changes back: the broken YAML, which is exactly what was wanted. In a shallow clone the earlier commits were never fetched, so HEAD is the only snapshot and the same command undoes the whole repository, staging every file for deletion: 151 files in one repository and 723 in the other.](/assets/posts/2026-08-28-coding-agent-git-safety/shallow-clone-revert.svg "The same command, two clones, two very different diffs."){:.diagram}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

git revert --no-commit HEAD in a depth-one clone staged deletion of all files. Git documents that shallow commits are treated as root commits, and that a revert undoes the changes represented by the target commit. Git shallow repositories, git-revert

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call. Kept the plain wording and linked both pages from the sentence above the figure, so the claim now points at the Git docs. bf6f7f2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants