git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 2/2] Teach the --no-ff option to 'rebase -i'.

From
Junio C Hamano <gitster@pobox.com>
Date
Mar 24, 2010, 19:06 UTC
Message-ID
<7vfx3pilo1.fsf@alter.siamese.dyndns.org>
In-Reply-To
<1269445261-2941-3-git-send-email-marcnarc@xiplink.com>
Marc Branchaud <marcnarc@xiplink.com> writes:
> This option tells git-rebase--interactive to cherry-pick all the commits in
> the rebased branch, instead of fast-forwarding over any unchanged commits.
Thanks.
Show 28 quoted lines
> +Sometimes you're in a situation like this
> +
> + P---o---o---M---x---x---W---x
> +  \         /
> +   A---B---C
> +
> +where W is the reversion of merge M and you:
> +
> + - Need to rewrite one of the commits on the A-B-C branch; and
> +
> + - Want the rewritten A-B-C branch to still start at commit P (perhaps P
> +   is a branching-off point for yet another branch, and you want be able to
> +   merge A-B-C into both branches).
> +
> +The natural thing to do in this case is to checkout the A-B-C branch and use
> +"rebase -i A" to change commit B.  However, this does not rewrite commit A,
> +and you end up with this:
> +
> + P---o---o---M---x---x---W---x
> +  \         /
> +   A---B---C   <-- old branch
> +   \
> +    B'---C'    <-- rewritten branch
> +
> +To merge A-B'-C' into the mainline branch you would still have to first revert
> +commit W in order to pick up the changes in A, but then it's likely that the
> +changes in B' will conflict with the original B changes re-introduced by the
> +reversion of W.

I find it somewhat a contrived and unconvincing explanation. A moderately intelligent reader would wonder "Why did you choose to 'rebase -i A' in the first place? if you did 'rebase -i P' instead, you didn't have to suffer from this issue, no?", and you are not answering that question.

Two things that you are assuming but not telling the user to make this explanation appear unsatisfactory are:

 - The true reason you reverted M turns out to be that B was bad, and A
   was fine, so you want to fix B in A-B-C and merge it to master; and
 - Because "rebase -i" by default fast-forwards earlier "pick", even
   "rebase -i P" wouldn't have given you a rewritten A.
If you spell these out, then the explanation starts to make sense.
Show 8 quoted lines
> +However, you can avoid these problems if you recreate the entire branch,
> +including commit A:
> +
> + P---o---o---M---x---x---W---x
> + |\         /
> + | A---B---C   <-- old branch
> + \
> +  A'---B'---C' <-- entirely recreated branch

This is just an advice on drawing, but you can avoid this ugly picture by starting your discussion with:

      A---B---C
     /         \
    P---o---o---M---x---x---W---x
and adding the reproduction like this:
      A---B---C
     /         \
    P---o---o---M---x---x---W---x
     \
      A'--B'--C'
Show 10 quoted lines
> +But if you don't actually need to change commit A, then you need some way to
> +recreate it as a new commit with the same changes in it.  The rebase commmand's
> +two modes (interactive and non-interactive) provide options to do this.  With
> +"rebase -i" use the --no-ff option:
> +
> +    $ git rebase -i --no-ff P
> +
> +With plain "rebase" use the -f option:
> +
> +    $ git rebase -f P

This is exactly why I don't mind giving a --no-ff synonym for --force to non-interactive rebase. That would make the choice between -i and no -i made by the reader solely depend on the need to change anything in the commits. If you are fixing B in A-B-C, you would use "rebase -i". If instead you queued a fix-up as D, like so:

      A---B---C-------------------D
     /         \
    P---o---o---M---x---x---W---x

then you can rebase non-interactively the whole thing in preparation for another merge:

      A---B---C---D
     /         \
    P---o---o---M---x---x---W---x...*
     \                             /
      A'--B'--C'------------------D'
Previous: Marc BranchaudNext: Jonathan Nieder
Message 27 of 32 in “Teach --no-ff option to 'rebase -i'.”
  1. Teach --no-ff option to 'rebase -i'.Marc Branchaud, Mar 16, 2010
  2. Marc BranchaudMar 16, 2010
  3. [PATCHv2] Teach --no-ff option to 'rebase -i'.Marc Branchaud, Mar 16, 2010
  4. Jonathan NiederMar 16, 2010
  5. Johannes SixtMar 17, 2010
  6. Peter BaumannMar 17, 2010
  7. Johannes SixtMar 17, 2010
  8. Peter BaumannMar 17, 2010
  9. Johannes SixtMar 18, 2010
  10. Peter BaumannMar 18, 2010
  11. Marc BranchaudMar 17, 2010
  12. Johannes SixtMar 17, 2010
  13. Marc BranchaudMar 17, 2010
  14. Test that the 'rebase -i' "reword" command always cherry-picks a commit.Marc Branchaud, Mar 22, 2010
  15. Avery PennarunMar 22, 2010
  16. Marc BranchaudMar 22, 2010
  17. Junio C HamanoMar 22, 2010
  18. Marc BranchaudMar 23, 2010
  19. [PATCHv3] Teach -f/--force-rebase option to 'rebase -i'.Marc Branchaud, Mar 23, 2010
  20. Junio C HamanoMar 23, 2010
  21. 0/2 Teach the --no-ff option to 'rebase -i'.Marc Branchaud, Mar 24, 2010
  22. Junio C HamanoMar 24, 2010
  23. [PATCHv5] Teach rebase the --no-ff option.Marc Branchaud, Mar 24, 2010
  24. Junio C HamanoMar 24, 2010
  25. 1/2 Teach 'rebase -i' to accept and ignore the -f/--force-rebase option.Marc Branchaud, Mar 24, 2010
  26. 2/2 Teach the --no-ff option to 'rebase -i'.Marc Branchaud, Mar 24, 2010
  27. Junio C HamanoMar 24, 2010
  28. Jonathan NiederMar 23, 2010
  29. Jonathan NiederMar 22, 2010
  30. Marc BranchaudMar 17, 2010
  31. Jonathan NiederMar 17, 2010
  32. Jonathan NiederMar 17, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.