{"thread":{"id":"64927","subject":"[DOC] merge-file: document that merge.conflictStyle requires a repository","startedAt":"2026-02-05T15:06:20Z","lastAt":"2026-02-09T16:13:59Z","messageCount":12,"participants":["Yannik Tausch","Junio C Hamano","Kristoffer Haugsbakk","Patrick Steinhardt"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"535246","messageId":"48B1AA62-D7FF-439E-B770-1127E1EE0E79@ytausch.de","threadId":"64927","inReplyTo":null,"subject":"[DOC] merge-file: document that merge.conflictStyle requires a repository","fromName":"Yannik Tausch","fromEmail":"dev@ytausch.de","sentAt":"2026-02-05T15:06:04Z","receivedAt":"2026-02-05T15:06:20Z","isPatch":false,"sender":{"key":"dev@ytausch.de","avatar":"https://avatars.githubusercontent.com/u/25906270?v=4"},"body":"Hi,\n\nWe noticed that `git merge-file` only respects the `merge.conflictStyle`\nconfiguration when run inside a repository. Outside a repository, the\nsetting is ignored and only the `--diff3`/`--zdiff3` flags work.\n\nLooking at the history, this appears to be intentional since b541248467\n(\"merge.conflictstyle: choose between merge and diff3 -m styles\", 2008),\nwhich explicitly gates config reading on being inside a repository.\n\nThis behavior surprised me, and I couldn't find it documented anywhere.\nWould a small documentation patch to git-merge-file.txt be welcome,\nnoting that the config is only read when inside a repository?\n\nSomething like adding to the --diff3 option description:\n\n  When run inside a repository, the `merge.conflictStyle`\n  configuration variable can be used as a default for this option.\n\nThanks,\n\nYannik Tausch\n"},{"id":"535274","messageId":"xmqq4invm2dk.fsf@gitster.g","threadId":"64927","inReplyTo":"48B1AA62-D7FF-439E-B770-1127E1EE0E79@ytausch.de","subject":"Re: [DOC] merge-file: document that merge.conflictStyle requires a repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-05T19:11:51Z","receivedAt":"2026-02-05T19:11:54Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Yannik Tausch <dev@ytausch.de> writes:\n\n> We noticed that `git merge-file` only respects the `merge.conflictStyle`\n> configuration when run inside a repository. Outside a repository, the\n> setting is ignored and only the `--diff3`/`--zdiff3` flags work.\n>\n> Looking at the history, this appears to be intentional since b541248467\n> (\"merge.conflictstyle: choose between merge and diff3 -m styles\", 2008),\n> which explicitly gates config reading on being inside a repository.\n>\n> This behavior surprised me, and I couldn't find it documented anywhere.\n> Would a small documentation patch to git-merge-file.txt be welcome,\n> noting that the config is only read when inside a repository?\n\nOr even better, teach the command to read (limited set of)\nconfiguration files.\n\nBy definition, you cannot read from per-repository configuration\nfile when working outside a repository, but these days we let our\ncommands read configuration from system and personal configuration\nfiles, I think.  Back in 2008, it is understandable we couldn't.\n"},{"id":"535277","messageId":"3724733C-FECB-47F5-841C-84DE9792332D@ytausch.de","threadId":"64927","inReplyTo":"xmqq4invm2dk.fsf@gitster.g","subject":"[PATCH] merge-file: honor merge.conflictStyle outside of a repository","fromName":"Yannik Tausch","fromEmail":"dev@ytausch.de","sentAt":"2026-02-05T20:27:21Z","receivedAt":"2026-02-05T20:27:43Z","isPatch":true,"sender":{"key":"dev@ytausch.de","avatar":"https://avatars.githubusercontent.com/u/25906270?v=4"},"body":"> Junio C Hamano <gitster@pobox.com> writes:\n> \n> Yannik Tausch <dev@ytausch.de> writes:\n> \n>> We noticed that `git merge-file` only respects the `merge.conflictStyle`\n>> configuration when run inside a repository. Outside a repository, the\n>> setting is ignored and only the `--diff3`/`--zdiff3` flags work.\n>> \n>> Looking at the history, this appears to be intentional since b541248467\n>> (\"merge.conflictstyle: choose between merge and diff3 -m styles\", 2008),\n>> which explicitly gates config reading on being inside a repository.\n>> \n>> This behavior surprised me, and I couldn't find it documented anywhere.\n>> Would a small documentation patch to git-merge-file.txt be welcome,\n>> noting that the config is only read when inside a repository?\n> \n> Or even better, teach the command to read (limited set of)\n> configuration files.\n> \n> By definition, you cannot read from per-repository configuration\n> file when working outside a repository, but these days we let our\n> commands read configuration from system and personal configuration\n> files, I think.  Back in 2008, it is understandable we couldn't.\n\nThanks for the suggestion. Here's a patch:\n\nFrom bed0035d38072c67e0be8eedb0cf98da936cbac6 Mon Sep 17 00:00:00 2001\nFrom: Yannik Tausch <dev@ytausch.de>\nDate: Thu, 5 Feb 2026 21:09:52 +0100\nSubject: [PATCH] merge-file: honor merge.conflictStyle outside of a repository\n\nWhen running outside a repository, git merge-file previously ignored\nthe merge.conflictStyle configuration variable entirely. Teach it to\nread from system and user configuration files using\nread_very_early_config(), so that users can set their preferred\nconflict style globally and have it honored even outside a repository.\n\nSigned-off-by: Yannik Tausch <dev@ytausch.de>\n---\n Documentation/git-merge-file.adoc |  3 +++\n builtin/merge-file.c              | 11 +++++-----\n t/t6403-merge-file.sh             | 34 +++++++++++++++++++++++++++++++\n 3 files changed, 43 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/git-merge-file.adoc b/Documentation/git-merge-file.adoc\nindex 71915a00fa..773037aa14 100644\n--- a/Documentation/git-merge-file.adoc\n+++ b/Documentation/git-merge-file.adoc\n@@ -86,6 +86,9 @@ object store and the object ID of its blob is written to standard output.\n --zdiff3::\n \tShow conflicts in \"zdiff3\" style.\n \n+The `--diff3` and `--zdiff3` options default to the value of the\n+`merge.conflictStyle` configuration variable (see linkgit:git-config[1]).\n+\n --ours::\n --theirs::\n --union::\ndiff --git a/builtin/merge-file.c b/builtin/merge-file.c\nindex 46775d0c79..1b6e16b9cb 100644\n--- a/builtin/merge-file.c\n+++ b/builtin/merge-file.c\n@@ -95,12 +95,13 @@ int cmd_merge_file(int argc,\n \txmp.style = 0;\n \txmp.favor = 0;\n \n-\tif (startup_info->have_repository) {\n-\t\t/* Read the configuration file */\n+\tif (startup_info->have_repository)\n \t\trepo_config(the_repository, git_xmerge_config, NULL);\n-\t\tif (0 <= git_xmerge_style)\n-\t\t\txmp.style = git_xmerge_style;\n-\t}\n+\telse\n+\t\tread_very_early_config(git_xmerge_config, NULL);\n+\n+\tif (0 <= git_xmerge_style)\n+\t\txmp.style = git_xmerge_style;\n \n \targc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);\n \tif (argc != 3)\ndiff --git a/t/t6403-merge-file.sh b/t/t6403-merge-file.sh\nindex 06ab4d7aed..9df9f878c8 100755\n--- a/t/t6403-merge-file.sh\n+++ b/t/t6403-merge-file.sh\n@@ -428,6 +428,40 @@ test_expect_success '\"diff3 -m\" style output (2)' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'merge.conflictStyle honored outside repo' '\n+\ttest_config_global merge.conflictStyle diff3 &&\n+\tcat >nongit-base <<-\\EOF &&\n+\tline1\n+\toriginal\n+\tline3\n+\tEOF\n+\tcat >nongit-ours <<-\\EOF &&\n+\tline1\n+\tours\n+\tline3\n+\tEOF\n+\tcat >nongit-theirs <<-\\EOF &&\n+\tline1\n+\ttheirs\n+\tline3\n+\tEOF\n+\tcat >nongit-expect <<-\\EOF &&\n+\tline1\n+\t<<<<<<< ours\n+\tours\n+\t||||||| base\n+\toriginal\n+\t=======\n+\ttheirs\n+\t>>>>>>> theirs\n+\tline3\n+\tEOF\n+\ttest_must_fail nongit git merge-file -p \\\n+\t\t-L ours -L base -L theirs \\\n+\t\t\"$PWD/nongit-ours\" \"$PWD/nongit-base\" \"$PWD/nongit-theirs\" >nongit-actual &&\n+\ttest_cmp nongit-expect nongit-actual\n+'\n+\n test_expect_success 'marker size' '\n \tcat >expect <<-\\EOF &&\n \tDominus regit me,\n-- \n2.52.0\n\n"},{"id":"535279","messageId":"xmqq8qd6ly3r.fsf@gitster.g","threadId":"64927","inReplyTo":"3724733C-FECB-47F5-841C-84DE9792332D@ytausch.de","subject":"Re: [PATCH] merge-file: honor merge.conflictStyle outside of a repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-05T20:44:08Z","receivedAt":"2026-02-05T20:44:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Yannik Tausch <dev@ytausch.de> writes:\n\n> -\tif (startup_info->have_repository) {\n> -\t\t/* Read the configuration file */\n> +\tif (startup_info->have_repository)\n>  \t\trepo_config(the_repository, git_xmerge_config, NULL);\n> -\t\tif (0 <= git_xmerge_style)\n> -\t\t\txmp.style = git_xmerge_style;\n> -\t}\n> +\telse\n> +\t\tread_very_early_config(git_xmerge_config, NULL);\n> +\n> +\tif (0 <= git_xmerge_style)\n> +\t\txmp.style = git_xmerge_style;\n\nWouldn't it suffice to unconditionally execute the body of the if\n(startup_info->have_repository) block to pass \"repo\" we obtained\nfrom the caller to repo_config() instead of the_repository?  The\ncaller of this function passes us either the_repository or NULL and\nrepo_config() does the very-early thing when passed NULL as the\nrepo, signalling that we are outside a repository.\n\nIOW, something like\n\ndiff --git c/builtin/merge-file.c w/builtin/merge-file.c\nindex 46775d0c79..f9de636884 100644\n--- c/builtin/merge-file.c\n+++ w/builtin/merge-file.c\n@@ -60,7 +60,7 @@ static int diff_algorithm_cb(const struct option *opt,\n int cmd_merge_file(int argc,\n \t\t   const char **argv,\n \t\t   const char *prefix,\n-\t\t   struct repository *repo UNUSED)\n+\t\t   struct repository *repo)\n {\n \tconst char *names[3] = { 0 };\n \tmmfile_t mmfs[3] = { 0 };\n@@ -95,12 +95,10 @@ int cmd_merge_file(int argc,\n \txmp.style = 0;\n \txmp.favor = 0;\n \n-\tif (startup_info->have_repository) {\n-\t\t/* Read the configuration file */\n-\t\trepo_config(the_repository, git_xmerge_config, NULL);\n-\t\tif (0 <= git_xmerge_style)\n-\t\t\txmp.style = git_xmerge_style;\n-\t}\n+\t/* Read the configuration file */\n+\trepo_config(repo, git_xmerge_config, NULL);\n+\tif (0 <= git_xmerge_style)\n+\t\txmp.style = git_xmerge_style;\n \n \targc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);\n \tif (argc != 3)\n"},{"id":"535280","messageId":"fa7fc215-03eb-492d-9af4-457482c56a48@app.fastmail.com","threadId":"64927","inReplyTo":"3724733C-FECB-47F5-841C-84DE9792332D@ytausch.de","subject":"Re: [PATCH] merge-file: honor merge.conflictStyle outside of a repository","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-05T20:51:51Z","receivedAt":"2026-02-05T20:52:37Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Thu, Feb 5, 2026, at 21:27, Yannik Tausch wrote:\n>[snip]\n> From bed0035d38072c67e0be8eedb0cf98da936cbac6 Mon Sep 17 00:00:00 2001\n> From: Yannik Tausch <dev@ytausch.de>\n> Date: Thu, 5 Feb 2026 21:09:52 +0100\n> Subject: [PATCH] merge-file: honor merge.conflictStyle outside of a repository\n>\n> When running outside a repository, git merge-file previously ignored\n> the merge.conflictStyle configuration variable entirely. Teach it to\n\nPreferably the message should discuss the code as it exists without the\npatch applied in the present tense. (SubmittingPatches present-tense)\n\n> read from system and user configuration files using\n> read_very_early_config(), so that users can set their preferred\n> conflict style globally and have it honored even outside a repository.\n\nThe update to the documentation might merit an “also”? I dunno.\n\n>\n> Signed-off-by: Yannik Tausch <dev@ytausch.de>\n> ---\n>  Documentation/git-merge-file.adoc |  3 +++\n>  builtin/merge-file.c              | 11 +++++-----\n>  t/t6403-merge-file.sh             | 34 +++++++++++++++++++++++++++++++\n>  3 files changed, 43 insertions(+), 5 deletions(-)\n>\n> diff --git a/Documentation/git-merge-file.adoc\n> b/Documentation/git-merge-file.adoc\n> index 71915a00fa..773037aa14 100644\n> --- a/Documentation/git-merge-file.adoc\n> +++ b/Documentation/git-merge-file.adoc\n> @@ -86,6 +86,9 @@ object store and the object ID of its blob is written\n> to standard output.\n>  --zdiff3::\n>  \tShow conflicts in \"zdiff3\" style.\n>\n\nYou need to replace this blank line with a `+` if you want this to be\nthe second paragraph on this option.\n\n> +The `--diff3` and `--zdiff3` options default to the value of the\n> +`merge.conflictStyle` configuration variable (see linkgit:git-config[1]).\n> +\n>  --ours::\n>  --theirs::\n>  --union::\n> diff --git a/builtin/merge-file.c b/builtin/merge-file.c\n> index 46775d0c79..1b6e16b9cb 100644\n> --- a/builtin/merge-file.c\n> +++ b/builtin/merge-file.c\n> @@ -95,12 +95,13 @@ int cmd_merge_file(int argc,\n>  \txmp.style = 0;\n>  \txmp.favor = 0;\n>\n> -\tif (startup_info->have_repository) {\n> -\t\t/* Read the configuration file */\n> +\tif (startup_info->have_repository)\n>  \t\trepo_config(the_repository, git_xmerge_config, NULL);\n> -\t\tif (0 <= git_xmerge_style)\n> -\t\t\txmp.style = git_xmerge_style;\n> -\t}\n> +\telse\n> +\t\tread_very_early_config(git_xmerge_config, NULL);\n> +\n> +\tif (0 <= git_xmerge_style)\n> +\t\txmp.style = git_xmerge_style;\n>\n>  \targc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);\n>  \tif (argc != 3)\n> diff --git a/t/t6403-merge-file.sh b/t/t6403-merge-file.sh\n> index 06ab4d7aed..9df9f878c8 100755\n> --- a/t/t6403-merge-file.sh\n> +++ b/t/t6403-merge-file.sh\n> @@ -428,6 +428,40 @@ test_expect_success '\"diff3 -m\" style output (2)' '\n>  \ttest_cmp expect actual\n>  '\n>\n> +test_expect_success 'merge.conflictStyle honored outside repo' '\n> +\ttest_config_global merge.conflictStyle diff3 &&\n> +\tcat >nongit-base <<-\\EOF &&\n> +\tline1\n> +\toriginal\n> +\tline3\n> +\tEOF\n> +\tcat >nongit-ours <<-\\EOF &&\n> +\tline1\n> +\tours\n> +\tline3\n> +\tEOF\n> +\tcat >nongit-theirs <<-\\EOF &&\n> +\tline1\n> +\ttheirs\n> +\tline3\n> +\tEOF\n> +\tcat >nongit-expect <<-\\EOF &&\n\nSome tests in this file already use the regular expect/actual but there\nare also many one-off names like expect.c/myers_output.c. I don’t\nunderstand why. But I’m just thinking out loud here.\n\n> +\tline1\n> +\t<<<<<<< ours\n> +\tours\n> +\t||||||| base\n> +\toriginal\n> +\t=======\n> +\ttheirs\n> +\t>>>>>>> theirs\n> +\tline3\n> +\tEOF\n> +\ttest_must_fail nongit git merge-file -p \\\n> +\t\t-L ours -L base -L theirs \\\n> +\t\t\"$PWD/nongit-ours\" \"$PWD/nongit-base\" \"$PWD/nongit-theirs\" >nongit-actual &&\n\nIt seems you might as well break the lines for this command further with\nsome `\\` to get closer to the soft limit.\n\n> +\ttest_cmp nongit-expect nongit-actual\n> +'\n> +\n>  test_expect_success 'marker size' '\n>  \tcat >expect <<-\\EOF &&\n>  \tDominus regit me,\n> --\n> 2.52.0\n"},{"id":"535284","messageId":"D514F3BA-36DD-4DAD-BF73-609730390A27@ytausch.de","threadId":"64927","inReplyTo":"fa7fc215-03eb-492d-9af4-457482c56a48@app.fastmail.com","subject":"Re: [PATCH v2] merge-file: honor merge.conflictStyle outside of a repository","fromName":"Yannik Tausch","fromEmail":"dev@ytausch.de","sentAt":"2026-02-05T21:55:58Z","receivedAt":"2026-02-05T21:56:15Z","isPatch":true,"sender":{"key":"dev@ytausch.de","avatar":"https://avatars.githubusercontent.com/u/25906270?v=4"},"body":"> Junio C Hamano <gitster@pobox.com> wrote:\n\n> Wouldn't it suffice to unconditionally execute the body of the if\n> (startup_info->have_repository) block to pass \"repo\" we obtained\n> from the caller to repo_config() instead of the_repository?  The\n> caller of this function passes us either the_repository or NULL and\n> repo_config() does the very-early thing when passed NULL as the\n> repo, signalling that we are outside a repository.\n\nJup, looks like I missed that. Implemented your suggestion!\n\n> Kristoffer Haugsbakk <kristofferhaugsbakk@fastmail.com> wrote:\n\n> Preferably the message should discuss the code as it exists without the\n> patch applied in the present tense. (SubmittingPatches present-tense)\n\nFixed!\n> \n>> read from system and user configuration files using\n>> read_very_early_config(), so that users can set their preferred\n>> conflict style globally and have it honored even outside a repository.\n> \n> The update to the documentation might merit an “also”? I dunno.\n\nAdded!\n\n> You need to replace this blank line with a `+` if you want this to be\n> the second paragraph on this option.\n\nFixed!\n\n> Some tests in this file already use the regular expect/actual but there\n> are also many one-off names like expect.c/myers_output.c. I don’t\n> understand why. But I’m just thinking out loud here.\n\nI also don’t understand why, but considering your point, I don’t see a reason\nto not use the regular expect/actual convention. Fixed.\n\n> It seems you might as well break the lines for this command further with\n> some `\\` to get closer to the soft limit.\n\nDone!\n\nHere is the new patch:\n\nFrom 9fa437c70bfd328cfdfe9cfca982b49b70ad033f Mon Sep 17 00:00:00 2001\nFrom: Yannik Tausch <dev@ytausch.de>\nDate: Thu, 5 Feb 2026 21:09:52 +0100\nSubject: [PATCH v2] merge-file: honor merge.conflictStyle outside of a\n repository\n\nWhen running outside a repository, git merge-file ignores the\nmerge.conflictStyle configuration variable entirely. Since the\nfunction receives `repo` from the caller (which is NULL outside a\nrepository), and repo_config() falls back to reading system and user\nconfiguration when passed NULL, pass `repo` to repo_config()\nunconditionally.\n\nAlso document that merge.conflictStyle is honored.\n\nSigned-off-by: Yannik Tausch <dev@ytausch.de>\n---\n\nNotes:\n    Changes since v1:\n    - Use repo parameter directly with repo_config() (Junio)\n    - Fix AsciiDoc continuation, rename test files, break long\n      lines (Kristoffer)\n\n Documentation/git-merge-file.adoc |  3 +++\n builtin/merge-file.c              | 12 +++++------\n t/t6403-merge-file.sh             | 36 +++++++++++++++++++++++++++++++\n 3 files changed, 44 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/git-merge-file.adoc b/Documentation/git-merge-file.adoc\nindex 71915a00fa..9dc5d8a370 100644\n--- a/Documentation/git-merge-file.adoc\n+++ b/Documentation/git-merge-file.adoc\n@@ -85,6 +85,9 @@ object store and the object ID of its blob is written to standard output.\n \n --zdiff3::\n \tShow conflicts in \"zdiff3\" style.\n++\n+The `--diff3` and `--zdiff3` options default to the value of the\n+`merge.conflictStyle` configuration variable (see linkgit:git-config[1]).\n \n --ours::\n --theirs::\ndiff --git a/builtin/merge-file.c b/builtin/merge-file.c\nindex 46775d0c79..f9de636884 100644\n--- a/builtin/merge-file.c\n+++ b/builtin/merge-file.c\n@@ -60,7 +60,7 @@ static int diff_algorithm_cb(const struct option *opt,\n int cmd_merge_file(int argc,\n \t\t   const char **argv,\n \t\t   const char *prefix,\n-\t\t   struct repository *repo UNUSED)\n+\t\t   struct repository *repo)\n {\n \tconst char *names[3] = { 0 };\n \tmmfile_t mmfs[3] = { 0 };\n@@ -95,12 +95,10 @@ int cmd_merge_file(int argc,\n \txmp.style = 0;\n \txmp.favor = 0;\n \n-\tif (startup_info->have_repository) {\n-\t\t/* Read the configuration file */\n-\t\trepo_config(the_repository, git_xmerge_config, NULL);\n-\t\tif (0 <= git_xmerge_style)\n-\t\t\txmp.style = git_xmerge_style;\n-\t}\n+\t/* Read the configuration file */\n+\trepo_config(repo, git_xmerge_config, NULL);\n+\tif (0 <= git_xmerge_style)\n+\t\txmp.style = git_xmerge_style;\n \n \targc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);\n \tif (argc != 3)\ndiff --git a/t/t6403-merge-file.sh b/t/t6403-merge-file.sh\nindex 06ab4d7aed..4d6e748320 100755\n--- a/t/t6403-merge-file.sh\n+++ b/t/t6403-merge-file.sh\n@@ -428,6 +428,42 @@ test_expect_success '\"diff3 -m\" style output (2)' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'merge.conflictStyle honored outside repo' '\n+\ttest_config_global merge.conflictStyle diff3 &&\n+\tcat >nongit-base <<-\\EOF &&\n+\tline1\n+\toriginal\n+\tline3\n+\tEOF\n+\tcat >nongit-ours <<-\\EOF &&\n+\tline1\n+\tours\n+\tline3\n+\tEOF\n+\tcat >nongit-theirs <<-\\EOF &&\n+\tline1\n+\ttheirs\n+\tline3\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\tline1\n+\t<<<<<<< ours\n+\tours\n+\t||||||| base\n+\toriginal\n+\t=======\n+\ttheirs\n+\t>>>>>>> theirs\n+\tline3\n+\tEOF\n+\ttest_must_fail nongit git merge-file -p \\\n+\t\t-L ours -L base -L theirs \\\n+\t\t\"$PWD/nongit-ours\" \\\n+\t\t\"$PWD/nongit-base\" \\\n+\t\t\"$PWD/nongit-theirs\" >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'marker size' '\n \tcat >expect <<-\\EOF &&\n \tDominus regit me,\n-- \n2.52.0\n\n\n\n"},{"id":"535398","messageId":"xmqqqzqxczeb.fsf@gitster.g","threadId":"64927","inReplyTo":"D514F3BA-36DD-4DAD-BF73-609730390A27@ytausch.de","subject":"Re: [PATCH v2] merge-file: honor merge.conflictStyle outside of a repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-06T21:53:16Z","receivedAt":"2026-02-06T21:53:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Yannik Tausch <dev@ytausch.de> writes:\n\n>> Junio C Hamano <gitster@pobox.com> wrote:\n>\n>> Wouldn't it suffice to unconditionally execute the body of the if\n>> (startup_info->have_repository) block to pass \"repo\" we obtained\n>> from the caller to repo_config() instead of the_repository?  The\n>> caller of this function passes us either the_repository or NULL and\n>> repo_config() does the very-early thing when passed NULL as the\n>> repo, signalling that we are outside a repository.\n>\n> Jup, looks like I missed that. Implemented your suggestion!\n> ...\n> Done!\n>\n> Here is the new patch:\n>\n> From 9fa437c70bfd328cfdfe9cfca982b49b70ad033f Mon Sep 17 00:00:00 2001\n> From: Yannik Tausch <dev@ytausch.de>\n> Date: Thu, 5 Feb 2026 21:09:52 +0100\n> Subject: [PATCH v2] merge-file: honor merge.conflictStyle outside of a\n>  repository\n\nPlease do not send patches this way.  Giving responses to review\ncomments is very good and strongly encouraged, but stop the response\nmessage with \"a new version of the patch coming!\" and have a separate\nmessage for the patch itself.\n\nIt sometimes is done to interject a sample patch in the middle of a\ndiscussion, but then the convention is\n\n\t... continuation of an existing discussion ...\n\n\tSo, how about doing things this way?\n\n\t--- >8 ---\n\tSubject: the title of the patch\n\n\tThe proposed log message for the commit comes here\n\n\tSigned-off-by: you\n\t---\n\n\t... notes, diffstat, diff ...\n\ni.e., use a scissors line to tell the receiving end that the rest of\nthe message is a patch message, and override the Subject: with an\nin-body header.  Omit the (From <object-name> Mon Sep 17 2001)\n\"magic\" line, \"From:\" and \"Date:\".  The last two can be taken from\nthe e-mail message anyway.\n"},{"id":"535444","messageId":"75AA7DD7-F8D8-48DC-ADA0-74E56CFF351D@ytausch.de","threadId":"64927","inReplyTo":"xmqqqzqxczeb.fsf@gitster.g","subject":"Re: [PATCH v2] merge-file: honor merge.conflictStyle outside of a repository","fromName":"Yannik Tausch","fromEmail":"dev@ytausch.de","sentAt":"2026-02-07T21:28:00Z","receivedAt":"2026-02-07T21:28:22Z","isPatch":true,"sender":{"key":"dev@ytausch.de","avatar":"https://avatars.githubusercontent.com/u/25906270?v=4"},"body":"> Junio C Hamano <gitster@pobox.com> wrote:\n> \n> Please do not send patches this way.  Giving responses to review\n> comments is very good and strongly encouraged, but stop the response\n> message with \"a new version of the patch coming!\" and have a separate\n> message for the patch itself.\n> \n> It sometimes is done to interject a sample patch in the middle of a\n> discussion, but then the convention is\n> \n> ... continuation of an existing discussion ...\n> \n> So, how about doing things this way?\n> \n> --- >8 ---\n> Subject: the title of the patch\n> \n> The proposed log message for the commit comes here\n> \n> Signed-off-by: you\n> ---\n> \n> ... notes, diffstat, diff ...\n> \n> i.e., use a scissors line to tell the receiving end that the rest of\n> the message is a patch message, and override the Subject: with an\n> in-body header.  Omit the (From <object-name> Mon Sep 17 2001)\n> \"magic\" line, \"From:\" and \"Date:\".  The last two can be taken from\n> the e-mail message anyway.\n\nThanks for your feedback on the patch submission format. Resending v2 as a separate message."},{"id":"535446","messageId":"3488DCC3-D127-465B-BB95-3D87BB2E48F6@ytausch.de","threadId":"64927","inReplyTo":"75AA7DD7-F8D8-48DC-ADA0-74E56CFF351D@ytausch.de","subject":"[PATCH v2] merge-file: honor merge.conflictStyle outside of a repository","fromName":"Yannik Tausch","fromEmail":"dev@ytausch.de","sentAt":"2026-02-07T21:37:48Z","receivedAt":"2026-02-07T21:38:27Z","isPatch":true,"sender":{"key":"dev@ytausch.de","avatar":"https://avatars.githubusercontent.com/u/25906270?v=4"},"body":"When running outside a repository, git merge-file ignores the\nmerge.conflictStyle configuration variable entirely. Since the\nfunction receives `repo` from the caller (which is NULL outside a\nrepository), and repo_config() falls back to reading system and user\nconfiguration when passed NULL, pass `repo` to repo_config()\nunconditionally.\n\nAlso document that merge.conflictStyle is honored.\n\nSigned-off-by: Yannik Tausch <dev@ytausch.de>\n---\n\nNotes:\n   Changes since v1:\n   - Use repo parameter directly with repo_config() (Junio)\n   - Fix AsciiDoc continuation, rename test files, break long\n     lines (Kristoffer)\n\n Documentation/git-merge-file.adoc |  3 +++\n builtin/merge-file.c              | 12 +++++------\n t/t6403-merge-file.sh             | 36 +++++++++++++++++++++++++++++++\n 3 files changed, 44 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/git-merge-file.adoc b/Documentation/git-merge-file.adoc\nindex 71915a00fa..9dc5d8a370 100644\n--- a/Documentation/git-merge-file.adoc\n+++ b/Documentation/git-merge-file.adoc\n@@ -85,6 +85,9 @@ object store and the object ID of its blob is written to standard output.\n \n --zdiff3::\n \tShow conflicts in \"zdiff3\" style.\n++\n+The `--diff3` and `--zdiff3` options default to the value of the\n+`merge.conflictStyle` configuration variable (see linkgit:git-config[1]).\n \n --ours::\n --theirs::\ndiff --git a/builtin/merge-file.c b/builtin/merge-file.c\nindex 46775d0c79..f9de636884 100644\n--- a/builtin/merge-file.c\n+++ b/builtin/merge-file.c\n@@ -60,7 +60,7 @@ static int diff_algorithm_cb(const struct option *opt,\n int cmd_merge_file(int argc,\n \t\t   const char **argv,\n \t\t   const char *prefix,\n-\t\t   struct repository *repo UNUSED)\n+\t\t   struct repository *repo)\n {\n \tconst char *names[3] = { 0 };\n \tmmfile_t mmfs[3] = { 0 };\n@@ -95,12 +95,10 @@ int cmd_merge_file(int argc,\n \txmp.style = 0;\n \txmp.favor = 0;\n \n-\tif (startup_info->have_repository) {\n-\t\t/* Read the configuration file */\n-\t\trepo_config(the_repository, git_xmerge_config, NULL);\n-\t\tif (0 <= git_xmerge_style)\n-\t\t\txmp.style = git_xmerge_style;\n-\t}\n+\t/* Read the configuration file */\n+\trepo_config(repo, git_xmerge_config, NULL);\n+\tif (0 <= git_xmerge_style)\n+\t\txmp.style = git_xmerge_style;\n \n \targc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);\n \tif (argc != 3)\ndiff --git a/t/t6403-merge-file.sh b/t/t6403-merge-file.sh\nindex 06ab4d7aed..4d6e748320 100755\n--- a/t/t6403-merge-file.sh\n+++ b/t/t6403-merge-file.sh\n@@ -428,6 +428,42 @@ test_expect_success '\"diff3 -m\" style output (2)' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'merge.conflictStyle honored outside repo' '\n+\ttest_config_global merge.conflictStyle diff3 &&\n+\tcat >nongit-base <<-\\EOF &&\n+\tline1\n+\toriginal\n+\tline3\n+\tEOF\n+\tcat >nongit-ours <<-\\EOF &&\n+\tline1\n+\tours\n+\tline3\n+\tEOF\n+\tcat >nongit-theirs <<-\\EOF &&\n+\tline1\n+\ttheirs\n+\tline3\n+\tEOF\n+\tcat >expect <<-\\EOF &&\n+\tline1\n+\t<<<<<<< ours\n+\tours\n+\t||||||| base\n+\toriginal\n+\t=======\n+\ttheirs\n+\t>>>>>>> theirs\n+\tline3\n+\tEOF\n+\ttest_must_fail nongit git merge-file -p \\\n+\t\t-L ours -L base -L theirs \\\n+\t\t\"$PWD/nongit-ours\" \\\n+\t\t\"$PWD/nongit-base\" \\\n+\t\t\"$PWD/nongit-theirs\" >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'marker size' '\n \tcat >expect <<-\\EOF &&\n \tDominus regit me,\n-- \n2.52.0\n\n"},{"id":"535449","messageId":"825e7404-f781-4739-a37b-ae3d095fda4d@app.fastmail.com","threadId":"64927","inReplyTo":"3488DCC3-D127-465B-BB95-3D87BB2E48F6@ytausch.de","subject":"Re: [PATCH v2] merge-file: honor merge.conflictStyle outside of a repository","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-02-07T21:47:44Z","receivedAt":"2026-02-07T21:48:05Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Sat, Feb 7, 2026, at 22:37, Yannik Tausch wrote:\n> When running outside a repository, git merge-file ignores the\n> merge.conflictStyle configuration variable entirely. Since the\n> function receives `repo` from the caller (which is NULL outside a\n> repository), and repo_config() falls back to reading system and user\n> configuration when passed NULL, pass `repo` to repo_config()\n> unconditionally.\n>\n> Also document that merge.conflictStyle is honored.\n>\n> Signed-off-by: Yannik Tausch <dev@ytausch.de>\n> ---\n\nThis looks good to me. Based on my previous feedback.\n\n>\n> Notes:\n>    Changes since v1:\n>    - Use repo parameter directly with repo_config() (Junio)\n>    - Fix AsciiDoc continuation, rename test files, break long\n>      lines (Kristoffer)\n\nNice and tidy change notes/changelog.\n\n>[snip]\n"},{"id":"535507","messageId":"aYmkCLbhZPPjKqNK@pks.im","threadId":"64927","inReplyTo":"3488DCC3-D127-465B-BB95-3D87BB2E48F6@ytausch.de","subject":"Re: [PATCH v2] merge-file: honor merge.conflictStyle outside of a repository","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-02-09T09:08:24Z","receivedAt":"2026-02-09T09:08:38Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Sat, Feb 07, 2026 at 10:37:48PM +0100, Yannik Tausch wrote:\n> diff --git a/builtin/merge-file.c b/builtin/merge-file.c\n> index 46775d0c79..f9de636884 100644\n> --- a/builtin/merge-file.c\n> +++ b/builtin/merge-file.c\n> @@ -95,12 +95,10 @@ int cmd_merge_file(int argc,\n>  \txmp.style = 0;\n>  \txmp.favor = 0;\n>  \n> -\tif (startup_info->have_repository) {\n> -\t\t/* Read the configuration file */\n> -\t\trepo_config(the_repository, git_xmerge_config, NULL);\n> -\t\tif (0 <= git_xmerge_style)\n> -\t\t\txmp.style = git_xmerge_style;\n> -\t}\n> +\t/* Read the configuration file */\n> +\trepo_config(repo, git_xmerge_config, NULL);\n> +\tif (0 <= git_xmerge_style)\n> +\t\txmp.style = git_xmerge_style;\n>  \n>  \targc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);\n>  \tif (argc != 3)\n\nMakes sense. I was briefly wondering about error handling in the old/new\ncode, but unknown keys are already handled by `git_xmerge_config()`, and\nwe'd die in case we see one.\n\nSo this patch looks good to me overall, thanks!\n\nPatrick\n"},{"id":"535557","messageId":"xmqq1pit7v3v.fsf@gitster.g","threadId":"64927","inReplyTo":"aYmkCLbhZPPjKqNK@pks.im","subject":"Re: [PATCH v2] merge-file: honor merge.conflictStyle outside of a repository","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-09T16:13:56Z","receivedAt":"2026-02-09T16:13:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> On Sat, Feb 07, 2026 at 10:37:48PM +0100, Yannik Tausch wrote:\n>> diff --git a/builtin/merge-file.c b/builtin/merge-file.c\n>> index 46775d0c79..f9de636884 100644\n>> --- a/builtin/merge-file.c\n>> +++ b/builtin/merge-file.c\n>> @@ -95,12 +95,10 @@ int cmd_merge_file(int argc,\n>>  \txmp.style = 0;\n>>  \txmp.favor = 0;\n>>  \n>> -\tif (startup_info->have_repository) {\n>> -\t\t/* Read the configuration file */\n>> -\t\trepo_config(the_repository, git_xmerge_config, NULL);\n>> -\t\tif (0 <= git_xmerge_style)\n>> -\t\t\txmp.style = git_xmerge_style;\n>> -\t}\n>> +\t/* Read the configuration file */\n>> +\trepo_config(repo, git_xmerge_config, NULL);\n>> +\tif (0 <= git_xmerge_style)\n>> +\t\txmp.style = git_xmerge_style;\n>>  \n>>  \targc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);\n>>  \tif (argc != 3)\n>\n> Makes sense. I was briefly wondering about error handling in the old/new\n> code, but unknown keys are already handled by `git_xmerge_config()`, and\n> we'd die in case we see one.\n>\n> So this patch looks good to me overall, thanks!\n>\n> Patrick\n\nYeah, looking good.  Thanks, both of you.\n"}]}