PUBLIC SERVICE ANNOUNCEMENT
If you’ve ever modified a Git repository’s history, undoing, redoing or rebasing commits, you’ll have met the -f option to git push.
While the normal push command will only push new commits on top of the existing history, refusing to overwrite anything in any way, the -f option will completely obliterate the existing remote branch and replace it with what you’re pushing.
This is usually what you want. The whole point is to replace the incorrect/inconvenient history with your modified version. But there’s one risk. Imagine the following sequence of events:
- You pull a remote branch, and start rebasing your changes onto it, preparing a new branch to push.
- Someone else quickly pushes a new commit.
- You use push -f; their commit is now gone.
Annoying? Yes. Unlikely? Also admittedly yes. But you can now guarantee this never happens! Simply use --force-with-lease instead of -f.
Git will then abort the push and warn you if the remote branch is different from what it was last time you fetched it.
bringing back convenience
Sadly -f can’t be changed to do this perfectly sensible thing by default, as literally dozens of scripts could potentially rely on it never failing. So, we are stuck having to autocomplete this huge option instead.
Well, actually, no. Aliases are a great solution to this kind of problem. If you use oh-my-zsh you’ve probably already noticed that its Git plugin provides a whole bunch. In addition, I like to define a few more in my .zshrc file, including the aforementioned alternative to -f:
alias gff="git fetch" alias gpl="git pull" alias gpr="git pull --rebase" alias gpp="git push" alias gppf="git push --force-with-lease" alias gitka="gitk --all&" alias tiga="tig --all" alias gs="git status -s" # Who uses Ghostscript anyway?! alias gss="git status -s" # I can't type. alias gsss="git status -s"
Hopefully this is interesting, even if it’s unlikely to actually make any significant difference to anything. Thanks for reading and have fun!