develop and main are usually protected — no reset, no force-push — so undoing means new commits on top. git revert needs a commit range and a -m parent decision per merge commit: many chances to pick wrong.

git revert 4dbcaf5419d5b5aa19776d7ed733a163cacd95fe..dbffeb4da345fd0c66b0b7a8193a6582b409cd4a

The fallback is a second clone: target branch checked out elsewhere, everything but .git deleted, the good branch’s contents copied in, commit — works, miserable.

The one-liner Link to this section

git restore copies files out of any revision into the working tree without touching the index, unlike git checkout or git reset, which move it — so the desired tree pulls in on the protected branch:

git fetch --all
git restore --source=origin/main .

A file or glob narrows it:

git restore --source=origin/main index.html

restore only writes the working tree, so the revert still needs its commit:

git add -A
git commit -m "Revert to origin/main"

No merge parents, no commits to enumerate, and the history stays append-only — the reason for protection.

References Link to this section