- Published on
git push --force-with-lease: The Safer Force Push
- Authors

- Name
- Sarah Murdock
We've all been there. You rebased your branch, cleaned up your commits, and now git is telling you to force push. Your finger hovers over --force. You do it. And then a teammate pings you: "hey, did you just wipe my commits?"
--force-with-lease exists specifically to prevent that. Here's how it works.
The problem with --force
When you rebase or amend commits, you rewrite history. Git sees your local branch and the remote branch as diverged — meaning they've gone in different directions from a common point and no longer share the same tip commit. Think of it like two people editing the same document simultaneously: once both make changes, neither version is simply "ahead" of the other. A normal git push will refuse to overwrite that. So you reach for --force.
The issue is that --force is absolute. It says: my version is correct, overwrite whatever is on the remote, no questions asked. If a teammate pushed new commits to that branch while you were rebasing, --force will silently delete them.
Each node is a commit — a saved snapshot of the code at a point in time. After you rebase, your local my-feature and the remote my-feature have gone in different directions: the remote has teammate pushes, yours has your rebase. A --force push overwrites the remote with your version, silently erasing your teammate's commit.
# ⚠️ This doesn't care what's already on the remote
git push --force origin my-feature
This is especially risky on shared branches.
What --force-with-lease does differently
--force-with-lease adds a safety check. Before overwriting the remote, Git verifies that the remote branch tip matches what you last fetched. If someone else pushed in the meantime, your push fails — loudly, before any damage is done.
# ✅ This will fail if the remote has commits you haven't seen
git push --force-with-lease origin my-feature
Think of it as: "force push, but only if nothing has changed since I last looked."
Side by side
| Command | What it does | Risk |
|---|---|---|
git push | Pushes if no divergence, refuses otherwise | Safe, but won't work after a rebase |
git push --force | Overwrites remote unconditionally | Can delete teammates' commits |
git push --force-with-lease | Overwrites only if remote matches your last fetch | Safe for rebased branches |
A typical workflow
Here's what using it actually looks like day-to-day:
# 1. Rebase your branch onto main to clean up history
git fetch origin
git rebase origin/main
# 2. Force push safely — will fail if someone else pushed in the meantime
git push --force-with-lease origin my-feature
If the push fails, it means the remote changed since your last fetch. Fix it by fetching and rebasing again:
git fetch origin
git rebase origin/my-feature
git push --force-with-lease origin my-feature
The one gotcha
--force-with-lease checks your local ref — specifically, what your remote-tracking branch (origin/my-feature) points to. If you ran git fetch right before pushing, that ref is up to date, and the lease check passes — even if new commits exist on the remote.
⚠️ Running
git fetchbeforegit push --force-with-leaseeffectively defeats the safety check. The lease only protects you if your local remote-tracking ref is stale.
In practice, just don't git fetch right before a force push without also reviewing what came in.
When to use it
- After rebasing a feature branch onto
main - After amending commits with
git commit --amend - Cleaning up a PR with interactive rebase (
git rebase -i) before merging - Any time git refuses a push because of diverged history
When not to use it
- On
mainor any shared long-lived branch — rewriting shared history causes problems for everyone, regardless of which force flag you use - When you actually want to discard remote commits intentionally (rare, and worth double-checking)
--force-with-lease won't save you from every mistake, but it closes the most common one: the silent overwrite. It's a small habit that makes force pushing a lot less scary to do — and a lot less scary for the people who work on the same branches as you.1
Footnotes
For the full details, see the official Git documentation on push options. ↩