Alexander Mills <alexander.d.mills@xxxxxxxxx> writes: > I have been confused about the need for --force-with-lease after rebasing > > Imagine I have a feature branch: > > git checkout --no-track -b 'feature' 'origin/dev' > git push -u origin feature > > I do some work, and then I rebase against origin/dev to keep up to > date with the integration branch. > > git fetch origin/dev > git rebase origin/dev > > then I try to push to the remote > > git push origin feature > > but that is rejected, I have to do: This all depends on how the "dev" branch at the "origin" remote relate to the branch at "origin" you are updating with the commit at the tip of the "feature" branch. Are you pushing to "feature" branch? If so, then the rejection is very much expected. At this point, the histories of the "feature" branch at the "origin" remote is seeing would look like this: ---X---o---o---o---o---A \ x---x---x---x---B where (X) is where you started the old iteration of the "feature" branch forking off of the "dev" branch, (A) is the tip of that old iteration of the "feature" branch, and (B) is the tip of the new itertion of the "feature" branch you are trying to update with. The "origin" repository does not know WHY B is not a fast-forward of A. The only thing it knows is that you are discarding the work done in commits (o) while attempting to publish commits (x). If it is intentional, then that's fine, but it does not know (x) are replacements for (o) due to rebasing, so it errs on the side of the caution. With the "--force-with-lease=feature:A" option, you can tell the other side: "it is OK if this push does not fast-forward, as long as I am updating from A" [*1*]. "--fore-with-lease" without saying what the commit you are expecting to discard makes Git on the sending side _guess_. Depending on what you do locally, it can make a wrong guess, so I would not recommend such a use, but if you saw it succeed and if you did not lose commits at the "origin", then it may have guessed correctly ;-) [Footnote] *1* Telling what the value of 'A' is to the other side is important, as you are essentially saying that 'B' has everything you want to resurrect from 'A'. Imagine that somebody else pushed to update "feature" at the "origin" remote from 'A' to 'C' (or if you did so and forgot about it) and then you tried to push 'B' after rebasing. C / ---X---o---o---o---o---A \ x---x---x---x---B As far as you (who rebased) were concerned, 'B' is equivalent to (or "an improved version of") 'A' and you want the push that does not fast-forward to go through to replace 'A' with 'B'. By telling "I am replacing A with B" (instead of saying "I am replacing whatever with B", which is what "--force" is), the receiving side at the "origin" repository can notice that there was another update by somebody else's push to the branch while you are preparing 'B' and the tip of "feature" is no longer at 'A', and reject the push in order to prevent you from losing the work between 'A' and 'C'.