{"thread":{"id":"34755","subject":"[PATCH v2 0/3] fix interactive rebase short SHA-1 collision bug","startedAt":"2013-08-24T00:10:39Z","lastAt":"2013-08-26T07:19:22Z","messageCount":6,"participants":["Eric Sunshine","Jonathan Nieder","Junio C Hamano"],"isPatch":true,"patchVersion":2,"patchTotal":3},"messages":[{"id":"225760","messageId":"1377303042-50868-1-git-send-email-sunshine@sunshineco.com","threadId":"34755","inReplyTo":null,"subject":"[PATCH v2 0/3] fix interactive rebase short SHA-1 collision bug","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2013-08-24T00:10:39Z","receivedAt":"2013-08-24T00:10:39Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"This is a re-roll of [1] which fixes a short SHA-1 collision bug during\nrebase -i. v1 graduated to 'next' quickly, before I was able to post a\nre-roll addressing Junio's review comments, so I instead posted fixes as\nincremental patches atop 'next' [2]. Also, after already in 'next', I\ndiscovered an issue in patch 3/3 where it ignored core.commentchar. This\nwas fixed by another incremental patch atop 'next' [3].\n\nJunio suggested [4] that, when 'next' is ready to be rewound after 1.8.4\nis released, a replacement to the original series should be sent with\nall the incremental patches squashed in.  This re-roll does just that.\nIt incorporates all the incremental patches and presents the series\nafresh. This series is meant to supersede all of the following commits\nin 'next':\n\n* v1 series\n\n4ababc19e3b6 (t3404: restore specialized rebase-editor following\n    commentchar test; 2013-08-12)\ncda44c3b5098 (t3404: rebase: interactive: demonstrate short SHA-1\n    collision; 2013-08-12)\n9a46c25bdbf7 (rebase: interactive: fix short SHA-1 collision;\n    2013-08-12)\n\n* patches addressing review comments & general cleanup\n\n4bd24da943d9 (t3404: preserve test_tick state across short SHA-1\n    collision test; 2013-08-21)\nd63f172cfd90 (t3404: make tests more self-contained; 2013-08-21)\n7883ad2419a3 (t3404: simplify short SHA-1 collision test; 2013-08-21)\n\n* core.commentchar bug fix\n\ncd5ce1625074 (rebase -i: fix core.commentchar regression; 2013-08-18)\n\n[This series does not include the similar core.commentchar bug fix\n7bca7afeff6f (rebase -i: fix cases ignoring core.commentchar;\n2013-08-16) currently in 'next' which is intended for 'maint' and\n'master'.]\n\n[1]: http://thread.gmane.org/gmane.comp.version-control.git/232146\n[2]: http://thread.gmane.org/gmane.comp.version-control.git/232718\n[3]: http://thread.gmane.org/gmane.comp.version-control.git/232482/focus=232483\n[4]: http://thread.gmane.org/gmane.comp.version-control.git/232718/focus=232771\n\nEric Sunshine (2):\n  t3404: make tests more self-contained\n  t3404: rebase -i: demonstrate short SHA-1 collision\n\nJunio C Hamano (1):\n  rebase -i: fix short SHA-1 collision\n\n git-rebase--interactive.sh    | 30 +++++++++++++++\n t/t3404-rebase-interactive.sh | 89 ++++++++++++++++++++++++++++++++++++++++++-\n 2 files changed, 117 insertions(+), 2 deletions(-)\n\n-- \n1.8.4.557.g34b3a2e\n"},{"id":"225761","messageId":"1377303042-50868-2-git-send-email-sunshine@sunshineco.com","threadId":"34755","inReplyTo":"1377303042-50868-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v2 1/3] t3404: make tests more self-contained","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2013-08-24T00:10:40Z","receivedAt":"2013-08-24T00:10:40Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"As its very first action, t3404 installs (via set_fake_editor) a\nspecialized $EDITOR which simplifies automated 'rebase -i' testing. Many\ntests rely upon this setting, thus tests which need a different editor\nmust take extra care upon completion to restore $EDITOR in order to\navoid breaking following tests. This places extra burden upon such tests\nand requires that they undesirably have extra knowledge about\nsurrounding tests. Ease this burden by having each test install the\n$EDITOR it requires, rather than relying upon a global setting.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n t/t3404-rebase-interactive.sh | 65 +++++++++++++++++++++++++++++++++++++++++--\n 1 file changed, 63 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex 49ccb38..f857161 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -29,8 +29,6 @@ Initial setup:\n \n . \"$TEST_DIRECTORY\"/lib-rebase.sh\n \n-set_fake_editor\n-\n # WARNING: Modifications to the initial repository can change the SHA ID used\n # in the expect2 file for the 'stop on conflicting pick' test.\n \n@@ -72,6 +70,7 @@ export SHELL\n test_expect_success 'rebase -i with the exec command' '\n \tgit checkout master &&\n \t(\n+\tset_fake_editor &&\n \tFAKE_LINES=\"1 exec_>touch-one\n \t\t2 exec_>touch-two exec_false exec_>touch-three\n \t\t3 4 exec_>\\\"touch-file__name_with_spaces\\\";_>touch-after-semicolon 5\" &&\n@@ -93,6 +92,7 @@ test_expect_success 'rebase -i with the exec command' '\n test_expect_success 'rebase -i with the exec command runs from tree root' '\n \tgit checkout master &&\n \tmkdir subdir && (cd subdir &&\n+\tset_fake_editor &&\n \tFAKE_LINES=\"1 exec_>touch-subdir\" \\\n \t\tgit rebase -i HEAD^\n \t) &&\n@@ -103,6 +103,7 @@ test_expect_success 'rebase -i with the exec command runs from tree root' '\n test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n \tgit checkout master &&\n \t(\n+\tset_fake_editor &&\n \tFAKE_LINES=\"exec_echo_foo_>file1 1\" &&\n \texport FAKE_LINES &&\n \ttest_must_fail git rebase -i HEAD^\n@@ -116,6 +117,7 @@ test_expect_success 'rebase -i with exec of inexistent command' '\n \tgit checkout master &&\n \ttest_when_finished \"git rebase --abort\" &&\n \t(\n+\tset_fake_editor &&\n \tFAKE_LINES=\"exec_this-command-does-not-exist 1\" &&\n \texport FAKE_LINES &&\n \ttest_must_fail git rebase -i HEAD^ >actual 2>&1\n@@ -125,6 +127,7 @@ test_expect_success 'rebase -i with exec of inexistent command' '\n \n test_expect_success 'no changes are a nop' '\n \tgit checkout branch2 &&\n+\tset_fake_editor &&\n \tgit rebase -i F &&\n \ttest \"$(git symbolic-ref -q HEAD)\" = \"refs/heads/branch2\" &&\n \ttest $(git rev-parse I) = $(git rev-parse HEAD)\n@@ -134,6 +137,7 @@ test_expect_success 'test the [branch] option' '\n \tgit checkout -b dead-end &&\n \tgit rm file6 &&\n \tgit commit -m \"stop here\" &&\n+\tset_fake_editor &&\n \tgit rebase -i F branch2 &&\n \ttest \"$(git symbolic-ref -q HEAD)\" = \"refs/heads/branch2\" &&\n \ttest $(git rev-parse I) = $(git rev-parse branch2) &&\n@@ -142,6 +146,7 @@ test_expect_success 'test the [branch] option' '\n \n test_expect_success 'test --onto <branch>' '\n \tgit checkout -b test-onto branch2 &&\n+\tset_fake_editor &&\n \tgit rebase -i --onto branch1 F &&\n \ttest \"$(git symbolic-ref -q HEAD)\" = \"refs/heads/test-onto\" &&\n \ttest $(git rev-parse HEAD^) = $(git rev-parse branch1) &&\n@@ -151,6 +156,7 @@ test_expect_success 'test --onto <branch>' '\n test_expect_success 'rebase on top of a non-conflicting commit' '\n \tgit checkout branch1 &&\n \tgit tag original-branch1 &&\n+\tset_fake_editor &&\n \tgit rebase -i branch2 &&\n \ttest file6 = $(git diff --name-only original-branch1) &&\n \ttest \"$(git symbolic-ref -q HEAD)\" = \"refs/heads/branch1\" &&\n@@ -163,6 +169,7 @@ test_expect_success 'reflog for the branch shows state before rebase' '\n '\n \n test_expect_success 'exchange two commits' '\n+\tset_fake_editor &&\n \tFAKE_LINES=\"2 1\" git rebase -i HEAD~2 &&\n \ttest H = $(git cat-file commit HEAD^ | sed -ne \\$p) &&\n \ttest G = $(git cat-file commit HEAD | sed -ne \\$p)\n@@ -188,6 +195,7 @@ EOF\n \n test_expect_success 'stop on conflicting pick' '\n \tgit tag new-branch1 &&\n+\tset_fake_editor &&\n \ttest_must_fail git rebase -i master &&\n \ttest \"$(git rev-parse HEAD~3)\" = \"$(git rev-parse master)\" &&\n \ttest_cmp expect .git/rebase-merge/patch &&\n@@ -208,6 +216,7 @@ test_expect_success 'abort' '\n test_expect_success 'abort with error when new base cannot be checked out' '\n \tgit rm --cached file1 &&\n \tgit commit -m \"remove file in base\" &&\n+\tset_fake_editor &&\n \ttest_must_fail git rebase -i master > output 2>&1 &&\n \tgrep \"The following untracked working tree files would be overwritten by checkout:\" \\\n \t\toutput &&\n@@ -222,6 +231,7 @@ test_expect_success 'retain authorship' '\n \ttest_tick &&\n \tGIT_AUTHOR_NAME=\"Twerp Snog\" git commit -m \"different author\" &&\n \tgit tag twerp &&\n+\tset_fake_editor &&\n \tgit rebase -i --onto master HEAD^ &&\n \tgit show HEAD | grep \"^Author: Twerp Snog\"\n '\n@@ -232,6 +242,7 @@ test_expect_success 'squash' '\n \ttest_tick &&\n \tGIT_AUTHOR_NAME=\"Nitfol\" git commit -m \"nitfol\" file7 &&\n \techo \"******************************\" &&\n+\tset_fake_editor &&\n \tFAKE_LINES=\"1 squash 2\" EXPECT_HEADER_COUNT=2 \\\n \t\tgit rebase -i --onto master HEAD~2 &&\n \ttest B = $(cat file7) &&\n@@ -244,6 +255,7 @@ test_expect_success 'retain authorship when squashing' '\n \n test_expect_success '-p handles \"no changes\" gracefully' '\n \tHEAD=$(git rev-parse HEAD) &&\n+\tset_fake_editor &&\n \tgit rebase -i -p HEAD^ &&\n \tgit update-index --refresh &&\n \tgit diff-files --quiet &&\n@@ -253,6 +265,7 @@ test_expect_success '-p handles \"no changes\" gracefully' '\n \n test_expect_failure 'exchange two commits with -p' '\n \tgit checkout H &&\n+\tset_fake_editor &&\n \tFAKE_LINES=\"2 1\" git rebase -i -p HEAD~2 &&\n \ttest H = $(git cat-file commit HEAD^ | sed -ne \\$p) &&\n \ttest G = $(git cat-file commit HEAD | sed -ne \\$p)\n@@ -287,6 +300,7 @@ test_expect_success 'preserve merges with -p' '\n \tgit commit -m M file1 &&\n \tgit checkout -b to-be-rebased &&\n \ttest_tick &&\n+\tset_fake_editor &&\n \tgit rebase -i -p --onto branch1 master &&\n \tgit update-index --refresh &&\n \tgit diff-files --quiet &&\n@@ -301,6 +315,7 @@ test_expect_success 'preserve merges with -p' '\n '\n \n test_expect_success 'edit ancestor with -p' '\n+\tset_fake_editor &&\n \tFAKE_LINES=\"1 2 edit 3 4\" git rebase -i -p HEAD~3 &&\n \techo 2 > unrelated-file &&\n \ttest_tick &&\n@@ -314,6 +329,7 @@ test_expect_success 'edit ancestor with -p' '\n \n test_expect_success '--continue tries to commit' '\n \ttest_tick &&\n+\tset_fake_editor &&\n \ttest_must_fail git rebase -i --onto new-branch1 HEAD^ &&\n \techo resolved > file1 &&\n \tgit add file1 &&\n@@ -325,6 +341,7 @@ test_expect_success '--continue tries to commit' '\n test_expect_success 'verbose flag is heeded, even after --continue' '\n \tgit reset --hard master@{1} &&\n \ttest_tick &&\n+\tset_fake_editor &&\n \ttest_must_fail git rebase -v -i --onto new-branch1 HEAD^ &&\n \techo resolved > file1 &&\n \tgit add file1 &&\n@@ -334,6 +351,7 @@ test_expect_success 'verbose flag is heeded, even after --continue' '\n \n test_expect_success 'multi-squash only fires up editor once' '\n \tbase=$(git rev-parse HEAD~4) &&\n+\tset_fake_editor &&\n \tFAKE_COMMIT_AMEND=\"ONCE\" FAKE_LINES=\"1 squash 2 squash 3 squash 4\" \\\n \t\tEXPECT_HEADER_COUNT=4 \\\n \t\tgit rebase -i $base &&\n@@ -344,6 +362,7 @@ test_expect_success 'multi-squash only fires up editor once' '\n test_expect_success 'multi-fixup does not fire up editor' '\n \tgit checkout -b multi-fixup E &&\n \tbase=$(git rev-parse HEAD~4) &&\n+\tset_fake_editor &&\n \tFAKE_COMMIT_AMEND=\"NEVER\" FAKE_LINES=\"1 fixup 2 fixup 3 fixup 4\" \\\n \t\tgit rebase -i $base &&\n \ttest $base = $(git rev-parse HEAD^) &&\n@@ -355,6 +374,7 @@ test_expect_success 'multi-fixup does not fire up editor' '\n test_expect_success 'commit message used after conflict' '\n \tgit checkout -b conflict-fixup conflict-branch &&\n \tbase=$(git rev-parse HEAD~4) &&\n+\tset_fake_editor &&\n \t(\n \t\tFAKE_LINES=\"1 fixup 3 fixup 4\" &&\n \t\texport FAKE_LINES &&\n@@ -373,6 +393,7 @@ test_expect_success 'commit message used after conflict' '\n test_expect_success 'commit message retained after conflict' '\n \tgit checkout -b conflict-squash conflict-branch &&\n \tbase=$(git rev-parse HEAD~4) &&\n+\tset_fake_editor &&\n \t(\n \t\tFAKE_LINES=\"1 fixup 3 squash 4\" &&\n \t\texport FAKE_LINES &&\n@@ -399,6 +420,7 @@ EOF\n test_expect_success 'squash and fixup generate correct log messages' '\n \tgit checkout -b squash-fixup E &&\n \tbase=$(git rev-parse HEAD~4) &&\n+\tset_fake_editor &&\n \tFAKE_COMMIT_AMEND=\"ONCE\" FAKE_LINES=\"1 fixup 2 squash 3 fixup 4\" \\\n \t\tEXPECT_HEADER_COUNT=4 \\\n \t\tgit rebase -i $base &&\n@@ -411,6 +433,7 @@ test_expect_success 'squash and fixup generate correct log messages' '\n test_expect_success 'squash ignores comments' '\n \tgit checkout -b skip-comments E &&\n \tbase=$(git rev-parse HEAD~4) &&\n+\tset_fake_editor &&\n \tFAKE_COMMIT_AMEND=\"ONCE\" FAKE_LINES=\"# 1 # squash 2 # squash 3 # squash 4 #\" \\\n \t\tEXPECT_HEADER_COUNT=4 \\\n \t\tgit rebase -i $base &&\n@@ -423,6 +446,7 @@ test_expect_success 'squash ignores comments' '\n test_expect_success 'squash ignores blank lines' '\n \tgit checkout -b skip-blank-lines E &&\n \tbase=$(git rev-parse HEAD~4) &&\n+\tset_fake_editor &&\n \tFAKE_COMMIT_AMEND=\"ONCE\" FAKE_LINES=\"> 1 > squash 2 > squash 3 > squash 4 >\" \\\n \t\tEXPECT_HEADER_COUNT=4 \\\n \t\tgit rebase -i $base &&\n@@ -435,6 +459,7 @@ test_expect_success 'squash ignores blank lines' '\n test_expect_success 'squash works as expected' '\n \tgit checkout -b squash-works no-conflict-branch &&\n \tone=$(git rev-parse HEAD~3) &&\n+\tset_fake_editor &&\n \tFAKE_LINES=\"1 squash 3 2\" EXPECT_HEADER_COUNT=2 \\\n \t\tgit rebase -i HEAD~3 &&\n \ttest $one = $(git rev-parse HEAD~2)\n@@ -443,6 +468,7 @@ test_expect_success 'squash works as expected' '\n test_expect_success 'interrupted squash works as expected' '\n \tgit checkout -b interrupted-squash conflict-branch &&\n \tone=$(git rev-parse HEAD~3) &&\n+\tset_fake_editor &&\n \t(\n \t\tFAKE_LINES=\"1 squash 3 2\" &&\n \t\texport FAKE_LINES &&\n@@ -460,6 +486,7 @@ test_expect_success 'interrupted squash works as expected' '\n test_expect_success 'interrupted squash works as expected (case 2)' '\n \tgit checkout -b interrupted-squash2 conflict-branch &&\n \tone=$(git rev-parse HEAD~3) &&\n+\tset_fake_editor &&\n \t(\n \t\tFAKE_LINES=\"3 squash 1 2\" &&\n \t\texport FAKE_LINES &&\n@@ -484,6 +511,7 @@ test_expect_success '--continue tries to commit, even for \"edit\"' '\n \tgit commit -m \"unrelated change\" &&\n \tparent=$(git rev-parse HEAD^) &&\n \ttest_tick &&\n+\tset_fake_editor &&\n \tFAKE_LINES=\"edit 1\" git rebase -i HEAD^ &&\n \techo edited > file7 &&\n \tgit add file7 &&\n@@ -496,6 +524,7 @@ test_expect_success '--continue tries to commit, even for \"edit\"' '\n test_expect_success 'aborted --continue does not squash commits after \"edit\"' '\n \told=$(git rev-parse HEAD) &&\n \ttest_tick &&\n+\tset_fake_editor &&\n \tFAKE_LINES=\"edit 1\" git rebase -i HEAD^ &&\n \techo \"edited again\" > file7 &&\n \tgit add file7 &&\n@@ -510,6 +539,7 @@ test_expect_success 'aborted --continue does not squash commits after \"edit\"' '\n \n test_expect_success 'auto-amend only edited commits after \"edit\"' '\n \ttest_tick &&\n+\tset_fake_editor &&\n \tFAKE_LINES=\"edit 1\" git rebase -i HEAD^ &&\n \techo \"edited again\" > file7 &&\n \tgit add file7 &&\n@@ -528,6 +558,7 @@ test_expect_success 'auto-amend only edited commits after \"edit\"' '\n test_expect_success 'clean error after failed \"exec\"' '\n \ttest_tick &&\n \ttest_when_finished \"git rebase --abort || :\" &&\n+\tset_fake_editor &&\n \t(\n \t\tFAKE_LINES=\"1 exec_false\" &&\n \t\texport FAKE_LINES &&\n@@ -543,6 +574,7 @@ test_expect_success 'rebase a detached HEAD' '\n \tgrandparent=$(git rev-parse HEAD~2) &&\n \tgit checkout $(git rev-parse HEAD) &&\n \ttest_tick &&\n+\tset_fake_editor &&\n \tFAKE_LINES=\"2 1\" git rebase -i HEAD~2 &&\n \ttest $grandparent = $(git rev-parse HEAD~2)\n '\n@@ -559,6 +591,7 @@ test_expect_success 'rebase a commit violating pre-commit' '\n \ttest_must_fail git commit -m doesnt-verify file1 &&\n \tgit commit -m doesnt-verify --no-verify file1 &&\n \ttest_tick &&\n+\tset_fake_editor &&\n \tFAKE_LINES=2 git rebase -i HEAD~2\n \n '\n@@ -580,6 +613,7 @@ test_expect_success 'rebase with a file named HEAD in worktree' '\n \t\tgit commit -m \"Add body\"\n \t) &&\n \n+\tset_fake_editor &&\n \tFAKE_LINES=\"1 squash 2\" git rebase -i to-be-rebased &&\n \ttest \"$(git show -s --pretty=format:%an)\" = \"Squashed Away\"\n \n@@ -591,6 +625,7 @@ test_expect_success 'do \"noop\" when there is nothing to cherry-pick' '\n \tGIT_EDITOR=: git commit --amend \\\n \t\t--author=\"Somebody else <somebody@else.com>\" &&\n \ttest $(git rev-parse branch3) != $(git rev-parse branch4) &&\n+\tset_fake_editor &&\n \tgit rebase -i branch3 &&\n \ttest $(git rev-parse branch3) = $(git rev-parse branch4)\n \n@@ -615,10 +650,12 @@ test_expect_success 'submodule rebase setup' '\n \t\tgit commit -a -m \"submodule second\"\n \t) &&\n \ttest_tick &&\n+\tset_fake_editor &&\n \tgit commit -a -m \"Three changes submodule\"\n '\n \n test_expect_success 'submodule rebase -i' '\n+\tset_fake_editor &&\n \tFAKE_LINES=\"1 squash 2 3\" git rebase -i A\n '\n \n@@ -636,6 +673,7 @@ test_expect_success 'submodule conflict setup' '\n '\n \n test_expect_success 'rebase -i continue with only submodule staged' '\n+\tset_fake_editor &&\n \ttest_must_fail git rebase -i submodule-base &&\n \tgit add sub &&\n \tgit rebase --continue &&\n@@ -645,6 +683,7 @@ test_expect_success 'rebase -i continue with only submodule staged' '\n test_expect_success 'rebase -i continue with unstaged submodule' '\n \tgit checkout submodule-topic &&\n \tgit reset --hard &&\n+\tset_fake_editor &&\n \ttest_must_fail git rebase -i submodule-base &&\n \tgit reset &&\n \tgit rebase --continue &&\n@@ -657,6 +696,7 @@ test_expect_success 'avoid unnecessary reset' '\n \ttest-chmtime =123456789 file3 &&\n \tgit update-index --refresh &&\n \tHEAD=$(git rev-parse HEAD) &&\n+\tset_fake_editor &&\n \tgit rebase -i HEAD~4 &&\n \ttest $HEAD = $(git rev-parse HEAD) &&\n \tMTIME=$(test-chmtime -v +0 file3 | sed 's/[^0-9].*$//') &&\n@@ -665,6 +705,7 @@ test_expect_success 'avoid unnecessary reset' '\n \n test_expect_success 'reword' '\n \tgit checkout -b reword-branch master &&\n+\tset_fake_editor &&\n \tFAKE_LINES=\"1 2 3 reword 4\" FAKE_COMMIT_MESSAGE=\"E changed\" git rebase -i A &&\n \tgit show HEAD | grep \"E changed\" &&\n \ttest $(git rev-parse master) != $(git rev-parse HEAD) &&\n@@ -684,6 +725,7 @@ test_expect_success 'rebase -i can copy notes' '\n \ttest_commit n2 &&\n \ttest_commit n3 &&\n \tgit notes add -m\"a note\" n3 &&\n+\tset_fake_editor &&\n \tgit rebase -i --onto n1 n2 &&\n \ttest \"a note\" = \"$(git notes show HEAD)\"\n '\n@@ -697,6 +739,7 @@ EOF\n test_expect_success 'rebase -i can copy notes over a fixup' '\n \tgit reset --hard n3 &&\n \tgit notes add -m\"an earlier note\" n2 &&\n+\tset_fake_editor &&\n \tGIT_NOTES_REWRITE_MODE=concatenate FAKE_LINES=\"1 fixup 2\" git rebase -i n1 &&\n \tgit notes show > output &&\n \ttest_cmp expect output\n@@ -706,6 +749,7 @@ test_expect_success 'rebase while detaching HEAD' '\n \tgit symbolic-ref HEAD &&\n \tgrandparent=$(git rev-parse HEAD~2) &&\n \ttest_tick &&\n+\tset_fake_editor &&\n \tFAKE_LINES=\"2 1\" git rebase -i HEAD~2 HEAD^0 &&\n \ttest $grandparent = $(git rev-parse HEAD~2) &&\n \ttest_must_fail git symbolic-ref HEAD\n@@ -715,6 +759,7 @@ test_tick # Ensure that the rebased commits get a different timestamp.\n test_expect_success 'always cherry-pick with --no-ff' '\n \tgit checkout no-ff-branch &&\n \tgit tag original-no-ff-branch &&\n+\tset_fake_editor &&\n \tgit rebase -i --no-ff A &&\n \ttouch empty &&\n \tfor p in 0 1 2\n@@ -747,6 +792,7 @@ test_expect_success 'set up commits with funny messages' '\n test_expect_success 'rebase-i history with funny messages' '\n \tgit rev-list A..funny >expect &&\n \ttest_tick &&\n+\tset_fake_editor &&\n \tFAKE_LINES=\"1 2 3 4\" git rebase -i A &&\n \tgit rev-list A.. >actual &&\n \ttest_cmp expect actual\n@@ -763,6 +809,7 @@ test_expect_success 'prepare for rebase -i --exec' '\n \n \n test_expect_success 'running \"git rebase -i --exec git show HEAD\"' '\n+\tset_fake_editor &&\n \tgit rebase -i --exec \"git show HEAD\" HEAD~2 >actual &&\n \t(\n \t\tFAKE_LINES=\"1 exec_git_show_HEAD 2 exec_git_show_HEAD\" &&\n@@ -776,6 +823,7 @@ test_expect_success 'running \"git rebase -i --exec git show HEAD\"' '\n \n test_expect_success 'running \"git rebase --exec git show HEAD -i\"' '\n \tgit reset --hard execute &&\n+\tset_fake_editor &&\n \tgit rebase --exec \"git show HEAD\" -i HEAD~2 >actual &&\n \t(\n \t\tFAKE_LINES=\"1 exec_git_show_HEAD 2 exec_git_show_HEAD\" &&\n@@ -789,6 +837,7 @@ test_expect_success 'running \"git rebase --exec git show HEAD -i\"' '\n \n test_expect_success 'running \"git rebase -ix git show HEAD\"' '\n \tgit reset --hard execute &&\n+\tset_fake_editor &&\n \tgit rebase -ix \"git show HEAD\" HEAD~2 >actual &&\n \t(\n \t\tFAKE_LINES=\"1 exec_git_show_HEAD 2 exec_git_show_HEAD\" &&\n@@ -802,6 +851,7 @@ test_expect_success 'running \"git rebase -ix git show HEAD\"' '\n \n test_expect_success 'rebase -ix with several <CMD>' '\n \tgit reset --hard execute &&\n+\tset_fake_editor &&\n \tgit rebase -ix \"git show HEAD; pwd\" HEAD~2 >actual &&\n \t(\n \t\tFAKE_LINES=\"1 exec_git_show_HEAD;_pwd 2 exec_git_show_HEAD;_pwd\" &&\n@@ -815,6 +865,7 @@ test_expect_success 'rebase -ix with several <CMD>' '\n \n test_expect_success 'rebase -ix with several instances of --exec' '\n \tgit reset --hard execute &&\n+\tset_fake_editor &&\n \tgit rebase -i --exec \"git show HEAD\" --exec \"pwd\" HEAD~2 >actual &&\n \t(\n \t\tFAKE_LINES=\"1 exec_git_show_HEAD exec_pwd 2\n@@ -836,6 +887,7 @@ test_expect_success 'rebase -ix with --autosquash' '\n \techo bis >bis.txt &&\n \tgit add bis.txt &&\n \tgit commit -m \"fixup! two_exec\" &&\n+\tset_fake_editor &&\n \t(\n \t\tgit checkout -b autosquash_actual &&\n \t\tgit rebase -i --exec \"git show HEAD\" --autosquash HEAD~4 >actual\n@@ -854,6 +906,7 @@ test_expect_success 'rebase -ix with --autosquash' '\n \n test_expect_success 'rebase --exec without -i shows error message' '\n \tgit reset --hard execute &&\n+\tset_fake_editor &&\n \ttest_must_fail git rebase --exec \"git show HEAD\" HEAD~2 2>actual &&\n \techo \"The --exec option must be used with the --interactive option\" >expected &&\n \ttest_i18ncmp expected actual\n@@ -862,6 +915,7 @@ test_expect_success 'rebase --exec without -i shows error message' '\n \n test_expect_success 'rebase -i --exec without <CMD>' '\n \tgit reset --hard execute &&\n+\tset_fake_editor &&\n \ttest_must_fail git rebase -i --exec 2>tmp &&\n \tsed -e \"1d\" tmp >actual &&\n \ttest_must_fail git rebase -h >expected &&\n@@ -871,6 +925,7 @@ test_expect_success 'rebase -i --exec without <CMD>' '\n \n test_expect_success 'rebase -i --root re-order and drop commits' '\n \tgit checkout E &&\n+\tset_fake_editor &&\n \tFAKE_LINES=\"3 1 2 5\" git rebase -i --root &&\n \ttest E = $(git cat-file commit HEAD | sed -ne \\$p) &&\n \ttest B = $(git cat-file commit HEAD^ | sed -ne \\$p) &&\n@@ -884,6 +939,7 @@ test_expect_success 'rebase -i --root retain root commit author and message' '\n \techo B >file7 &&\n \tgit add file7 &&\n \tGIT_AUTHOR_NAME=\"Twerp Snog\" git commit -m \"different author\" &&\n+\tset_fake_editor &&\n \tFAKE_LINES=\"2\" git rebase -i --root &&\n \tgit cat-file commit HEAD | grep -q \"^author Twerp Snog\" &&\n \tgit cat-file commit HEAD | grep -q \"^different author$\"\n@@ -892,6 +948,7 @@ test_expect_success 'rebase -i --root retain root commit author and message' '\n test_expect_success 'rebase -i --root temporary sentinel commit' '\n \tgit checkout B &&\n \t(\n+\t\tset_fake_editor &&\n \t\tFAKE_LINES=\"2\" &&\n \t\texport FAKE_LINES &&\n \t\ttest_must_fail git rebase -i --root\n@@ -902,6 +959,7 @@ test_expect_success 'rebase -i --root temporary sentinel commit' '\n \n test_expect_success 'rebase -i --root fixup root commit' '\n \tgit checkout B &&\n+\tset_fake_editor &&\n \tFAKE_LINES=\"1 fixup 2\" git rebase -i --root &&\n \ttest A = $(git cat-file commit HEAD | sed -ne \\$p) &&\n \ttest B = $(git show HEAD:file1) &&\n@@ -911,6 +969,7 @@ test_expect_success 'rebase -i --root fixup root commit' '\n test_expect_success 'rebase --edit-todo does not works on non-interactive rebase' '\n \tgit reset --hard &&\n \tgit checkout conflict-branch &&\n+\tset_fake_editor &&\n \ttest_must_fail git rebase --onto HEAD~2 HEAD~ &&\n \ttest_must_fail git rebase --edit-todo &&\n \tgit rebase --abort\n@@ -919,6 +978,7 @@ test_expect_success 'rebase --edit-todo does not works on non-interactive rebase\n test_expect_success 'rebase --edit-todo can be used to modify todo' '\n \tgit reset --hard &&\n \tgit checkout no-conflict-branch^0 &&\n+\tset_fake_editor &&\n \tFAKE_LINES=\"edit 1 2 3\" git rebase -i HEAD~3 &&\n \tFAKE_LINES=\"2 1\" git rebase --edit-todo &&\n \tgit rebase --continue\n@@ -929,6 +989,7 @@ test_expect_success 'rebase --edit-todo can be used to modify todo' '\n test_expect_success 'rebase -i produces readable reflog' '\n \tgit reset --hard &&\n \tgit branch -f branch-reflog-test H &&\n+\tset_fake_editor &&\n \tgit rebase -i --onto I F branch-reflog-test &&\n \tcat >expect <<-\\EOF &&\n \trebase -i (start): checkout I\n-- \n1.8.4.557.g34b3a2e\n"},{"id":"225763","messageId":"1377303042-50868-3-git-send-email-sunshine@sunshineco.com","threadId":"34755","inReplyTo":"1377303042-50868-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v2 2/3] t3404: rebase -i: demonstrate short SHA-1 collision","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2013-08-24T00:10:41Z","receivedAt":"2013-08-24T00:10:41Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"The 'todo' sheet for interactive rebase shows abbreviated SHA-1's and\nthen performs its operations upon those shortened values. This can lead\nto an abort if the SHA-1 of a reworded or edited commit is no longer\nunique within the abbreviated SHA-1 space and a subsequent SHA-1 in the\ntodo list has the same abbreviated value.\n\nFor example:\n\n  edit f00dfad first\n  pick badbeef second\n\nIf, after editing, the new SHA-1 of \"first\" also has prefix badbeef,\nthen the subsequent 'pick badbeef second' will fail since badbeef is no\nlonger a unique SHA-1 abbreviation:\n\n  error: short SHA1 badbeef is ambiguous.\n  fatal: Needed a single revision\n  Invalid commit name: badbeef\n\nDemonstrate this problem with a couple of specially crafted commits\nwhich initially have distinct abbreviated SHA-1's, but for which the\nabbreviated SHA-1's collide after a simple rewording of the first\ncommit's message.\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n t/t3404-rebase-interactive.sh | 24 ++++++++++++++++++++++++\n 1 file changed, 24 insertions(+)\n\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex f857161..64a02a0 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -1037,4 +1037,28 @@ test_expect_success 'rebase -i with --strategy and -X' '\n \ttest $(cat file1) = Z\n '\n \n+test_expect_success 'short SHA-1 setup' '\n+\ttest_when_finished \"git checkout master\" &&\n+\tgit checkout --orphan collide &&\n+\tgit rm -rf . &&\n+\t(\n+\tunset test_tick &&\n+\ttest_commit collide1 collide &&\n+\ttest_commit --notick collide2 collide &&\n+\ttest_commit --notick collide3 collide\n+\t)\n+'\n+\n+test_expect_failure 'short SHA-1 collide' '\n+\ttest_when_finished \"reset_rebase && git checkout master\" &&\n+\tgit checkout collide &&\n+\t(\n+\tunset test_tick &&\n+\ttest_tick &&\n+\tset_fake_editor &&\n+\tFAKE_COMMIT_MESSAGE=\"collide2 ac4f2ee\" \\\n+\tFAKE_LINES=\"reword 1 2\" git rebase -i HEAD~2\n+\t)\n+'\n+\n test_done\n-- \n1.8.4.557.g34b3a2e\n"},{"id":"225762","messageId":"1377303042-50868-4-git-send-email-sunshine@sunshineco.com","threadId":"34755","inReplyTo":"1377303042-50868-1-git-send-email-sunshine@sunshineco.com","subject":"[PATCH v2 3/3] rebase -i: fix short SHA-1 collision","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2013-08-24T00:10:42Z","receivedAt":"2013-08-24T00:10:42Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"From: Junio C Hamano <gitster@pobox.com>\n\nThe 'todo' sheet for interactive rebase shows abbreviated SHA-1's and\nthen performs its operations upon those shortened values. This can lead\nto an abort if the SHA-1 of a reworded or edited commit is no longer\nunique within the abbreviated SHA-1 space and a subsequent SHA-1 in the\ntodo list has the same abbreviated value.\n\nFor example:\n\n  edit f00dfad first\n  pick badbeef second\n\nIf, after editing, the new SHA-1 of \"first\" also has prefix badbeef,\nthen the subsequent 'pick badbeef second' will fail since badbeef is no\nlonger a unique SHA-1 abbreviation:\n\n  error: short SHA1 badbeef is ambiguous.\n  fatal: Needed a single revision\n  Invalid commit name: badbeef\n\nFix this problem by expanding the SHA-1's in the todo list before\nperforming the operations.\n\n[es: also collapse & expand SHA-1's for --edit-todo; respect\ncore.commentchar in transform_todo_ids(); compose commit message]\n\nSigned-off-by: Eric Sunshine <sunshine@sunshineco.com>\n---\n git-rebase--interactive.sh    | 30 ++++++++++++++++++++++++++++++\n t/t3404-rebase-interactive.sh |  2 +-\n 2 files changed, 31 insertions(+), 1 deletion(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 83d6d46..b97a1d0 100644\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -689,6 +689,32 @@ skip_unnecessary_picks () {\n \tdie \"Could not skip unnecessary pick commands\"\n }\n \n+transform_todo_ids () {\n+\twhile read -r command rest\n+\tdo\n+\t\tcase \"$command\" in\n+\t\t\"$comment_char\"* | exec)\n+\t\t\t# Be careful for oddball commands like 'exec'\n+\t\t\t# that do not have a SHA-1 at the beginning of $rest.\n+\t\t\t;;\n+\t\t*)\n+\t\t\tsha1=$(git rev-parse --verify --quiet \"$@\" ${rest%% *}) &&\n+\t\t\trest=\"$sha1 ${rest#* }\"\n+\t\t\t;;\n+\t\tesac\n+\t\tprintf '%s\\n' \"$command${rest:+ }$rest\"\n+\tdone <\"$todo\" >\"$todo.new\" &&\n+\tmv -f \"$todo.new\" \"$todo\"\n+}\n+\n+expand_todo_ids() {\n+\ttransform_todo_ids\n+}\n+\n+collapse_todo_ids() {\n+\ttransform_todo_ids --short=7\n+}\n+\n # Rearrange the todo list that has both \"pick sha1 msg\" and\n # \"pick sha1 fixup!/squash! msg\" appears in it so that the latter\n # comes immediately after the former, and change \"pick\" to\n@@ -841,6 +867,7 @@ skip)\n edit-todo)\n \tgit stripspace --strip-comments <\"$todo\" >\"$todo\".new\n \tmv -f \"$todo\".new \"$todo\"\n+\tcollapse_todo_ids\n \tappend_todo_help\n \tgit stripspace --comment-lines >>\"$todo\" <<\\EOF\n \n@@ -852,6 +879,7 @@ EOF\n \n \tgit_sequence_editor \"$todo\" ||\n \t\tdie \"Could not execute editor\"\n+\texpand_todo_ids\n \n \texit\n \t;;\n@@ -1008,6 +1036,8 @@ git_sequence_editor \"$todo\" ||\n has_action \"$todo\" ||\n \tdie_abort \"Nothing to do\"\n \n+expand_todo_ids\n+\n test -d \"$rewritten\" || test -n \"$force_rebase\" || skip_unnecessary_picks\n \n GIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION: checkout $onto_name\"\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex 64a02a0..6cdc2ea 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -1049,7 +1049,7 @@ test_expect_success 'short SHA-1 setup' '\n \t)\n '\n \n-test_expect_failure 'short SHA-1 collide' '\n+test_expect_success 'short SHA-1 collide' '\n \ttest_when_finished \"reset_rebase && git checkout master\" &&\n \tgit checkout collide &&\n \t(\n-- \n1.8.4.557.g34b3a2e\n"},{"id":"225837","messageId":"20130825061649.GS2882@elie.Belkin","threadId":"34755","inReplyTo":"1377303042-50868-3-git-send-email-sunshine@sunshineco.com","subject":"Re: [PATCH v2 2/3] t3404: rebase -i: demonstrate short SHA-1 collision","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2013-08-25T06:16:49Z","receivedAt":"2013-08-25T06:16:49Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Eric Sunshine wrote:\n\n> --- a/t/t3404-rebase-interactive.sh\n> +++ b/t/t3404-rebase-interactive.sh\n> @@ -1037,4 +1037,28 @@ test_expect_success 'rebase -i with --strategy and -X' '\n>  \ttest $(cat file1) = Z\n>  '\n>  \n> +test_expect_success 'short SHA-1 setup' '\n> +\ttest_when_finished \"git checkout master\" &&\n> +\tgit checkout --orphan collide &&\n> +\tgit rm -rf . &&\n> +\t(\n> +\tunset test_tick &&\n> +\ttest_commit collide1 collide &&\n> +\ttest_commit --notick collide2 collide &&\n> +\ttest_commit --notick collide3 collide\n> +\t)\n\nStyle: would be clearer indented:\n\n\t(\n\t\tunset test_tick &&\n\t\ttest_commit ...\n\t)\n\n> +test_expect_failure 'short SHA-1 collide' '\n> +\ttest_when_finished \"reset_rebase && git checkout master\" &&\n> +\tgit checkout collide &&\n> +\t(\n> +\tunset test_tick &&\n\nLikewise.\n\nThanks,\nJonathan\n"},{"id":"225887","messageId":"xmqqbo4kkjgl.fsf@gitster.dls.corp.google.com","threadId":"34755","inReplyTo":"1377303042-50868-1-git-send-email-sunshine@sunshineco.com","subject":"Re: [PATCH v2 0/3] fix interactive rebase short SHA-1 collision bug","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-08-26T07:19:22Z","receivedAt":"2013-08-26T07:19:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Sunshine <sunshine@sunshineco.com> writes:\n\n> ... when 'next' is ready to be rewound after 1.8.4\n> is released, a replacement to the original series should be sent with\n> all the incremental patches squashed in.\n\nIt was more like \"could, if you want to help us keep clean history\ngoing forward\", rather than \"should\" ;-) Thanks for resending.\n\nI've locally queued this series after seeing the end-result matches\nwhat has been cooking.\n\nTraditionally we waited for a few days after a release to see if we\ndo not receive regression reports that require us to issue brown\npaper bag fixes before rewinding \"next\" and opening a new cycle. I\nam hoping that it will happen in a few days.\n\nMy responses may be slower than usual today (i.e. Monday 26th), as I\nwould need to be sitting in dentist's for a few hours.\n"}]}