{"thread":{"id":"26169","subject":"Why doesn't git rebase --interactive --preserve-merges continue past known conflicts?","startedAt":"2010-12-31T19:30:46Z","lastAt":"2011-01-02T01:20:02Z","messageCount":2,"participants":["David D. Kilzer"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"158793","messageId":"282560.39741.qm@web30004.mail.mud.yahoo.com","threadId":"26169","inReplyTo":null,"subject":"Why doesn't git rebase --interactive --preserve-merges continue past known conflicts?","fromName":"David D. Kilzer","fromEmail":"ddkilzer@kilzer.net","sentAt":"2010-12-31T19:30:46Z","receivedAt":"2010-12-31T19:30:46Z","isPatch":false,"sender":{"key":"ddkilzer@kilzer.net","avatar":"https://avatars.githubusercontent.com/u/263571?v=4"},"body":"When I run \"git rebase --interactive --preserve-merges\" on a sequence of \ncommits, edit an earlier commit, then run \"git rebase --continue\", the rebase \noperation always stops on a merge commit with a known conflict (in the rr-cache) \ninstead of resolving it and continuing.\n\nAs long as I'm not rearranging commits, I expect git-rebase to resolve the known \nmerge commit conflict and continue.  Why does it always stop?\n\nI've attached a simple test case that demonstrates this behavior.\n\nDave\n"},{"id":"158805","messageId":"1293931202-88931-1-git-send-email-ddkilzer@kilzer.net","threadId":"26169","inReplyTo":"282560.39741.qm@web30004.mail.mud.yahoo.com","subject":"[RFC PATCH] Why doesn't git rebase --interactive --preserve-merges continue past known conflicts?","fromName":"David D. Kilzer","fromEmail":"ddkilzer@kilzer.net","sentAt":"2011-01-02T01:20:02Z","receivedAt":"2011-01-02T01:20:02Z","isPatch":true,"sender":{"key":"ddkilzer@kilzer.net","avatar":"https://avatars.githubusercontent.com/u/263571?v=4"},"body":"On 2010-12-31, David Kilzer wrote:\n> When I run \"git rebase --interactive --preserve-merges\" on a sequence of \n> commits, edit an earlier commit, then run \"git rebase --continue\", the rebase \n> operation always stops on a merge commit with a known conflict (in the rr-cache) \n> instead of resolving it and continuing.\n> \n> As long as I'm not rearranging commits, I expect git-rebase to resolve the known \n> merge commit conflict and continue.  Why does it always stop?\n\nHere's a very rough patch that fixes my original test case so that an interactive\nrebase won't stop when git-rerere knows how to resolve all conflicts during a\nmerge.\n\nHowever, if there are any changes to a non-conflicted file during the original\nmerge commit, they will be lost when rebasing, even with --preserve-merges.\nNote that this occurs even without this patch applied.  You must compare the\ncurrent commit with original being rebased to make sure they're not lost.\n\nWhy doesn't an interactive rebase serialize to disk all of the changes in a merge\ncommit like it does for non-merge commits?\n\nDave\n---\n git-rebase--interactive.sh                    |   11 ++++-\n t/t3404-rebase-interactive-preserve-merges.sh |   64 +++++++++++++++++++++++++\n 2 files changed, 73 insertions(+), 2 deletions(-)\n create mode 100755 t/t3404-rebase-interactive-preserve-merges.sh\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex a5ffd9a..32375bc 100755\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -338,11 +338,18 @@ pick_one_preserving_merges () {\n \t\t\tmsg=\"$(commit_message $sha1)\"\n \t\t\t# No point in merging the first parent, that's HEAD\n \t\t\tnew_parents=${new_parents# $first_parent}\n+\t\t\t# If rerere is enabled, pass the --rerere-autoupdate flag\n+\t\t\ttest \"$(git config --bool rerere.enabled)\" = \"true\" &&\n+\t\t\t\trerere_autoupdate=--rerere-autoupdate || rerere_autoupdate=\n \t\t\tif ! do_with_author output \\\n-\t\t\t\tgit merge $STRATEGY -m \"$msg\" $new_parents\n+\t\t\t\tgit merge $STRATEGY $rerere_autoupdate -m \"$msg\" $new_parents\n \t\t\tthen\n \t\t\t\tprintf \"%s\\n\" \"$msg\" > \"$GIT_DIR\"/MERGE_MSG\n-\t\t\t\tdie_with_patch $sha1 \"Error redoing merge $sha1\"\n+\t\t\t\t# Commit the result if rerere resolved all the conflicts.\n+\t\t\t\tgit update-index -q --refresh &&\n+\t\t\t\t\tprintf \"Resolved all conflicts using rerere.\\n\"  &&\n+\t\t\t\t\tdo_with_author git commit --no-verify -F \"$GIT_DIR\"/MERGE_MSG ||\n+\t\t\t\t\tdie_with_patch $sha1 \"Error redoing merge $sha1\"\n \t\t\tfi\n \t\t\techo \"$sha1 $(git rev-parse HEAD^0)\" >> \"$REWRITTEN_LIST\"\n \t\t\t;;\ndiff --git a/t/t3404-rebase-interactive-preserve-merges.sh b/t/t3404-rebase-interactive-preserve-merges.sh\nnew file mode 100755\nindex 0000000..3479f38\n--- /dev/null\n+++ b/t/t3404-rebase-interactive-preserve-merges.sh\n@@ -0,0 +1,64 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2007 Johannes E. Schindelin\n+# Copyright (c) 2010 David D. Kilzer\n+#\n+\n+test_description='git rebase --interactive --preserve-matches does not automatically resolve known conflicts in merge commits'\n+. ./test-lib.sh\n+\n+. \"$TEST_DIRECTORY\"/lib-rebase.sh\n+\n+set_fake_editor\n+\n+test_expect_success 'setup' '\n+\ttest_commit A file1 &&\n+\ttest_commit AA file2 &&\n+\ttest_commit B file1 &&\n+\tgit checkout -b topic1 HEAD^ &&\n+\ttest_commit C file1 &&\n+\tgit checkout master\n+'\n+\n+test_expect_success 'rebase --interactive --preserve-merges should use rerere to resolve conflicts' '\n+\tgit config rerere.enabled 1 &&\n+\tgit rerere clear &&\n+\n+\tgit checkout -b merge1 master &&\n+\ttest_must_fail git merge topic1 &&\n+\tprintf \"B\\nC\\n\" > file1 &&\n+\tgit add file1 &&\n+\tgit commit -m \"Merged.\" &&\n+\tgit branch merge1-baseline &&\n+\n+\tFAKE_LINES=\"edit 1 2\" git rebase -i -p HEAD~2 &&\n+\techo BB >> file2 &&\n+\tgit add file2 &&\n+\tgit commit --amend &&\n+\tgit rebase --continue &&\n+\tgit diff --exit-code merge1-baseline..merge1 file1\n+'\n+\n+test_expect_success 'rebase --interactive --preserve-merges should not lose changes in merge commits' '\n+\tgit config rerere.enabled 1 &&\n+\tgit rerere clear &&\n+\n+\tgit checkout -b merge2 master &&\n+\ttest_must_fail git merge topic1 &&\n+\tprintf \"B\\nC\\n\" > file1 &&\n+\tgit add file1 &&\n+\techo BB >> file2 &&\n+\tgit add file2 &&\n+\tgit commit -m \"Merged with change to non-conflicted file.\" &&\n+\tgit branch merge2-baseline &&\n+\n+\tFAKE_LINES=\"edit 1 2\" git rebase -i -p HEAD~2 &&\n+\techo AAA > file3 &&\n+\tgit add file3 &&\n+\tgit commit --amend &&\n+\tgit rebase --continue &&\n+\tgit diff --exit-code merge2-baseline..merge2 file1 &&\n+\tgit diff --exit-code merge2-baseline..merge2 file2\n+'\n+\n+test_done\n-- \n1.7.2.1.103.g48452\n"}]}