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