Re: using --force-with-lease after git rebase
- Date: Thu, 01 Nov 2018 10:19:55 +0900
- From: Junio C Hamano <gitster@xxxxxxxxx>
- Subject: Re: using --force-with-lease after git rebase
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:
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
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 ;-)
*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.
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'.