diff options
author | Junio C Hamano <gitster@pobox.com> | 2013-08-23 20:10:42 -0400 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2013-08-25 23:43:40 -0700 |
commit | 75c69766554c4b34ede65502d481dd7beb7f3388 (patch) | |
tree | d17b7485c2c73bd6d493b24986ccbacf0549055d | |
parent | t3404: rebase -i: demonstrate short SHA-1 collision (diff) | |
download | tgif-75c69766554c4b34ede65502d481dd7beb7f3388.tar.xz |
rebase -i: fix short SHA-1 collision
The 'todo' sheet for interactive rebase shows abbreviated SHA-1's and
then performs its operations upon those shortened values. This can lead
to an abort if the SHA-1 of a reworded or edited commit is no longer
unique within the abbreviated SHA-1 space and a subsequent SHA-1 in the
todo list has the same abbreviated value.
For example:
edit f00dfad first
pick badbeef second
If, after editing, the new SHA-1 of "first" also has prefix badbeef,
then the subsequent 'pick badbeef second' will fail since badbeef is no
longer a unique SHA-1 abbreviation:
error: short SHA1 badbeef is ambiguous.
fatal: Needed a single revision
Invalid commit name: badbeef
Fix this problem by expanding the SHA-1's in the todo list before
performing the operations.
[es: also collapse & expand SHA-1's for --edit-todo; respect
core.commentchar in transform_todo_ids(); compose commit message]
Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | git-rebase--interactive.sh | 30 | ||||
-rwxr-xr-x | t/t3404-rebase-interactive.sh | 2 |
2 files changed, 31 insertions, 1 deletions
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index 83d6d4676b..b97a1d07cb 100644 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -689,6 +689,32 @@ skip_unnecessary_picks () { die "Could not skip unnecessary pick commands" } +transform_todo_ids () { + while read -r command rest + do + case "$command" in + "$comment_char"* | exec) + # Be careful for oddball commands like 'exec' + # that do not have a SHA-1 at the beginning of $rest. + ;; + *) + sha1=$(git rev-parse --verify --quiet "$@" ${rest%% *}) && + rest="$sha1 ${rest#* }" + ;; + esac + printf '%s\n' "$command${rest:+ }$rest" + done <"$todo" >"$todo.new" && + mv -f "$todo.new" "$todo" +} + +expand_todo_ids() { + transform_todo_ids +} + +collapse_todo_ids() { + transform_todo_ids --short=7 +} + # Rearrange the todo list that has both "pick sha1 msg" and # "pick sha1 fixup!/squash! msg" appears in it so that the latter # comes immediately after the former, and change "pick" to @@ -841,6 +867,7 @@ skip) edit-todo) git stripspace --strip-comments <"$todo" >"$todo".new mv -f "$todo".new "$todo" + collapse_todo_ids append_todo_help git stripspace --comment-lines >>"$todo" <<\EOF @@ -852,6 +879,7 @@ EOF git_sequence_editor "$todo" || die "Could not execute editor" + expand_todo_ids exit ;; @@ -1008,6 +1036,8 @@ git_sequence_editor "$todo" || has_action "$todo" || die_abort "Nothing to do" +expand_todo_ids + test -d "$rewritten" || test -n "$force_rebase" || skip_unnecessary_picks GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name" diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 64a02a0073..6cdc2eadc7 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -1049,7 +1049,7 @@ test_expect_success 'short SHA-1 setup' ' ) ' -test_expect_failure 'short SHA-1 collide' ' +test_expect_success 'short SHA-1 collide' ' test_when_finished "reset_rebase && git checkout master" && git checkout collide && ( |