If you’re still using git push --force (or git push -f), I hope you’ll read my post Never use git push force.
If you’re using git push --force-with-lease (or using the git please alias), git will only force push changes if your local copy is aware of all of the commits on the remote branch but how is git “aware” of the commits.
Someone Else Pushed a Commit
In the following example, while you were creating commit dg34mp on your local branch someone else posted a new commit (zyx911) on the remote origin/master branch.
master origin/master (remote)
dg34mp zyx911
cem32k cem32k
b4d2o1 b4d2o1
abc123 abc123
When you try to git push, you’ll get the error
error: failed to push some refs
Even if you try git push --force-with-lease, the operation will fail and you’ll get the same error message.
You Modified a Commit
On the other hand, if you have a local copy
sal-dev origin/sal-dev (remote)
crsc14 crsc14
bu24ox bu24ox
akw82n akw82n
and you modify your commit, replacing crsc14 with a new updated commit (kl055q).
sal-dev origin/sal-dev (remote)
kl055q crsc14
bu24ox bu24ox
akw82n akw82n
git push will still fail, but git push --force-with-lease will work!
The Local Copy of Your Remote Branch
The secret to git push --force-with-lease is your local install includes a copy of the remote branch. When deciding whether or not to force push, git push --force-with-lease checks both the current branch and the local copy of the remote branch when looking for commits that match those on the remote.
Let’s look at these two scenarios again and include our local copy of the remote branch.
You Modified a Commit
Initially, all three branches were in sync.
sal-dev origin/sal-dev (local) origin/sal-dev (remote)
crsc14 crsc14 crsc14
bu24ox bu24ox bu24ox
akw82n akw82n akw82n
but when we modified our commit, replacing crsc14 with a new updated commit (kl055q)
sal-dev origin/sal-dev (local) origin/sal-dev (remote)
kl055q crsc14 crsc14
bu24ox bu24ox bu24ox
akw82n akw82n akw82n
our local copy of origin/sal-dev was still aware of crsc14, so git push --force-with-lease worked.
Someone Else Pushed a Commit
Initially, all three branches are in sync.
master origin/master (local) origin/master (remote)
cem32k cem32k cem32k
b4d2o1 b4d2o1 b4d2o1
abc123 abc123 abc123
When we add a new commit (dg34mp) and during the same timeframe someone else adds a new commit to the remote (zyx911), we become out of sync.
master origin/master (local) origin/master (remote)
dg34mp zyx911
cem32k cem32k cem32k
b4d2o1 b4d2o1 b4d2o1
abc123 abc123 abc123
Now our local copy is unaware of commit zyx911 because it does not appear in any of our local branches (neither master nor our local origin/master), therefore git push --force-with-lease will fail.
The correct way to resolve this situation is not to use --force nor --force-with-lease, instead you should pull in the changes from the remote origin/master – see my Git failed to push some refs post.
Leave a Reply