Git, CI/CD & GitOpsXXXVI · Git History RewritingOperations
The force-push aftermath — communication, coordination, audit
What you'll learn
- Pre-push communication: announce the rewrite window, freeze the affected branches, prepare the recovery message
- Post-push coordination: notify every clone owner, distribute the recovery commands, handle concurrent pushes that arrived during the window
- Audit the channels the rewrite does not reach: forks, clones, mirrors, CI caches, backups
- Document the incident for the post-mortem (what was rewritten, why, who was notified, what was rotated)
Prerequisites
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
The force-push is the visible step of the rewrite. The aftermath is the coordination work. The pre-push is the announcement; the post-push is the notification and the audit. The team must do all three.
Pre-push communication
Before the force-push, three things must happen:
- Announce the window. The team channel receives a message with the start time, end time, branches, and reason for the rewrite.
- Freeze the affected branches. Every engineer with a clone stops pushing. A freeze banner names the branches and the end of the freeze.
- Prepare the recovery message. A template ready at the
moment of the force-push: the new HEAD SHA, the recovery
command (
git fetch origin && git reset --hard origin/<branch>), and a reminder that uncommitted work is lost.
flowchart LR
A["pre-push"] --> B["announce window"]
A --> C["freeze branches"]
A --> D["prepare recovery message"]
B --> E["force-push --force-with-lease"]
C --> E
D --> E
E --> F["post-push"]
F --> G["notify clone owners"]
F --> H["distribute recovery commands"]
F --> I["audit channels"]
The pre-push is what makes the post-push safe. Without the freeze, concurrent pushes arrive during the rewrite window and are silently overwritten; the engineer who pushed them loses work.
Post-push coordination
At the moment of the force-push, three things happen:
- Send the recovery message. The template is filled in with the new HEAD SHA and broadcast to the team channel. Every engineer with a clone has the recovery command.
- Notify every clone owner. If the repository has external contributors (a fork, a contractor, a partner), notify the owners individually. The contractor’s CI cache must be invalidated; the partner’s mirror must be reset.
- Handle concurrent pushes. If
--force-with-leaserejected the push (the remote had commits the local repository did not see), the engineer reviews the new commits, integrates them into the rewrite, and re-pushes. The integration is itself a rewrite; the team must be told that the window extends.
The recovery command for a typical clone:
git fetch origin
git reset --hard origin/main
The command discards the clone’s local commits and resets to the rewritten remote. Any uncommitted work in the clone is lost; the engineer must re-apply from a backup or re-create the work.
The audit
The rewrite does not reach every channel. The audit is the step that finds the channels and treats them:
- Forks. Every fork created before the rewrite has the original history. The forge cannot rewrite forks owned by other users; the team must contact the fork owner or treat the fork as a compromised channel.
- Clones. Every
git cloneperformed before the rewrite has the original history on the engineer’s machine. The recovery command resets the clone. - Mirrors. Every read-only mirror has the original history. The mirror operator must be told to reset.
- CI caches. The CI runner’s cache, the artifact store, the dependency-proxy cache. Invalidated and rebuilt from the rewritten history.
- Backups. The forge’s off-site backups, the S3 snapshots, the disaster-recovery archive.
The audit is the only step that finds the channels.
The post-mortem
After the audit, the incident is documented:
- What was rewritten. The expressions.txt file, the paths removed, the new SHAs.
- Why. The credential rotation, the large file, the identity correction.
- Who was notified. The team channel, the contractors, the partners.
- What was rotated. The credentials, the keys, the tokens. The rotation is the fix; the rewrite is the hygiene.
- What was missed. The channels the rewrite did not reach.
Production discipline
- Pre-push is mandatory. Announce the window, freeze the branches, prepare the recovery message. The pre-push is what makes the post-push safe.
--force-with-leasealways. The safety catch against clobbering commits that landed during the rewrite window. If the push is rejected, the window extends.- Audit every channel. Forks, clones, mirrors, CI caches, backups. The audit is the only step that finds the channels the rewrite cannot reach.
Cross-course references
- Linux for Production Sysadmins - Part XXXIV (ConfigMgmt) covers the backup retention that the audit must reach.
- Ansible for Production Sysadmins - Part XXXVII (RepoArch) covers the mirror updates that have to follow the audit.
- Terraform for Production Sysadmins - Parts IX-XII (State) cover the state-file backups that the audit must reach.
Quiz
Knowledge check · 4 questions
Q1. What are the three pre-push steps that must happen before a history-rewrite force-push?
Q2. After a successful git filter-repo rewrite and force-push, the rewrite has reached every channel that originally had the history.
Q3. Name the five channels the audit must reach after a history rewrite.
Q4. A team force-pushes a history rewrite without pre-push communication. Diagnose the failure.
Time T0: engineer E runs git filter-repo on a fresh clone and force-pushes with --force-with-lease. No announcement was made; no freeze was declared; no recovery message was prepared. Time T0+5m: engineer F's push to the same branch is silently overwritten by the force-push. Engineer F reports their work is lost. Time T0+1h: contractor C reports the contractor's CI cache still contains the original blob.
Passing score: 75%. Answers are checked in this browser.