Message ID | 8f6af8d494e0924aef4ae6963b8dca2228dad9b1.1627776462.git.gitgitgadget@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Switch default merge backend from recursive to ort | expand |
On Sun, Aug 01 2021, Elijah Newren via GitGitGadget wrote: > From: Elijah Newren <newren@gmail.com> > [...] > @@ -3968,7 +3968,7 @@ static int do_merge(struct repository *r, > o.branch2 = ref_name.buf; > o.buffer_output = 2; > > - if (opts->strategy && !strcmp(opts->strategy, "ort")) { > + if (!opts->strategy || strcmp(opts->strategy, "recursive")) { > /* > * TODO: Should use merge_incore_recursive() and > * merge_switch_to_result(), skipping the call to I might spot more tiny issues, but it looks like our error messaging needs updating for 14c4586c2df (merge,rebase,revert: select ort or recursive by config or environment, 2020-11-02). I.e. we die on "Unknown option for merge-recursive", presumably that should be updated to indicate that we might call one of merge_recursive() or merge_ort_recursive() now. And perhaps this in sequencer.c: that represents the "current" state for merge-recursive[...]
On Mon, Aug 2, 2021 at 9:56 AM Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote: > > On Sun, Aug 01 2021, Elijah Newren via GitGitGadget wrote: > > > From: Elijah Newren <newren@gmail.com> > > [...] > > @@ -3968,7 +3968,7 @@ static int do_merge(struct repository *r, > > o.branch2 = ref_name.buf; > > o.buffer_output = 2; > > > > - if (opts->strategy && !strcmp(opts->strategy, "ort")) { > > + if (!opts->strategy || strcmp(opts->strategy, "recursive")) { > > /* > > * TODO: Should use merge_incore_recursive() and > > * merge_switch_to_result(), skipping the call to > > I might spot more tiny issues, but it looks like our error messaging > needs updating for 14c4586c2df (merge,rebase,revert: select ort or > recursive by config or environment, 2020-11-02). > > I.e. we die on "Unknown option for merge-recursive", presumably that > should be updated to indicate that we might call one of > merge_recursive() or merge_ort_recursive() now. Ooh, good catch. I think I'd prefer to reword this to "Unknown strategy option: -X%s" > And perhaps this in sequencer.c: > > that represents the "current" state for merge-recursive[...] Yeah, it's just a comment but it should still be updated. I'll s/merge-recursive/the merge machinery/ for this one. I tried to look for other error messages or comments similar to these two but didn't find anything. I might have missed something, though. I'll get these fixed up with the next submission.
Hi Elijah, On Sun, 1 Aug 2021, Elijah Newren via GitGitGadget wrote: > From: Elijah Newren <newren@gmail.com> > > There are a few reasons to switch the default: > [...] I think it would be really fantastic to change to the new default right after v2.33.0. As to the patch, I only struggled slightly with the changes to `sequencer.c`: > diff --git a/sequencer.c b/sequencer.c > index 0bec01cf38e..a98de9a8d15 100644 > --- a/sequencer.c > +++ b/sequencer.c > @@ -636,7 +636,7 @@ static int do_recursive_merge(struct repository *r, > for (i = 0; i < opts->xopts_nr; i++) > parse_merge_opt(&o, opts->xopts[i]); > > - if (opts->strategy && !strcmp(opts->strategy, "ort")) { > + if (!opts->strategy || strcmp(opts->strategy, "recursive")) { At this stage, we're in `do_recursive_merge()`, and there is only one caller, `do_pick_commit()`, and the caller is guarded by the following condition: else if (!opts->strategy || !strcmp(opts->strategy, "recursive") || !strcmp(opts->strategy, "ort") || command == TODO_REVERT) { The issue I see is with `git revert` allowing custom merge strategies. I _think_ we need a slightly different patch here, something like this: - if (opts->strategy && !strcmp(opts->strategy, "ort")) { + if (!opts->strategy || !strcmp(opts->strategy, "ort")) { > memset(&result, 0, sizeof(result)); > merge_incore_nonrecursive(&o, base_tree, head_tree, next_tree, > &result); > @@ -3968,7 +3968,7 @@ static int do_merge(struct repository *r, > o.branch2 = ref_name.buf; > o.buffer_output = 2; > > - if (opts->strategy && !strcmp(opts->strategy, "ort")) { > + if (!opts->strategy || strcmp(opts->strategy, "recursive")) { It took me a while to convince myself that this is correct. At least now I _think_ it is correct: `do_merge()` defines: const char *strategy = !opts->xopts_nr && (!opts->strategy || !strcmp(opts->strategy, "recursive") || !strcmp(opts->strategy, "ort")) ? NULL : opts->strategy; and then hands off to `git merge -s <strategy>` if `strategy` is set, _before_ this hunk. Therefore we can be pretty certain that `opts->strategy` is either not set, or "ort", or "recursive" at that stage. However, I think we could use the same idea I outlined in the previous hunk, to make things more obvious: - if (opts->strategy && !strcmp(opts->strategy, "ort")) { + if (!opts->strategy || !strcmp(opts->strategy, "ort")) { Thank you, Dscho > /* > * TODO: Should use merge_incore_recursive() and > * merge_switch_to_result(), skipping the call to > -- > gitgitgadget > >
On Mon, Aug 2, 2021 at 4:46 PM Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote: > > Hi Elijah, > > On Sun, 1 Aug 2021, Elijah Newren via GitGitGadget wrote: > > > From: Elijah Newren <newren@gmail.com> > > > > There are a few reasons to switch the default: > > [...] > > I think it would be really fantastic to change to the new default right > after v2.33.0. > > As to the patch, I only struggled slightly with the changes to > `sequencer.c`: > > > diff --git a/sequencer.c b/sequencer.c > > index 0bec01cf38e..a98de9a8d15 100644 > > --- a/sequencer.c > > +++ b/sequencer.c > > @@ -636,7 +636,7 @@ static int do_recursive_merge(struct repository *r, > > for (i = 0; i < opts->xopts_nr; i++) > > parse_merge_opt(&o, opts->xopts[i]); > > > > - if (opts->strategy && !strcmp(opts->strategy, "ort")) { > > + if (!opts->strategy || strcmp(opts->strategy, "recursive")) { > > At this stage, we're in `do_recursive_merge()`, and there is only one > caller, `do_pick_commit()`, and the caller is guarded by the following > condition: > > else if (!opts->strategy || > !strcmp(opts->strategy, "recursive") || > !strcmp(opts->strategy, "ort") || > command == TODO_REVERT) { > > The issue I see is with `git revert` allowing custom merge strategies. I > _think_ we need a slightly different patch here, something like this: > > - if (opts->strategy && !strcmp(opts->strategy, "ort")) { > + if (!opts->strategy || !strcmp(opts->strategy, "ort")) { > > > memset(&result, 0, sizeof(result)); > > merge_incore_nonrecursive(&o, base_tree, head_tree, next_tree, > > &result); > > @@ -3968,7 +3968,7 @@ static int do_merge(struct repository *r, > > o.branch2 = ref_name.buf; > > o.buffer_output = 2; > > > > - if (opts->strategy && !strcmp(opts->strategy, "ort")) { > > + if (!opts->strategy || strcmp(opts->strategy, "recursive")) { > > It took me a while to convince myself that this is correct. At least now I > _think_ it is correct: `do_merge()` defines: > > const char *strategy = !opts->xopts_nr && > (!opts->strategy || > !strcmp(opts->strategy, "recursive") || > !strcmp(opts->strategy, "ort")) ? > NULL : opts->strategy; > > and then hands off to `git merge -s <strategy>` if `strategy` is set, > _before_ this hunk. Therefore we can be pretty certain that > `opts->strategy` is either not set, or "ort", or "recursive" at that > stage. > > However, I think we could use the same idea I outlined in the previous > hunk, to make things more obvious: > > - if (opts->strategy && !strcmp(opts->strategy, "ort")) { > + if (!opts->strategy || !strcmp(opts->strategy, "ort")) { > > Thank you, > Dscho > > > /* > > * TODO: Should use merge_incore_recursive() and > > * merge_switch_to_result(), skipping the call to > > -- > > gitgitgadget I'll include both suggestions in my next re-roll. Thanks for the feedback!
Hi Elijah, Le 2021-07-31 à 20:07, Elijah Newren via GitGitGadget a écrit : > From: Elijah Newren <newren@gmail.com> > > > * `git diff AUTO_MERGE` -- ability to see what changes the user has > made to resolve conflicts so far (see commit 5291828df8 ("merge-ort: > write $GIT_DIR/AUTO_MERGE whenever we hit a conflict", 2021-03-20) > > > The last three have been implemented already (though only one has been > submitted upstream so far; From what I could find this indeed only refers to your 5291828df8 (merge-ort: write $GIT_DIR/AUTO_MERGE whenever we hit a conflict, 2021-03-20). This is a very nice improvement, but I noticed it is not mentioned in the doc. Do you plan to update the 'git diff' doc to mention that special ref ? (And maybe also gitrevisions(5), where most of the special refs are listed ?) Do you plan to implement a new '--auto-merge' option to 'git diff' as a shortcut to 'git diff AUTO_MERGE', in order to hide a bit the special ref from users ? Thanks a lot for your work, Philippe.
Hi Philippe, On Mon, Aug 2, 2021 at 8:56 PM Philippe Blain <levraiphilippeblain@gmail.com> wrote: > > Hi Elijah, > > Le 2021-07-31 à 20:07, Elijah Newren via GitGitGadget a écrit : > > From: Elijah Newren <newren@gmail.com> > > > > > > * `git diff AUTO_MERGE` -- ability to see what changes the user has > > made to resolve conflicts so far (see commit 5291828df8 ("merge-ort: > > write $GIT_DIR/AUTO_MERGE whenever we hit a conflict", 2021-03-20) > > > > > > The last three have been implemented already (though only one has been > > submitted upstream so far; > > From what I could find this indeed only refers to your 5291828df8 (merge-ort: > write $GIT_DIR/AUTO_MERGE whenever we hit a conflict, 2021-03-20). > This is a very nice improvement, but I noticed it is not mentioned in the doc. > Do you plan to update the 'git diff' doc to mention that special ref ? > (And maybe also gitrevisions(5), where most of the special refs are listed ?) > > Do you plan to implement a new '--auto-merge' option to 'git diff' as a shortcut > to 'git diff AUTO_MERGE', in order to hide a bit the special ref from users ? Fair point, it probably does deserve to be documented somewhere, at least once ort is the default merge algorithm. I don't think it'd make sense to include a reference to it in gitrevisions(5), since $GIT_DIR/AUTO_MERGE is a reference to a tree rather than to a revision. But documenting that special ref in Documentation/git-diff.txt, and perhaps linking to it from other conflict-related options (e.g. --base, --ours, --theirs) may make sense. Your --auto-merge idea may also make sense, and it'd be somewhat similar to how git-rebase has a --show-current-patch option that is shorthand for `git show REBASE_HEAD` and is documented as such. However, it might be confusing to users how to combine --auto-merge with paths, whereas `git diff AUTO_MERGE -- pathname` is pretty clear once you know that AUTO_MERGE is a tree you can diff against. Hmmm....
diff --git a/builtin/merge.c b/builtin/merge.c index a8a843b1f54..217c5061eb6 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -88,9 +88,9 @@ static int autostash; static int no_verify; static struct strategy all_strategy[] = { - { "recursive", DEFAULT_TWOHEAD | NO_TRIVIAL }, + { "recursive", NO_TRIVIAL }, { "octopus", DEFAULT_OCTOPUS }, - { "ort", NO_TRIVIAL }, + { "ort", DEFAULT_TWOHEAD | NO_TRIVIAL }, { "resolve", 0 }, { "ours", NO_FAST_FORWARD | NO_TRIVIAL }, { "subtree", NO_FAST_FORWARD | NO_TRIVIAL }, @@ -1484,6 +1484,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix) fast_forward = FF_NO; } + if (!use_strategies && !pull_twohead && + remoteheads && !remoteheads->next) { + char *default_strategy = getenv("GIT_TEST_MERGE_ALGORITHM"); + if (default_strategy) + append_strategy(get_strategy(default_strategy)); + } if (!use_strategies) { if (!remoteheads) ; /* already up-to-date */ diff --git a/builtin/rebase.c b/builtin/rebase.c index 12f093121d9..587a2f1d299 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -1713,7 +1713,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix) int i; if (!options.strategy) - options.strategy = "recursive"; + options.strategy = "ort"; strbuf_reset(&buf); for (i = 0; i < strategy_options.nr; i++) diff --git a/sequencer.c b/sequencer.c index 0bec01cf38e..a98de9a8d15 100644 --- a/sequencer.c +++ b/sequencer.c @@ -636,7 +636,7 @@ static int do_recursive_merge(struct repository *r, for (i = 0; i < opts->xopts_nr; i++) parse_merge_opt(&o, opts->xopts[i]); - if (opts->strategy && !strcmp(opts->strategy, "ort")) { + if (!opts->strategy || strcmp(opts->strategy, "recursive")) { memset(&result, 0, sizeof(result)); merge_incore_nonrecursive(&o, base_tree, head_tree, next_tree, &result); @@ -3968,7 +3968,7 @@ static int do_merge(struct repository *r, o.branch2 = ref_name.buf; o.buffer_output = 2; - if (opts->strategy && !strcmp(opts->strategy, "ort")) { + if (!opts->strategy || strcmp(opts->strategy, "recursive")) { /* * TODO: Should use merge_incore_recursive() and * merge_switch_to_result(), skipping the call to