From: Junio C Hamano Date: Mon, 13 Jul 2015 21:00:25 +0000 (-0700) Subject: Merge branch 'js/rebase-i-clean-up-upon-continue-to-skip' X-Git-Tag: v2.5.0-rc2~8 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/e01787f1a1de589b7adc6f6946b53996a5e74c34?ds=inline;hp=-c Merge branch 'js/rebase-i-clean-up-upon-continue-to-skip' Abandoning an already applied change in "git rebase -i" with "--continue" left CHERRY_PICK_HEAD and confused later steps. * js/rebase-i-clean-up-upon-continue-to-skip: rebase -i: do not leave a CHERRY_PICK_HEAD file behind t3404: demonstrate CHERRY_PICK_HEAD bug --- e01787f1a1de589b7adc6f6946b53996a5e74c34 diff --combined git-rebase--interactive.sh index dc3133f681,3b361229b7..5ff0f1c81a --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@@ -132,16 -132,6 +132,16 @@@ mark_action_done () fi } +# Put the last action marked done at the beginning of the todo list +# again. If there has not been an action marked done yet, leave the list of +# items on the todo list unchanged. +reschedule_last_action () { + tail -n 1 "$done" | cat - "$todo" >"$todo".new + sed -e \$d <"$done" >"$done".new + mv -f "$todo".new "$todo" + mv -f "$done".new "$done" +} + append_todo_help () { git stripspace --comment-lines >>"$todo" <<\EOF @@@ -262,12 -252,6 +262,12 @@@ pick_one () output eval git cherry-pick \ ${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} \ "$strategy_args" $empty_args $ff "$@" + + # If cherry-pick dies it leaves the to-be-picked commit unrecorded. Reschedule + # previous task so this commit is not lost. + ret=$? + case "$ret" in [01]) ;; *) reschedule_last_action ;; esac + return $ret } pick_one_preserving_merges () { @@@ -502,7 -486,7 +502,7 @@@ do_pick () } do_next () { - rm -f "$msg" "$author_script" "$amend" || exit + rm -f "$msg" "$author_script" "$amend" "$state_dir"/stopped-sha || exit read -r command sha1 rest < "$todo" case "$command" in "$comment_char"*|''|noop) @@@ -592,6 -576,9 +592,6 @@@ read -r command rest < "$todo" mark_action_done printf 'Executing: %s\n' "$rest" - # "exec" command doesn't take a sha1 in the todo-list. - # => can't just use $sha1 here. - git rev-parse --verify HEAD > "$state_dir"/stopped-sha ${SHELL:-@SHELL_PATH@} -c "$rest" # Actual execution status=$? # Run in subshell because require_clean_work_tree can die. @@@ -655,9 -642,9 +655,9 @@@ git notes copy --for-rewrite=rebase < "$rewritten_list" || true # we don't care if this copying failed } && - if test -x "$GIT_DIR"/hooks/post-rewrite && - test -s "$rewritten_list"; then - "$GIT_DIR"/hooks/post-rewrite rebase < "$rewritten_list" + hook="$(git rev-parse --git-path hooks/post-rewrite)" + if test -x "$hook" && test -s "$rewritten_list"; then + "$hook" rebase < "$rewritten_list" true # we don't care if this hook failed fi && warn "Successfully rebased and updated $head_name." @@@ -849,7 -836,11 +849,11 @@@ continue # do we have anything to commit? if git diff-index --cached --quiet HEAD -- then - : Nothing to commit -- skip this + # Nothing to commit -- skip this commit + + test ! -f "$GIT_DIR"/CHERRY_PICK_HEAD || + rm "$GIT_DIR"/CHERRY_PICK_HEAD || + die "Could not remove CHERRY_PICK_HEAD" else if ! test -f "$author_script" then @@@ -887,10 -878,7 +891,10 @@@ first and then run 'git rebase --contin fi fi - record_in_rewritten "$(cat "$state_dir"/stopped-sha)" + if test -r "$state_dir"/stopped-sha + then + record_in_rewritten "$(cat "$state_dir"/stopped-sha)" + fi require_clean_work_tree "rebase" do_rest @@@ -977,13 -965,14 +981,13 @@@ els revisions=$onto...$orig_head shortrevisions=$shorthead fi -git rev-list $merges_option --pretty=oneline --abbrev-commit \ - --abbrev=7 --reverse --left-right --topo-order \ +git rev-list $merges_option --pretty=oneline --reverse --left-right --topo-order \ $revisions ${restrict_revision+^$restrict_revision} | \ sed -n "s/^>//p" | -while read -r shortsha1 rest +while read -r sha1 rest do - if test -z "$keep_empty" && is_empty_commit $shortsha1 && ! is_merge_commit $shortsha1 + if test -z "$keep_empty" && is_empty_commit $sha1 && ! is_merge_commit $sha1 then comment_out="$comment_char " else @@@ -992,8 -981,9 +996,8 @@@ if test t != "$preserve_merges" then - printf '%s\n' "${comment_out}pick $shortsha1 $rest" >>"$todo" + printf '%s\n' "${comment_out}pick $sha1 $rest" >>"$todo" else - sha1=$(git rev-parse $shortsha1) if test -z "$rebase_root" then preserve=t @@@ -1010,7 -1000,7 +1014,7 @@@ if test f = "$preserve" then touch "$rewritten"/$sha1 - printf '%s\n' "${comment_out}pick $shortsha1 $rest" >>"$todo" + printf '%s\n' "${comment_out}pick $sha1 $rest" >>"$todo" fi fi done @@@ -1034,8 -1024,8 +1038,8 @@@ the # just the history of its first-parent for others that will # be rebasing on top of it git rev-list --parents -1 $rev | cut -d' ' -s -f2 > "$dropped"/$rev - short=$(git rev-list -1 --abbrev-commit --abbrev=7 $rev) - sane_grep -v "^[a-z][a-z]* $short" <"$todo" > "${todo}2" ; mv "${todo}2" "$todo" + sha1=$(git rev-list -1 $rev) + sane_grep -v "^[a-z][a-z]* $sha1" <"$todo" > "${todo}2" ; mv "${todo}2" "$todo" rm "$rewritten"/$rev fi done @@@ -1045,12 -1035,9 +1049,12 @@@ test -s "$todo" || echo noop >> "$todo test -n "$autosquash" && rearrange_squash "$todo" test -n "$cmd" && add_exec_commands "$todo" +todocount=$(git stripspace --strip-comments <"$todo" | wc -l) +todocount=${todocount##* } + cat >>"$todo" <>"$todo" <<\EOF @@@ -1069,7 -1056,6 +1073,7 @@@ has_action "$todo" | return 2 cp "$todo" "$todo".backup +collapse_todo_ids git_sequence_editor "$todo" || die_abort "Could not execute editor" diff --combined t/t3404-rebase-interactive.sh index ac429a0bbb,914020176d..467e6c1ed5 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@@ -950,7 -950,7 +950,7 @@@ test_expect_success 'rebase --edit-tod set_fake_editor && FAKE_LINES="edit 1 2 3" git rebase -i HEAD~3 && FAKE_LINES="2 1" git rebase --edit-todo && - git rebase --continue + git rebase --continue && test M = $(git cat-file commit HEAD^ | sed -ne \$p) && test L = $(git cat-file commit HEAD | sed -ne \$p) ' @@@ -1007,7 -1007,7 +1007,7 @@@ test_expect_success 'rebase -i with --s ' test_expect_success 'rebase -i error on commits with \ in message' ' - current_head=$(git rev-parse HEAD) + current_head=$(git rev-parse HEAD) && test_when_finished "git rebase --abort; git reset --hard $current_head; rm -f error" && test_commit TO-REMOVE will-conflict old-content && test_commit "\temp" will-conflict new-content dummy && @@@ -1039,67 -1039,25 +1039,88 @@@ test_expect_success 'short SHA-1 collid ) ' +test_expect_success 'respect core.abbrev' ' + git config core.abbrev 12 && + set_cat_todo_editor && + test_must_fail git rebase -i HEAD~4 >todo-list && + test 4 = $(grep -c "pick [0-9a-f]\{12,\}" todo-list) +' + +test_expect_success 'todo count' ' + write_script dump-raw.sh <<-\EOF && + cat "$1" + EOF + test_set_editor "$(pwd)/dump-raw.sh" && + git rebase -i HEAD~4 >actual && + grep "^# Rebase ..* onto ..* ([0-9]" actual +' + +test_expect_success 'rebase -i commits that overwrite untracked files (pick)' ' + git checkout --force branch2 && + git clean -f && + set_fake_editor && + FAKE_LINES="edit 1 2" git rebase -i A && + test_cmp_rev HEAD F && + test_path_is_missing file6 && + >file6 && + test_must_fail git rebase --continue && + test_cmp_rev HEAD F && + rm file6 && + git rebase --continue && + test_cmp_rev HEAD I +' + +test_expect_success 'rebase -i commits that overwrite untracked files (squash)' ' + git checkout --force branch2 && + git clean -f && + git tag original-branch2 && + set_fake_editor && + FAKE_LINES="edit 1 squash 2" git rebase -i A && + test_cmp_rev HEAD F && + test_path_is_missing file6 && + >file6 && + test_must_fail git rebase --continue && + test_cmp_rev HEAD F && + rm file6 && + git rebase --continue && + test $(git cat-file commit HEAD | sed -ne \$p) = I && + git reset --hard original-branch2 +' + +test_expect_success 'rebase -i commits that overwrite untracked files (no ff)' ' + git checkout --force branch2 && + git clean -f && + set_fake_editor && + FAKE_LINES="edit 1 2" git rebase -i --no-ff A && + test $(git cat-file commit HEAD | sed -ne \$p) = F && + test_path_is_missing file6 && + >file6 && + test_must_fail git rebase --continue && + test $(git cat-file commit HEAD | sed -ne \$p) = F && + rm file6 && + git rebase --continue && + test $(git cat-file commit HEAD | sed -ne \$p) = I +' + + test_expect_success 'rebase --continue removes CHERRY_PICK_HEAD' ' + git checkout -b commit-to-skip && + for double in X 3 1 + do + test_seq 5 | sed "s/$double/&&/" >seq && + git add seq && + test_tick && + git commit -m seq-$double + done && + git tag seq-onto && + git reset --hard HEAD~2 && + git cherry-pick seq-onto && + set_fake_editor && + test_must_fail env FAKE_LINES= git rebase -i seq-onto && + test -d .git/rebase-merge && + git rebase --continue && + git diff --exit-code seq-onto && + test ! -d .git/rebase-merge && + test ! -f .git/CHERRY_PICK_HEAD + ' + test_done