HOWTO · Git
Git Push --force-with-lease vs Git Push --force
Compare git push --force and git push --force-with-lease, then choose a safer way to update a remote branch after rewriting history.
On this page
When a rebase or amend changes commits already published, a normal push may be rejected because the remote branch no longer fast-forwards from your local branch. Both git push --force and git push --force-with-lease can replace the remote branch tip. The difference is whether Git checks an expected remote value before updating it. Prefer the lease form for an intentional rewrite, then inspect and reconcile the remote if Git rejects the push.
How git push --force works
A normal push protects remote commits by requiring the update to move the branch forward. git push --force disables that protection for the ref being pushed: the remote branch is set to the commit you specify, even when that removes commits from its visible history. If a teammate pushed work you have not incorporated, that work can become unreachable from the branch.
The command is scoped by its destination. For example, git push --force origin feature targets the feature branch on origin; omitting a clear branch name can make the affected ref less obvious. Use force only when replacing the branch history is intentional and coordinated with everyone using it. A force push does not create a merge conflict or combine the remote commits for you.
How git push --force-with-lease works
git push --force-with-lease origin feature also permits a non-fast-forward update, but first checks that the remote branch still has the expected value. In its common form, Git derives that expectation from the local remote-tracking ref, such as origin/feature. If the server’s branch value differs, Git rejects the update instead of replacing it.
That check is useful, but it is not proof that nobody has pushed unseen work. If a background fetch updates origin/feature after you last reviewed it, the default lease may accept a rewrite against that newly fetched value. An explicit expected object ID makes the comparison deliberate: git push --force-with-lease=refs/heads/feature:<expected-object-id> origin HEAD:refs/heads/feature. Obtain and review the expected value as part of your team workflow; do not copy an ID without checking what it represents.
Use --force-with-lease after rewriting history
Suppose the shared branch was A---B---C, a collaborator added D on top of C, and you rebased your local work to produce A---B---C'. Your local C' and the remote D now represent different tips. A lease is intended to stop you from silently replacing D when your expected remote state is still C.
First inspect the branch and fetch its current state. Then decide whether the collaborator’s commit belongs in your rewritten history. You might rebase your work on the fetched branch, or coordinate another integration plan with the team. After resolving and reviewing the history, push the intended result with a lease. If the lease rejects the push, fetch and inspect again; do not immediately retry with --force.
Run this self-contained demonstration to create a local branch, publish it to a temporary bare repository, amend its tip, and update it with a lease:
set -e
root="$(mktemp -d)"
trap 'rm -rf "$root"' EXIT
git init --bare "$root/remote.git" >/dev/null 2>&1
git init -b feature "$root/work" >/dev/null 2>&1
cd "$root/work"
git config user.name "Example Developer"
git config user.email "developer@example.com"
printf 'first version\n' > README.md
git add README.md
git commit -m "Add first version" >/dev/null 2>&1
git remote add origin "$root/remote.git"
git push -u origin feature >/dev/null 2>&1
git commit --amend -m "Rewrite first version" >/dev/null 2>&1
git push --force-with-lease origin feature >/dev/null 2>&1
The paths are temporary and the script removes its fixture when it exits. In a real repository, inspect the commits and coordinate with collaborators before replacing shared history.
Choose a force-push option safely
For a personal branch with no collaborators, a direct force push may be acceptable if replacing its remote tip is intended. On a shared branch, choose --force-with-lease after reviewing the expected remote state and coordinating the rewrite. Prefer a pull request or another review workflow when it can avoid rewriting a shared branch altogether.
Keep the remote and branch explicit, fetch before making a decision, and review the commit graph before pushing. A lease rejection is a safety signal: compare your local branch with the fetched remote branch, preserve any needed commits, and retry only after deciding how they fit. Regular synchronization reduces surprises, but it does not replace review of the history that the push will publish.
Recover or prevent lost commits
If a force push removed a commit from the branch tip, stop making cleanup changes and look for a retained reference. In your local clone, git reflog may show recent branch positions; another collaborator’s clone, a remote backup, or a hosting provider’s recovery feature may also retain the commit. If you find the commit, create a branch at it before deciding how to restore or integrate it. Reflog entries expire and are local, so recovery is not guaranteed.
Prevent loss by agreeing on who may rewrite a shared branch, telling collaborators before the update, and preserving a known reference when a rewrite needs review. A lease reduces one class of accidental overwrite, while clear coordination and a verified recovery point address risks it cannot detect.
FAQ
What is the difference between git push --force and git push --force-with-lease? The first replaces the remote ref without checking its current value. The second checks an expected value and rejects the update when the remote does not match it.
When may I use git push --force? Use it only when you intend to replace the target branch tip, understand which commits may leave that branch, and have coordinated with affected collaborators. For shared work, prefer a lease and inspect its expected state.
Is force pushing dangerous on a shared branch? It can hide commits from the branch and disrupt collaborators’ work. A lease helps when the remote differs from the expected value, but its default expectation can be updated by a fetch you did not review.
How can I reduce conflicts or surprises? Fetch and inspect the remote, integrate collaborators’ commits into the rewritten history as appropriate, communicate the plan, and use review workflows for shared changes.
Can I undo a force push? There is no automatic undo. You may be able to find the previous commit through a reflog, another clone, or a provider’s recovery feature, then create a reference and coordinate restoration. Availability depends on whether a reference to that commit remains.