Replies: 3 comments 9 replies
-
What's the command you used to rebase? |
Beta Was this translation helpful? Give feedback.
-
My complete "failing" repro script is:
(my apologies for the script length / the fast-import - this is a repro case I have been reusing across multiple configurations and clients) |
Beta Was this translation helpful? Give feedback.
-
For comparison, the following script, where there is an extra unrelated commit before the merge, and that previous commit is the thing we ask to rebase, works cleanly -
|
Beta Was this translation helpful? Give feedback.
-
Background: Why Rebasing Merges matters
Supporting a large group of developers, on a large project, with most users being relatively inexperienced with git, one of my big frustrations with that system is the way merges and rebases don't work together:
We generally recommend merging over rebasing, because branches are often shared and rebasing shared branches (where many/most users aren't rebasing experts) is a recipe for disaster. Generally, that policy ("just don't rebase unless you really know what you're doing; always default to merging") works well for us.
Occasionally however, a user will end up rebasing a previous merge of
main
onto another topic/feature branch, by accident because of a bad GUI, or because they don't know better. When you rebase a merge commit in git (without--rebase-merges
), all the merged-in commits (in the typical flow here, all themain
commits that were merged in) get rebased onto the target branch - they effectively get duplicated - which is absolutely not what you want, of course.In git, this can be fixed-ish using
--rebase-merges
, which automatically recreates merge commits / attempts to replicate the merge topology when you rebase. It's not a panacea by any means because previously resolved conflicts need to be re-resolved (unless you're also usingrerere
are your conflicts are isolated), but it's more reasonable than the default behavior, in the scenario above, at least.A naive rebase of a merge commit in
jj
"flattens" it...?When I first tried this scenario in JJ, I found two surprises:
jj resolve
refused to run on, and with conflict markers that were unintelligible to me (I couldn't understand what the different bases were supposed to be)jj squash
ed andjj log
ged, only to find that the merge commit I rebased had turned into a regular single-parent commit.I understood later from the answers below that this outcome came about because of the way I specified the merge commit in the
-s
arg, and only the single new parent commit in-d
, which toldjj
to rebase as a simple single commit; the weird 3-way conflict, I think I now understand, wasjj
showing me that there were two sets of parent-child changes to collapse into a new single-parent commit.As I later noted in #3727 (comment), if the merge commit is a child of the commit provided in the
-s
arg, everything works as you would expect, magically wrt git.@bnjmnt4n has noted that it is possible to specify a
-d
argument that specifies the right parent commit(s) for such a rebase, but it's a bit of a mouthful: #3727 (reply in thread). Can/should there be a more "natural" way of doing the equivalent ofgit pull --rebase=merges
?Beta Was this translation helpful? Give feedback.
All reactions