{"thread":{"id":"15311","subject":"[PATCH 1/2] checkout --conflict=<style>: recreate merge in a non-default style","startedAt":"2008-09-01T06:22:29Z","lastAt":"2008-09-01T10:39:07Z","messageCount":3,"participants":["Junio C Hamano","Johannes Sixt"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"89365","messageId":"7v4p501j2y.fsf@gitster.siamese.dyndns.org","threadId":"15311","inReplyTo":null,"subject":"[PATCH 1/2] checkout --conflict=<style>: recreate merge in a non-default style","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-09-01T06:22:29Z","receivedAt":"2008-09-01T06:22:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This new option does essentially the same thing as -m option when checking\nunmerged paths out of the index, but it uses the specified style instead\nof configured merge.conflictstyle.\n\nSetting \"merge.conflictstyle\" to \"diff3\" is usually less useful than using\nthe default \"merge\" style, because the latter allows a conflict that\nresults by both sides changing the same region in a very similar way to\nget simplified substancially by reducing the common lines.  However, when\none side removed a group of lines (perhaps a function was moved to some\nother file) while the other side modified it, the default \"merge\" style\ndoes not give any clue as to why the hunk is left conflicting.  You would\nneed the original to understand what is going on.\n\nThe recommended use would be not to set merge.conflictstyle variable so\nthat you would usually use the default \"merge\" style conflict, and when\nthe result in a path in a particular merge is too hard to understand, use\n\"git checkout --conflict=diff3 $path\" to check it out with the original to\nreview what is going on.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n * This comes on top of the previous series (the series got reordered\n   in my tree before it was merged to 'next', but it is essentially the\n   same).\n\n Documentation/git-checkout.txt |   10 ++++-\n builtin-checkout.c             |   10 ++++-\n t/t7201-co.sh                  |  100 +++++++++++++++++++++------------------\n 3 files changed, 72 insertions(+), 48 deletions(-)\n\ndiff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt\nindex c884862..13b106d 100644\n--- a/Documentation/git-checkout.txt\n+++ b/Documentation/git-checkout.txt\n@@ -9,7 +9,7 @@ SYNOPSIS\n --------\n [verse]\n 'git checkout' [-q] [-f] [[--track | --no-track] -b <new_branch> [-l]] [-m] [<branch>]\n-'git checkout' [-f|--ours|--theirs|-m] [<tree-ish>] [--] <paths>...\n+'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...\n \n DESCRIPTION\n -----------\n@@ -84,6 +84,7 @@ entries; instead, unmerged entries are ignored.\n \tbased sha1 expressions such as \"<branchname>@\\{yesterday}\".\n \n -m::\n+--merge::\n \tWhen switching branches,\n \tif you have local modifications to one or more files that\n \tare different between the current branch and the branch to\n@@ -101,6 +102,13 @@ should result in deletion of the path).\n When checking out paths from the index, this option lets you recreate\n the conflicted merge in the specified paths.\n \n+--conflict=<style>::\n+\tThe same as --merge option above, but changes the way the\n+\tconflicting hunks are presented, overriding the\n+\tmerge.conflictstyle configuration variable.  Possible values are\n+\t\"merge\" (default) and \"diff3\" (in addition to what is shown by\n+\t\"merge\" style, shows the original contents).\n+\n <new_branch>::\n \tName for the new branch.\n \ndiff --git a/builtin-checkout.c b/builtin-checkout.c\nindex b957193..7921432 100644\n--- a/builtin-checkout.c\n+++ b/builtin-checkout.c\n@@ -580,6 +580,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \tconst char *arg;\n \tstruct branch_info new;\n \tstruct tree *source_tree = NULL;\n+\tchar *conflict_style = NULL;\n \tstruct option options[] = {\n \t\tOPT__QUIET(&opts.quiet),\n \t\tOPT_STRING('b', NULL, &opts.new_branch, \"new branch\", \"branch\"),\n@@ -591,7 +592,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \t\tOPT_SET_INT('3', \"theirs\", &opts.writeout_stage, \"stage\",\n \t\t\t    3),\n \t\tOPT_BOOLEAN('f', NULL, &opts.force, \"force\"),\n-\t\tOPT_BOOLEAN('m', NULL, &opts.merge, \"merge\"),\n+\t\tOPT_BOOLEAN('m', \"merge\", &opts.merge, \"merge\"),\n+\t\tOPT_STRING(0, \"conflict\", &conflict_style, \"style\",\n+\t\t\t   \"conflict style (merge or diff3)\"),\n \t\tOPT_END(),\n \t};\n \tint has_dash_dash;\n@@ -606,6 +609,11 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, options, checkout_usage,\n \t\t\t     PARSE_OPT_KEEP_DASHDASH);\n \n+\tif (conflict_style) {\n+\t\topts.merge = 1; /* implied */\n+\t\tgit_xmerge_config(\"merge.conflictstyle\", conflict_style, NULL);\n+\t}\n+\n \tif (!opts.new_branch && (opts.track != git_branch_track))\n \t\tdie(\"git checkout: --track and --no-track require -b\");\n \ndiff --git a/t/t7201-co.sh b/t/t7201-co.sh\nindex 1d4ff6e..ac49311 100755\n--- a/t/t7201-co.sh\n+++ b/t/t7201-co.sh\n@@ -337,7 +337,7 @@ test_expect_success \\\n     test refs/heads/delete-me = \"$(git symbolic-ref HEAD)\" &&\n     test_must_fail git checkout --track -b track'\n \n-test_expect_success 'checkout an unmerged path should fail' '\n+setup_conflicting_index () {\n \trm -f .git/index &&\n \tO=$(echo original | git hash-object -w --stdin) &&\n \tA=$(echo ourside | git hash-object -w --stdin) &&\n@@ -348,7 +348,11 @@ test_expect_success 'checkout an unmerged path should fail' '\n \t\techo \"100644 $A 2\tfile\" &&\n \t\techo \"100644 $B 3\tfile\" &&\n \t\techo \"100644 $A 0\tfilf\"\n-\t) | git update-index --index-info &&\n+\t) | git update-index --index-info\n+}\n+\n+test_expect_success 'checkout an unmerged path should fail' '\n+\tsetup_conflicting_index &&\n \techo \"none of the above\" >sample &&\n \tcat sample >fild &&\n \tcat sample >file &&\n@@ -360,17 +364,7 @@ test_expect_success 'checkout an unmerged path should fail' '\n '\n \n test_expect_success 'checkout with an unmerged path can be ignored' '\n-\trm -f .git/index &&\n-\tO=$(echo original | git hash-object -w --stdin) &&\n-\tA=$(echo ourside | git hash-object -w --stdin) &&\n-\tB=$(echo theirside | git hash-object -w --stdin) &&\n-\t(\n-\t\techo \"100644 $A 0\tfild\" &&\n-\t\techo \"100644 $O 1\tfile\" &&\n-\t\techo \"100644 $A 2\tfile\" &&\n-\t\techo \"100644 $B 3\tfile\" &&\n-\t\techo \"100644 $A 0\tfilf\"\n-\t) | git update-index --index-info &&\n+\tsetup_conflicting_index &&\n \techo \"none of the above\" >sample &&\n \techo ourside >expect &&\n \tcat sample >fild &&\n@@ -383,17 +377,7 @@ test_expect_success 'checkout with an unmerged path can be ignored' '\n '\n \n test_expect_success 'checkout unmerged stage' '\n-\trm -f .git/index &&\n-\tO=$(echo original | git hash-object -w --stdin) &&\n-\tA=$(echo ourside | git hash-object -w --stdin) &&\n-\tB=$(echo theirside | git hash-object -w --stdin) &&\n-\t(\n-\t\techo \"100644 $A 0\tfild\" &&\n-\t\techo \"100644 $O 1\tfile\" &&\n-\t\techo \"100644 $A 2\tfile\" &&\n-\t\techo \"100644 $B 3\tfile\" &&\n-\t\techo \"100644 $A 0\tfilf\"\n-\t) | git update-index --index-info &&\n+\tsetup_conflicting_index &&\n \techo \"none of the above\" >sample &&\n \techo ourside >expect &&\n \tcat sample >fild &&\n@@ -408,17 +392,7 @@ test_expect_success 'checkout unmerged stage' '\n '\n \n test_expect_success 'checkout with --merge' '\n-\trm -f .git/index &&\n-\tO=$(echo original | git hash-object -w --stdin) &&\n-\tA=$(echo ourside | git hash-object -w --stdin) &&\n-\tB=$(echo theirside | git hash-object -w --stdin) &&\n-\t(\n-\t\techo \"100644 $A 0\tfild\" &&\n-\t\techo \"100644 $O 1\tfile\" &&\n-\t\techo \"100644 $A 2\tfile\" &&\n-\t\techo \"100644 $B 3\tfile\" &&\n-\t\techo \"100644 $A 0\tfilf\"\n-\t) | git update-index --index-info &&\n+\tsetup_conflicting_index &&\n \techo \"none of the above\" >sample &&\n \techo ourside >expect &&\n \tcat sample >fild &&\n@@ -439,17 +413,7 @@ test_expect_success 'checkout with --merge' '\n \n test_expect_success 'checkout with --merge, in diff3 -m style' '\n \tgit config merge.conflictstyle diff3 &&\n-\trm -f .git/index &&\n-\tO=$(echo original | git hash-object -w --stdin) &&\n-\tA=$(echo ourside | git hash-object -w --stdin) &&\n-\tB=$(echo theirside | git hash-object -w --stdin) &&\n-\t(\n-\t\techo \"100644 $A 0\tfild\" &&\n-\t\techo \"100644 $O 1\tfile\" &&\n-\t\techo \"100644 $A 2\tfile\" &&\n-\t\techo \"100644 $B 3\tfile\" &&\n-\t\techo \"100644 $A 0\tfilf\"\n-\t) | git update-index --index-info &&\n+\tsetup_conflicting_index &&\n \techo \"none of the above\" >sample &&\n \techo ourside >expect &&\n \tcat sample >fild &&\n@@ -470,4 +434,48 @@ test_expect_success 'checkout with --merge, in diff3 -m style' '\n \ttest_cmp merged file\n '\n \n+test_expect_success 'checkout --conflict=merge, overriding config' '\n+\tgit config merge.conflictstyle diff3 &&\n+\tsetup_conflicting_index &&\n+\techo \"none of the above\" >sample &&\n+\techo ourside >expect &&\n+\tcat sample >fild &&\n+\tcat sample >file &&\n+\tcat sample >filf &&\n+\tgit checkout --conflict=merge -- fild file filf &&\n+\t(\n+\t\techo \"<<<<<<< ours\"\n+\t\techo ourside\n+\t\techo \"=======\"\n+\t\techo theirside\n+\t\techo \">>>>>>> theirs\"\n+\t) >merged &&\n+\ttest_cmp expect fild &&\n+\ttest_cmp expect filf &&\n+\ttest_cmp merged file\n+'\n+\n+test_expect_success 'checkout --conflict=diff3' '\n+\tgit config --unset merge.conflictstyle\n+\tsetup_conflicting_index &&\n+\techo \"none of the above\" >sample &&\n+\techo ourside >expect &&\n+\tcat sample >fild &&\n+\tcat sample >file &&\n+\tcat sample >filf &&\n+\tgit checkout --conflict=diff3 -- fild file filf &&\n+\t(\n+\t\techo \"<<<<<<< ours\"\n+\t\techo ourside\n+\t\techo \"|||||||\"\n+\t\techo original\n+\t\techo \"=======\"\n+\t\techo theirside\n+\t\techo \">>>>>>> theirs\"\n+\t) >merged &&\n+\ttest_cmp expect fild &&\n+\ttest_cmp expect filf &&\n+\ttest_cmp merged file\n+'\n+\n test_done\n-- \n1.6.0.1.260.g7aa8\n"},{"id":"89371","messageId":"48BB9F45.4070509@viscovery.net","threadId":"15311","inReplyTo":"7v4p501j2y.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 1/2] checkout --conflict=<style>: recreate merge in a non-default style","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2008-09-01T07:52:37Z","receivedAt":"2008-09-01T07:52:37Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Junio C Hamano schrieb:\n> +--conflict=<style>::\n> +\tThe same as --merge option above, but changes the way the\n> +\tconflicting hunks are presented, overriding the\n> +\tmerge.conflictstyle configuration variable.  Possible values are\n> +\t\"merge\" (default) and \"diff3\" (in addition to what is shown by\n> +\t\"merge\" style, shows the original contents).\n> +\n\nIf --conflict is basically the same as --merge, couldn't we then pass\nstyle argument to --merge or omit it to get the default style?\n\n-- Hannes\n"},{"id":"89401","messageId":"7vhc90w3p0.fsf@gitster.siamese.dyndns.org","threadId":"15311","inReplyTo":"48BB9F45.4070509@viscovery.net","subject":"Re: [PATCH 1/2] checkout --conflict=<style>: recreate merge in a non-default style","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-09-01T10:39:07Z","receivedAt":"2008-09-01T10:39:07Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Sixt <j.sixt@viscovery.net> writes:\n\n> If --conflict is basically the same as --merge, couldn't we then pass\n> style argument to --merge or omit it to get the default style?\n\nI originally was thinking about doing it that way, but the option parsing\nwould become somewhat hairly.\n\n    $ git checkout --merge=diff3 foo\n    $ git checkout --merge diff3 foo\n    $ git checkout --merge diff3\n\nThe first one is clearly \"switch to branch 'foo'; simple 2-way read-tree\nmay find the changes in my working tree conflicting and refuse, so use\n3-way merge to resolve such conflicts and express the conflicts in diff3\nstyle\".\n\nThe third one is \"switch to branch 'diff3'; don't barf on conflicting\nworking tree changes; 3-way merge them\".\n\nWhat about the second one?  Is it \"switch to 'foo', express conflicts in\ndiff3 style\", or \"checkout path foo from tree-ish diff3\"?\n\nIt is the former, but that is only because the latter is an error (-m is\ndefined only for checking things out of the index).  That is not something\nparse-options can easily/cleanly do.\n"}]}