There is a command in Git that strikes fear into the hearts of experienced developers. A command that can destroy hours of work with a single keystroke. A command that has caused more team conflicts than any other: git push --force.
But force pushWhat is force push?A destructive Git push that overwrites the remote branch history with your local version, which can break teammates' work if they already pulled the original. is not evil. It is a powerful tool that exists for legitimate reasons. The problem is using it without understanding the consequences. When you know when, why, and how to use it safely, it becomes just another tool in your toolkit.
git push --force as a standard step. ChatGPT in particular will suggest force push as a quick fix for diverged branches. In a team environment, this casual advice can overwrite days of work in seconds.Why force pushWhat is force push?A destructive Git push that overwrites the remote branch history with your local version, which can break teammates' work if they already pulled the original. exists
Git is distributed. Your local repositoryWhat is repository?A project folder tracked by Git that stores your files along with the complete history of every change, inside a hidden .git directory. is independent of the remote. Sometimes they diverge in ways that a normal push cannot resolve:
| Scenario | Why force push is needed |
|---|---|
| Rebased feature branch | Commit hashes changed, Git sees them as "different" |
| Amended commit | git commit --amend changes the hash |
| Personal branch cleanup | You cleaned up messy commits before a PR |
| Removing sensitive data | Passwords or API keys need to be erased from history |
In all these cases, you intentionally changed history locally and need the remote to match.
The danger explained
Normal push adds new commits on top of what is already on the remote:
Local: A---B---C (main)
Remote: A---B (main)
After push:
Remote: A---B---C (main)Force pushWhat is force push?A destructive Git push that overwrites the remote branch history with your local version, which can break teammates' work if they already pulled the original. replaces the remote history with your local history:
Local: A---B---C'--D' (main) [you rewrote history]
Remote: A---B---C---D (main)
After force push:
Remote: A---B---C'--D' (main)
Commits C and D are GONE from the remote.The team disaster scenario:
- You push commits to main
- Alice pulls those commits and starts building on them
- You force push to "fix" something
- Alice tries to push her work
- Chaos. Alice's work conflicts with the rewritten history. Commits are lost.
Force with lease: the safer alternative
git push --force-with-leaseBefore pushing, Git checks if anyone has pushed to the branch since your last fetch. If the remote changed, the push fails with an error instead of overwriting.
| Scenario | --force | --force-with-lease |
|---|---|---|
| Remote unchanged | Pushes | Pushes |
| Someone else pushed | Overwrites their work | Fails safely |
| You did not fetch recently | May overwrite | Fails safely |
Always use --force-with-lease instead of bare --force.
The golden rules
Never force pushWhat is force push?A destructive Git push that overwrites the remote branch history with your local version, which can break teammates' work if they already pulled the original. on:
mainormasterdevelopor release branches- Any branch multiple people work on
- Any branch with open pull requests
Acceptable to force push on:
- Your personal feature branch (that only you touch)
- After rebasing your branch (before creating a PR)
- To remove sensitive data (inform the team first)
Safe force pushWhat is force push?A destructive Git push that overwrites the remote branch history with your local version, which can break teammates' work if they already pulled the original. workflow
# 1. Always fetch first
git fetch origin
# 2. Check what you are about to overwrite
git log --oneline origin/my-branch..my-branch
# 3. Confirm no one else has pushed
git log --oneline my-branch..origin/my-branch
# Should show nothing
# 4. If safe, use force-with-lease
git push --force-with-leaseThe better alternative: revert
Before force pushing to "fix" a mistake on a shared branch, consider reverting:
# Instead of (dangerous):
git reset --hard HEAD~3
git push --force
# Do this (safe):
git revert HEAD~2..HEAD
git pushRevert creates new commits that undo changes. The old commits stay in history. It is the safe, collaborative way to undo mistakes on shared branches.
If you accidentally force pushed
Do not panic. Act quickly:
# 1. Tell your team: "Don't pull from main!"
# 2. Find the old commits
git reflog
# 3. Restore the branch
git reset --hard <old-commit-hash>
git push --force-with-lease
# 4. Tell your team it is safe nowgit reflog to find the old commit hashes and restore the branch.Quick reference
| Command | Safety | Use case |
|---|---|---|
git push --force | Dangerous | Only if you are 100% certain |
git push --force-with-lease | Safer | Preferred for all force pushes |
git revert | Safe | Always preferred for shared branches |
git reflog | Recovery | Find old commits after accidental force push |