Replace the contents or history of a Git main branch
Choose between a normal commit that replaces main’s files and an explicitly coordinated rewrite of the branch history.
First decide what “replace main” means. You can make its tracked files match another branch while preserving the existing history, or move the branch itself to a different commit. The second operation rewrites shared history when published and needs explicit team coordination.
Replace the tracked snapshot with a normal commit
For most content replacements, use a dedicated branch from the current remote main. Preserve unfinished work first and start from a clean checkout:
git fetch origin
git switch -c replace-main-content origin/main
git restore --source=new-main-content --staged --worktree -- :/
git diff --cached --stat
git diff --cached
git commit -m "Replace main content with reviewed snapshot"
The root pathspec :/ applies to the whole repository. git restore also removes tracked files absent from the replacement tree. It does not sweep away all unrelated untracked or ignored files. Review submodule state separately if the repository uses submodules.
Test the result and submit it through the normal review process. This records the replacement as a new commit without resetting main or bypassing branch protection.
An ancestry-preserving ours merge
Another technique starts on the replacement branch, merges main with git merge -s ours main, and then fast-forwards main to the result. The ours strategy keeps the current branch's tree; running it on main would retain the old content instead.
This technique has limits. If main is already an ancestor, Git can report “Already up to date.” Unrelated histories require a separate, deliberate decision. Later movement of main can prevent the expected fast-forward. It also records main's changes as merged even though their content was discarded, affecting future merges. Prefer the ordinary snapshot replacement when that is the intended change.
Move main to another commit
If rewriting the branch is explicitly intended, keep a recovery ref and preserve uncommitted work before resetting. This example captures the expected remote tip for the lease:
git fetch origin
git branch backup/main-before-replacement origin/main
expected=$(git rev-parse refs/remotes/origin/main)
git switch main
git reset --hard new-main-content
git push --force-with-lease="refs/heads/main:$expected" origin main:main
The lease rejects a push if the server tip differs from the captured value. It does not make removing reviewed remote commits harmless. Follow branch protection and your team's approval process.
After a coordinated rewrite, collaborators should save local work, fetch, and decide how to move their own branches. git reset --hard origin/main discards local tracked changes and branch commits; it is appropriate only when those are intentionally abandoned.
A backup branch or tag retains old committed history while that ref exists. Store the backup where the team can recover it; a local tag is not automatically published or permanent.
References: git restore, git merge, and git push.
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan