2020: I mention in "Is git push --force-with-lease
always safe?" the new option
git push --force-if-includes
Add a check to verify if the remote-tracking ref of the local branch is reachable from one of its "reflog" entries.
Alexey Romanov refers in the comments to:
"When should I use "git push --force-if-includes
", which adds more details.
2017:
I'm worried that I might forget about this nifty feature the next time I need it.
Git 2.13 (Q2 2017) explains why there is no "protection" against this push option being forgotten, because even if you do not forget it at the git push
level, it might still be ignored.
See commit f17d642 (19 Apr 2017) by Ævar Arnfjörð Bjarmason (avar
).
(Merged by Junio C Hamano -- gitster
-- in commit 46bdfa3, 26 Apr 2017)
push
: document & test --force-with-lease
with multiple remotes
Document & test for cases where there are two remotes pointing to the
same URL, and a background fetch & subsequent git push --force-with-lease
shouldn't clobber un-updated references we haven't fetched.
Some editors like Microsoft's VSC have a feature to auto-fetch in the
background, this bypasses the protections offered by --force-with-lease
& --force-with-lease=<refname>
, as noted in the documentation being added here.
So the documentation for git push
now includes:
general note on safety: supplying this option without an expected value, i.e. as --force-with-lease
or --force-with-lease=<refname>
interacts very badly with anything that implicitly runs git fetch
on the remote to be pushed to in the background, e.g. git fetch origin
on your repository in a cronjob.
The protection it offers over --force
is ensuring that subsequent changes your work wasn't based on aren't clobbered, but this is trivially defeated if some background process is updating refs in the background. We don't have anything except the remote tracking info to go by as a heuristic for refs you're expected to have seen & are willing to clobber.
If your editor or some other system is running git fetch
in the
background for you, a way to mitigate this is to simply set up another
remote:
git remote add origin-push $(git config remote.origin.url)
git fetch origin-push
Now when the background process runs git fetch origin
the references
on origin-push
won't be updated, and thus commands like:
git push --force-with-lease origin-push
Will fail unless you manually run git fetch origin-push
.
This method is of course entirely defeated by something that runs git fetch --all
, in that case you'd need to either disable it or do something
more tedious like:
git fetch # update 'master' from remote
git tag base master # mark our base point
git rebase -i master # rewrite some commits
git push --force-with-lease=master:base master:master
I.e. create a base
tag for versions of the upstream code that you've seen and are willing to overwrite, then rewrite history, and finally force push changes to master
if the remote version is still at base
, regardless of what your local remotes/origin/master
has been updated to in the background.
rm
torm -i
in your .bashrc; you'll forget and delete an important file on a server some day. Going with your own alias doesn't have that problem :) – Clarindaclarine