From: "Antonin Delpeuch via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano [ ]" <gitster@pobox.com>,
Antonin Delpeuch <antonin@delpeuch.eu>,
Antonin Delpeuch <antonin@delpeuch.eu>
Subject: [PATCH v2] merge-recursive: honor diff.algorithm
Date: Tue, 09 Jul 2024 19:01:41 +0000 [thread overview]
Message-ID: <pull.1743.v2.git.git.1720551701648.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.1743.git.git.1720431288496.gitgitgadget@gmail.com>
From: Antonin Delpeuch <antonin@delpeuch.eu>
The documentation claims that "recursive defaults to the diff.algorithm
config setting", but this is currently not the case. This fixes it,
ensuring that diff.algorithm is used when -Xdiff-algorithm is not
supplied. This affects the following porcelain commands: "merge",
"rebase", "cherry-pick", "pull", "stash", "log", "am" and "checkout".
It also affects the "merge-tree" ancillary interrogator.
This change refactors the initialization of merge options to introduce
two functions, "init_merge_ui_options" and "init_merge_basic_options"
instead of just one "init_merge_options". This design follows the
approach used in diff.c, providing initialization methods for
porcelain and plumbing commands respectively. Thanks to that, the
"replay" and "merge-recursive" plumbing commands remain unaffected by
diff.algorithm.
Signed-off-by: Antonin Delpeuch <antonin@delpeuch.eu>
---
merge-recursive: honor diff.algorithm
Changes since v1:
* introduce separate initialization methods for porcelain and plumbing
commands
* adapt commit message accordingly
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1743%2Fwetneb%2Frecursive_respects_diff.algorithm-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1743/wetneb/recursive_respects_diff.algorithm-v2
Pull-Request: https://github.com/git/git/pull/1743
Range-diff vs v1:
1: 798b1612189 ! 1: 9c1907fad43 merge-recursive: honor diff.algorithm
@@ Commit message
"rebase", "cherry-pick", "pull", "stash", "log", "am" and "checkout".
It also affects the "merge-tree" ancillary interrogator.
- This change also affects the "replay" and "merge-recursive" plumbing
- commands, which happen to call 'merge_recursive_config' and therefore
- are also affected by other configuration variables read in this
- function. For instance theay read "diff.renames", classified in diff.c
- as a diff "UI" config variable. Removing the reliance of those
- commands on this set of configuration variables feels like a bigger
- change and introducing an argument to 'merge_recursive_config' to
- prevent only the newly added diff.algorithm to be read by plumbing
- commands feels like muddying the architecture, as this function
- should likely not be called at all by plumbing commands.
+ This change refactors the initialization of merge options to introduce
+ two functions, "init_merge_ui_options" and "init_merge_basic_options"
+ instead of just one "init_merge_options". This design follows the
+ approach used in diff.c, providing initialization methods for
+ porcelain and plumbing commands respectively. Thanks to that, the
+ "replay" and "merge-recursive" plumbing commands remain unaffected by
+ diff.algorithm.
Signed-off-by: Antonin Delpeuch <antonin@delpeuch.eu>
+ ## builtin/am.c ##
+@@ builtin/am.c: static int fall_back_threeway(const struct am_state *state, const char *index_pa
+ * changes.
+ */
+
+- init_merge_options(&o, the_repository);
++ init_ui_merge_options(&o, the_repository);
+
+ o.branch1 = "HEAD";
+ their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
+
+ ## builtin/checkout.c ##
+@@ builtin/checkout.c: static int merge_working_tree(const struct checkout_opts *opts,
+
+ add_files_to_cache(the_repository, NULL, NULL, NULL, 0,
+ 0);
+- init_merge_options(&o, the_repository);
++ init_ui_merge_options(&o, the_repository);
+ o.verbosity = 0;
+ work = write_in_core_index_as_tree(the_repository);
+
+
## builtin/merge-recursive.c ##
@@ builtin/merge-recursive.c: int cmd_merge_recursive(int argc, const char **argv, const char *prefix UNUSED)
char *better1, *better2;
struct commit *result;
-+ /*
-+ * FIXME: This reads various config variables,
-+ * which 'merge-recursive' should ignore as a plumbing command
-+ */
- init_merge_options(&o, the_repository);
+- init_merge_options(&o, the_repository);
++ init_basic_merge_options(&o, the_repository);
if (argv[0] && ends_with(argv[0], "-subtree"))
o.subtree_shift = "";
+
+
+ ## builtin/merge-tree.c ##
+@@ builtin/merge-tree.c: int cmd_merge_tree(int argc, const char **argv, const char *prefix)
+ };
+
+ /* Init merge options */
+- init_merge_options(&o.merge_options, the_repository);
++ init_ui_merge_options(&o.merge_options, the_repository);
+
+ /* Parse arguments */
+ original_argc = argc - 1; /* ignoring argv[0] */
+
+ ## builtin/merge.c ##
+@@ builtin/merge.c: static int try_merge_strategy(const char *strategy, struct commit_list *common,
+ return 2;
+ }
+
+- init_merge_options(&o, the_repository);
++ init_ui_merge_options(&o, the_repository);
+ if (!strcmp(strategy, "subtree"))
+ o.subtree_shift = "";
+
## builtin/replay.c ##
@@ builtin/replay.c: int cmd_replay(int argc, const char **argv, const char *prefix)
goto cleanup;
}
-+ /*
-+ * FIXME: This reads various config variables,
-+ * which 'replay' should ignore as a plumbing command
-+ */
- init_merge_options(&merge_opt, the_repository);
+- init_merge_options(&merge_opt, the_repository);
++ init_basic_merge_options(&merge_opt, the_repository);
memset(&result, 0, sizeof(result));
merge_opt.show_rename_progress = 0;
+ last_commit = onto;
+
+ ## builtin/stash.c ##
+@@ builtin/stash.c: static int do_apply_stash(const char *prefix, struct stash_info *info,
+ }
+ }
+
+- init_merge_options(&o, the_repository);
++ init_ui_merge_options(&o, the_repository);
+
+ o.branch1 = "Updated upstream";
+ o.branch2 = "Stashed changes";
+
+ ## log-tree.c ##
+@@ log-tree.c: static int do_remerge_diff(struct rev_info *opt,
+ struct strbuf parent2_desc = STRBUF_INIT;
+
+ /* Setup merge options */
+- init_merge_options(&o, the_repository);
++ init_ui_merge_options(&o, the_repository);
+ o.show_rename_progress = 0;
+ o.record_conflict_msgs_as_headers = 1;
+ o.msg_header_prefix = "remerge";
## merge-recursive.c ##
+@@ merge-recursive.c: int merge_recursive_generic(struct merge_options *opt,
+ return clean ? 0 : 1;
+ }
+
+-static void merge_recursive_config(struct merge_options *opt)
++static void merge_recursive_config(struct merge_options *opt, int ui)
+ {
+ char *value = NULL;
+ int renormalize = 0;
@@ merge-recursive.c: static void merge_recursive_config(struct merge_options *opt)
} /* avoid erroring on values from future versions of git */
free(value);
}
-+ if (!git_config_get_string("diff.algorithm", &value)) {
-+ long diff_algorithm = parse_algorithm_value(value);
-+ if (diff_algorithm < 0)
-+ die(_("unknown value for config '%s': %s"), "diff.algorithm", value);
-+ opt->xdl_opts = (opt->xdl_opts & ~XDF_DIFF_ALGORITHM_MASK) | diff_algorithm;
-+ free(value);
++ if (ui) {
++ if (!git_config_get_string("diff.algorithm", &value)) {
++ long diff_algorithm = parse_algorithm_value(value);
++ if (diff_algorithm < 0)
++ die(_("unknown value for config '%s': %s"), "diff.algorithm", value);
++ opt->xdl_opts = (opt->xdl_opts & ~XDF_DIFF_ALGORITHM_MASK) | diff_algorithm;
++ free(value);
++ }
+ }
git_config(git_xmerge_config, NULL);
}
+-void init_merge_options(struct merge_options *opt,
+- struct repository *repo)
++static void init_merge_options(struct merge_options *opt,
++ struct repository *repo, int ui)
+ {
+ const char *merge_verbosity;
+ memset(opt, 0, sizeof(struct merge_options));
+@@ merge-recursive.c: void init_merge_options(struct merge_options *opt,
+
+ opt->conflict_style = -1;
+
+- merge_recursive_config(opt);
++ merge_recursive_config(opt, ui);
+ merge_verbosity = getenv("GIT_MERGE_VERBOSITY");
+ if (merge_verbosity)
+ opt->verbosity = strtol(merge_verbosity, NULL, 10);
+@@ merge-recursive.c: void init_merge_options(struct merge_options *opt,
+ opt->buffer_output = 0;
+ }
+
++void init_ui_merge_options(struct merge_options *opt,
++ struct repository *repo)
++{
++ init_merge_options(opt, repo, 1);
++}
++
++void init_basic_merge_options(struct merge_options *opt,
++ struct repository *repo)
++{
++ init_merge_options(opt, repo, 0);
++}
++
+ /*
+ * For now, members of merge_options do not need deep copying, but
+ * it may change in the future, in which case we would need to update
+
+ ## merge-recursive.h ##
+@@ merge-recursive.h: struct merge_options {
+ struct merge_options_internal *priv;
+ };
+
+-void init_merge_options(struct merge_options *opt, struct repository *repo);
++/* for use by porcelain commands */
++void init_ui_merge_options(struct merge_options *opt, struct repository *repo);
++/* for use by plumbing commands */
++void init_basic_merge_options(struct merge_options *opt, struct repository *repo);
+
+ void copy_merge_options(struct merge_options *dst, struct merge_options *src);
+ void clear_merge_options(struct merge_options *opt);
+
+ ## sequencer.c ##
+@@ sequencer.c: static int do_recursive_merge(struct repository *r,
+
+ repo_read_index(r);
+
+- init_merge_options(&o, r);
++ init_ui_merge_options(&o, r);
+ o.ancestor = base ? base_label : "(empty tree)";
+ o.branch1 = "HEAD";
+ o.branch2 = next ? next_label : "(empty tree)";
+@@ sequencer.c: static int do_merge(struct repository *r,
+ bases = reverse_commit_list(bases);
+
+ repo_read_index(r);
+- init_merge_options(&o, r);
++ init_ui_merge_options(&o, r);
+ o.branch1 = "HEAD";
+ o.branch2 = ref_name.buf;
+ o.buffer_output = 2;
## t/t3515-cherry-pick-diff.sh (new) ##
@@
builtin/am.c | 2 +-
builtin/checkout.c | 2 +-
builtin/merge-recursive.c | 2 +-
builtin/merge-tree.c | 2 +-
builtin/merge.c | 2 +-
builtin/replay.c | 2 +-
builtin/stash.c | 2 +-
log-tree.c | 2 +-
merge-recursive.c | 29 +++++++++++++++++++++----
merge-recursive.h | 5 ++++-
sequencer.c | 4 ++--
t/t3515-cherry-pick-diff.sh | 41 +++++++++++++++++++++++++++++++++++
t/t3515/base.c | 17 +++++++++++++++
t/t3515/ours.c | 17 +++++++++++++++
t/t3515/theirs.c | 17 +++++++++++++++
t/t7615-merge-diff.sh | 43 +++++++++++++++++++++++++++++++++++++
16 files changed, 174 insertions(+), 15 deletions(-)
create mode 100755 t/t3515-cherry-pick-diff.sh
create mode 100644 t/t3515/base.c
create mode 100644 t/t3515/ours.c
create mode 100644 t/t3515/theirs.c
create mode 100755 t/t7615-merge-diff.sh
diff --git a/builtin/am.c b/builtin/am.c
index 8f9619ea3a3..b821561b15a 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1630,7 +1630,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
* changes.
*/
- init_merge_options(&o, the_repository);
+ init_ui_merge_options(&o, the_repository);
o.branch1 = "HEAD";
their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 3cf44b4683a..5769efaca00 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -884,7 +884,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
add_files_to_cache(the_repository, NULL, NULL, NULL, 0,
0);
- init_merge_options(&o, the_repository);
+ init_ui_merge_options(&o, the_repository);
o.verbosity = 0;
work = write_in_core_index_as_tree(the_repository);
diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c
index c2ce044a201..9e9d0b57158 100644
--- a/builtin/merge-recursive.c
+++ b/builtin/merge-recursive.c
@@ -31,7 +31,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix UNUSED)
char *better1, *better2;
struct commit *result;
- init_merge_options(&o, the_repository);
+ init_basic_merge_options(&o, the_repository);
if (argv[0] && ends_with(argv[0], "-subtree"))
o.subtree_shift = "";
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index 1082d919fd1..aab0843ff5a 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -570,7 +570,7 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
};
/* Init merge options */
- init_merge_options(&o.merge_options, the_repository);
+ init_ui_merge_options(&o.merge_options, the_repository);
/* Parse arguments */
original_argc = argc - 1; /* ignoring argv[0] */
diff --git a/builtin/merge.c b/builtin/merge.c
index 66a4fa72e1c..686326bc1d3 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -720,7 +720,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
return 2;
}
- init_merge_options(&o, the_repository);
+ init_ui_merge_options(&o, the_repository);
if (!strcmp(strategy, "subtree"))
o.subtree_shift = "";
diff --git a/builtin/replay.c b/builtin/replay.c
index 6bf0691f15d..d90ddd0837d 100644
--- a/builtin/replay.c
+++ b/builtin/replay.c
@@ -373,7 +373,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix)
goto cleanup;
}
- init_merge_options(&merge_opt, the_repository);
+ init_basic_merge_options(&merge_opt, the_repository);
memset(&result, 0, sizeof(result));
merge_opt.show_rename_progress = 0;
last_commit = onto;
diff --git a/builtin/stash.c b/builtin/stash.c
index 7859bc0866a..86803755f03 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -574,7 +574,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
}
}
- init_merge_options(&o, the_repository);
+ init_ui_merge_options(&o, the_repository);
o.branch1 = "Updated upstream";
o.branch2 = "Stashed changes";
diff --git a/log-tree.c b/log-tree.c
index 101079e8200..5d8fb6ff8df 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -1025,7 +1025,7 @@ static int do_remerge_diff(struct rev_info *opt,
struct strbuf parent2_desc = STRBUF_INIT;
/* Setup merge options */
- init_merge_options(&o, the_repository);
+ init_ui_merge_options(&o, the_repository);
o.show_rename_progress = 0;
o.record_conflict_msgs_as_headers = 1;
o.msg_header_prefix = "remerge";
diff --git a/merge-recursive.c b/merge-recursive.c
index 46ee364af73..cd9bd3c03ef 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -3901,7 +3901,7 @@ int merge_recursive_generic(struct merge_options *opt,
return clean ? 0 : 1;
}
-static void merge_recursive_config(struct merge_options *opt)
+static void merge_recursive_config(struct merge_options *opt, int ui)
{
char *value = NULL;
int renormalize = 0;
@@ -3930,11 +3930,20 @@ static void merge_recursive_config(struct merge_options *opt)
} /* avoid erroring on values from future versions of git */
free(value);
}
+ if (ui) {
+ if (!git_config_get_string("diff.algorithm", &value)) {
+ long diff_algorithm = parse_algorithm_value(value);
+ if (diff_algorithm < 0)
+ die(_("unknown value for config '%s': %s"), "diff.algorithm", value);
+ opt->xdl_opts = (opt->xdl_opts & ~XDF_DIFF_ALGORITHM_MASK) | diff_algorithm;
+ free(value);
+ }
+ }
git_config(git_xmerge_config, NULL);
}
-void init_merge_options(struct merge_options *opt,
- struct repository *repo)
+static void init_merge_options(struct merge_options *opt,
+ struct repository *repo, int ui)
{
const char *merge_verbosity;
memset(opt, 0, sizeof(struct merge_options));
@@ -3953,7 +3962,7 @@ void init_merge_options(struct merge_options *opt,
opt->conflict_style = -1;
- merge_recursive_config(opt);
+ merge_recursive_config(opt, ui);
merge_verbosity = getenv("GIT_MERGE_VERBOSITY");
if (merge_verbosity)
opt->verbosity = strtol(merge_verbosity, NULL, 10);
@@ -3961,6 +3970,18 @@ void init_merge_options(struct merge_options *opt,
opt->buffer_output = 0;
}
+void init_ui_merge_options(struct merge_options *opt,
+ struct repository *repo)
+{
+ init_merge_options(opt, repo, 1);
+}
+
+void init_basic_merge_options(struct merge_options *opt,
+ struct repository *repo)
+{
+ init_merge_options(opt, repo, 0);
+}
+
/*
* For now, members of merge_options do not need deep copying, but
* it may change in the future, in which case we would need to update
diff --git a/merge-recursive.h b/merge-recursive.h
index e67d38c3030..85a5c332bbb 100644
--- a/merge-recursive.h
+++ b/merge-recursive.h
@@ -54,7 +54,10 @@ struct merge_options {
struct merge_options_internal *priv;
};
-void init_merge_options(struct merge_options *opt, struct repository *repo);
+/* for use by porcelain commands */
+void init_ui_merge_options(struct merge_options *opt, struct repository *repo);
+/* for use by plumbing commands */
+void init_basic_merge_options(struct merge_options *opt, struct repository *repo);
void copy_merge_options(struct merge_options *dst, struct merge_options *src);
void clear_merge_options(struct merge_options *opt);
diff --git a/sequencer.c b/sequencer.c
index b4f055e5a85..3608374166a 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -762,7 +762,7 @@ static int do_recursive_merge(struct repository *r,
repo_read_index(r);
- init_merge_options(&o, r);
+ init_ui_merge_options(&o, r);
o.ancestor = base ? base_label : "(empty tree)";
o.branch1 = "HEAD";
o.branch2 = next ? next_label : "(empty tree)";
@@ -4308,7 +4308,7 @@ static int do_merge(struct repository *r,
bases = reverse_commit_list(bases);
repo_read_index(r);
- init_merge_options(&o, r);
+ init_ui_merge_options(&o, r);
o.branch1 = "HEAD";
o.branch2 = ref_name.buf;
o.buffer_output = 2;
diff --git a/t/t3515-cherry-pick-diff.sh b/t/t3515-cherry-pick-diff.sh
new file mode 100755
index 00000000000..caeaa01c590
--- /dev/null
+++ b/t/t3515-cherry-pick-diff.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+test_description='git cherry-pick
+
+Testing the influence of the diff algorithm on the merge output.'
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ cp "$TEST_DIRECTORY"/t3515/base.c file.c &&
+ git add file.c &&
+ git commit -m c0 &&
+ git tag c0 &&
+ cp "$TEST_DIRECTORY"/t3515/ours.c file.c &&
+ git add file.c &&
+ git commit -m c1 &&
+ git tag c1 &&
+ git reset --hard c0 &&
+ cp "$TEST_DIRECTORY"/t3515/theirs.c file.c &&
+ git add file.c &&
+ git commit -m c2 &&
+ git tag c2
+'
+
+test_expect_success 'cherry-pick c2 to c1 with recursive merge strategy fails with the current default myers diff algorithm' '
+ git reset --hard c1 &&
+ test_must_fail git cherry-pick -s recursive c2
+'
+
+test_expect_success 'cherry-pick c2 to c1 with recursive merge strategy succeeds with -Xdiff-algorithm=histogram' '
+ git reset --hard c1 &&
+ git cherry-pick --strategy recursive -Xdiff-algorithm=histogram c2
+'
+
+test_expect_success 'cherry-pick c2 to c1 with recursive merge strategy succeeds with diff.algorithm = histogram' '
+ git reset --hard c1 &&
+ git config diff.algorithm histogram &&
+ git cherry-pick --strategy recursive c2
+'
+test_done
diff --git a/t/t3515/base.c b/t/t3515/base.c
new file mode 100644
index 00000000000..c64abc59366
--- /dev/null
+++ b/t/t3515/base.c
@@ -0,0 +1,17 @@
+int f(int x, int y)
+{
+ if (x == 0)
+ {
+ return y;
+ }
+ return x;
+}
+
+int g(size_t u)
+{
+ while (u < 30)
+ {
+ u++;
+ }
+ return u;
+}
diff --git a/t/t3515/ours.c b/t/t3515/ours.c
new file mode 100644
index 00000000000..44d82513970
--- /dev/null
+++ b/t/t3515/ours.c
@@ -0,0 +1,17 @@
+int g(size_t u)
+{
+ while (u < 30)
+ {
+ u++;
+ }
+ return u;
+}
+
+int h(int x, int y, int z)
+{
+ if (z == 0)
+ {
+ return x;
+ }
+ return y;
+}
diff --git a/t/t3515/theirs.c b/t/t3515/theirs.c
new file mode 100644
index 00000000000..85f02146fee
--- /dev/null
+++ b/t/t3515/theirs.c
@@ -0,0 +1,17 @@
+int f(int x, int y)
+{
+ if (x == 0)
+ {
+ return y;
+ }
+ return x;
+}
+
+int g(size_t u)
+{
+ while (u > 34)
+ {
+ u--;
+ }
+ return u;
+}
diff --git a/t/t7615-merge-diff.sh b/t/t7615-merge-diff.sh
new file mode 100755
index 00000000000..be335c7c3d1
--- /dev/null
+++ b/t/t7615-merge-diff.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+test_description='git merge
+
+Testing the influence of the diff algorithm on the merge output.'
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ cp "$TEST_DIRECTORY"/t3515/base.c file.c &&
+ git add file.c &&
+ git commit -m c0 &&
+ git tag c0 &&
+ cp "$TEST_DIRECTORY"/t3515/ours.c file.c &&
+ git add file.c &&
+ git commit -m c1 &&
+ git tag c1 &&
+ git reset --hard c0 &&
+ cp "$TEST_DIRECTORY"/t3515/theirs.c file.c &&
+ git add file.c &&
+ git commit -m c2 &&
+ git tag c2
+'
+
+GIT_TEST_MERGE_ALGORITHM=recursive
+
+test_expect_success 'merge c2 to c1 with recursive merge strategy fails with the current default myers diff algorithm' '
+ git reset --hard c1 &&
+ test_must_fail git merge -s recursive c2
+'
+
+test_expect_success 'merge c2 to c1 with recursive merge strategy succeeds with -Xdiff-algorithm=histogram' '
+ git reset --hard c1 &&
+ git merge --strategy recursive -Xdiff-algorithm=histogram c2
+'
+
+test_expect_success 'merge c2 to c1 with recursive merge strategy succeeds with diff.algorithm = histogram' '
+ git reset --hard c1 &&
+ git config diff.algorithm histogram &&
+ git merge --strategy recursive c2
+'
+test_done
base-commit: 06e570c0dfb2a2deb64d217db78e2ec21672f558
--
gitgitgadget
next prev parent reply other threads:[~2024-07-09 19:01 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-08 9:34 [PATCH] merge-recursive: honor diff.algorithm Antonin Delpeuch via GitGitGadget
2024-07-09 17:16 ` Antonin Delpeuch
2024-07-09 18:51 ` Junio C Hamano
2024-07-09 19:01 ` Antonin Delpeuch via GitGitGadget [this message]
2024-07-10 17:58 ` [PATCH v2] " Junio C Hamano
2024-07-13 16:50 ` Antonin Delpeuch
2024-07-13 16:51 ` [PATCH v3] " Antonin Delpeuch via GitGitGadget
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pull.1743.v2.git.git.1720551701648.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=antonin@delpeuch.eu \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).