What is the difference between these two git commands when force pushing changes?
git push -f origin branch and git push origin +branch
If you're only pushing one branch, there is no difference.
git push -f origin branch
and
git push origin +branch
are exact equivalents. The difference arises when you're pushing more than one branch with a single git push.
In a nutshell, the optional + gives you finer control than -f does: if you're pushing more than one ref at a time, the + allows you to specify which of the pushed refs get force-pushed, whereas --force (or -f) applies to all the refs that are getting pushed.
git-push man page tells youThe most basic form of git push that involve one or more refspec(s) is
git push <repository> <refspec>...
The form that the <refspec>... argument must satisfy is described in the git-push man page thus:
<refspec>...Specify what destination ref to update with what source object. The format of a `<refspec>` parameter is an optional plus `+`, followed by the source object `<src>`, followed by a colon `:`, followed by the destination ref `<dst>`.
So, just to be clear, the syntax for <refspec> is
[+]<src>[:<dest>]
If :<dst> is omitted, the same ref as <src> will be updated... unless the remote.<repository>.push entry (if any) in your Git config says otherwise.
Further down in the git-push man page, you find
By having the optional leading
+, you can tell Git to update the<dst>ref even if it is not allowed by default (e.g., it is not a fast-forward.) This does not attempt to merge<src>into<dst>.
And still further down:
Note that
--forceapplies to all the refs that are pushed, hence using it withpush.defaultset tomatchingor with multiple push destinations configured withremote.*.pushmay overwrite refs other than the current branch (including local refs that are strictly behind their remote counterpart). To force a push to only one branch, use a+in front of the refspec to push (e.ggit push origin +masterto force a push to themasterbranch).
Consider a local repo with two branches, master and develop, which you want to push (with a single git push command) to an origin remote.
git push origin master develop will push both branches, but neither will get force-pushed.
git push origin +master develop will push both branches, but only master will get force-pushed.
git push origin master +develop , conversely, will push both branches, but only develop will get force-pushed.
git push origin +master +develop will force-push both branches. It's an exact equivalent to git push -f origin master develop.