Imported Upstream version 2.12.1
[platform/upstream/git.git] / t / t3404-rebase-interactive.sh
index 467e6c1..e2f18d1 100755 (executable)
@@ -60,9 +60,9 @@ test_expect_success 'setup' '
        test_commit P fileP
 '
 
-# "exec" commands are ran with the user shell by default, but this may
+# "exec" commands are run with the user shell by default, but this may
 # be non-POSIX. For example, if SHELL=zsh then ">file" doesn't work
-# to create a file. Unseting SHELL avoids such non-portable behavior
+# to create a file. Unsetting SHELL avoids such non-portable behavior
 # in tests. It must be exported for it to take effect where needed.
 SHELL=
 export SHELL
@@ -219,9 +219,9 @@ test_expect_success 'abort with error when new base cannot be checked out' '
        git commit -m "remove file in base" &&
        set_fake_editor &&
        test_must_fail git rebase -i master > output 2>&1 &&
-       grep "The following untracked working tree files would be overwritten by checkout:" \
+       test_i18ngrep "The following untracked working tree files would be overwritten by checkout:" \
                output &&
-       grep "file1" output &&
+       test_i18ngrep "file1" output &&
        test_path_is_missing .git/rebase-merge &&
        git reset --hard HEAD^
 '
@@ -237,6 +237,22 @@ test_expect_success 'retain authorship' '
        git show HEAD | grep "^Author: Twerp Snog"
 '
 
+test_expect_success 'retain authorship w/ conflicts' '
+       git reset --hard twerp &&
+       test_commit a conflict a conflict-a &&
+       git reset --hard twerp &&
+       GIT_AUTHOR_NAME=AttributeMe \
+       test_commit b conflict b conflict-b &&
+       set_fake_editor &&
+       test_must_fail git rebase -i conflict-a &&
+       echo resolved >conflict &&
+       git add conflict &&
+       git rebase --continue &&
+       test $(git rev-parse conflict-a^0) = $(git rev-parse HEAD^) &&
+       git show >out &&
+       grep AttributeMe out
+'
+
 test_expect_success 'squash' '
        git reset --hard twerp &&
        echo B > file7 &&
@@ -540,7 +556,7 @@ test_expect_success 'clean error after failed "exec"' '
        echo "edited again" > file7 &&
        git add file7 &&
        test_must_fail git rebase --continue 2>error &&
-       grep "You have staged changes in your working tree." error
+       test_i18ngrep "You have staged changes in your working tree." error
 '
 
 test_expect_success 'rebase a detached HEAD' '
@@ -555,10 +571,9 @@ test_expect_success 'rebase a detached HEAD' '
 test_expect_success 'rebase a commit violating pre-commit' '
 
        mkdir -p .git/hooks &&
-       PRE_COMMIT=.git/hooks/pre-commit &&
-       echo "#!/bin/sh" > $PRE_COMMIT &&
-       echo "test -z \"\$(git diff --cached --check)\"" >> $PRE_COMMIT &&
-       chmod a+x $PRE_COMMIT &&
+       write_script .git/hooks/pre-commit <<-\EOF &&
+       test -z "$(git diff --cached --check)"
+       EOF
        echo "monde! " >> file1 &&
        test_tick &&
        test_must_fail git commit -m doesnt-verify file1 &&
@@ -771,7 +786,6 @@ test_expect_success 'rebase-i history with funny messages' '
        test_cmp expect actual
 '
 
-
 test_expect_success 'prepare for rebase -i --exec' '
        git checkout master &&
        git checkout -b execute &&
@@ -780,7 +794,6 @@ test_expect_success 'prepare for rebase -i --exec' '
        test_commit three_exec main.txt three_exec
 '
 
-
 test_expect_success 'running "git rebase -i --exec git show HEAD"' '
        set_fake_editor &&
        git rebase -i --exec "git show HEAD" HEAD~2 >actual &&
@@ -793,7 +806,6 @@ test_expect_success 'running "git rebase -i --exec git show HEAD"' '
        test_cmp expected actual
 '
 
-
 test_expect_success 'running "git rebase --exec git show HEAD -i"' '
        git reset --hard execute &&
        set_fake_editor &&
@@ -807,7 +819,6 @@ test_expect_success 'running "git rebase --exec git show HEAD -i"' '
        test_cmp expected actual
 '
 
-
 test_expect_success 'running "git rebase -ix git show HEAD"' '
        git reset --hard execute &&
        set_fake_editor &&
@@ -835,7 +846,6 @@ test_expect_success 'rebase -ix with several <CMD>' '
        test_cmp expected actual
 '
 
-
 test_expect_success 'rebase -ix with several instances of --exec' '
        git reset --hard execute &&
        set_fake_editor &&
@@ -850,7 +860,6 @@ test_expect_success 'rebase -ix with several instances of --exec' '
        test_cmp expected actual
 '
 
-
 test_expect_success 'rebase -ix with --autosquash' '
        git reset --hard execute &&
        git checkout -b autosquash &&
@@ -876,16 +885,15 @@ test_expect_success 'rebase -ix with --autosquash' '
        test_cmp expected actual
 '
 
-
-test_expect_success 'rebase --exec without -i shows error message' '
+test_expect_success 'rebase --exec works without -i ' '
        git reset --hard execute &&
-       set_fake_editor &&
-       test_must_fail git rebase --exec "git show HEAD" HEAD~2 2>actual &&
-       echo "The --exec option must be used with the --interactive option" >expected &&
-       test_i18ncmp expected actual
+       rm -rf exec_output &&
+       EDITOR="echo >invoked_editor" git rebase --exec "echo a line >>exec_output"  HEAD~2 2>actual &&
+       test_i18ngrep  "Successfully rebased and updated" actual &&
+       test_line_count = 2 exec_output &&
+       test_path_is_missing invoked_editor
 '
 
-
 test_expect_success 'rebase -i --exec without <CMD>' '
        git reset --hard execute &&
        set_fake_editor &&
@@ -961,13 +969,13 @@ test_expect_success 'rebase -i produces readable reflog' '
        set_fake_editor &&
        git rebase -i --onto I F branch-reflog-test &&
        cat >expect <<-\EOF &&
-       rebase -i (start): checkout I
-       rebase -i (pick): G
-       rebase -i (pick): H
        rebase -i (finish): returning to refs/heads/branch-reflog-test
+       rebase -i (pick): H
+       rebase -i (pick): G
+       rebase -i (start): checkout I
        EOF
-       tail -n 4 .git/logs/HEAD |
-       sed -e "s/.*    //" >actual &&
+       git reflog -n4 HEAD |
+       sed "s/[^:]*: //" >actual &&
        test_cmp expect actual
 '
 
@@ -984,6 +992,17 @@ test_expect_success 'rebase -i respects core.commentchar' '
        test B = $(git cat-file commit HEAD^ | sed -ne \$p)
 '
 
+test_expect_success 'rebase -i respects core.commentchar=auto' '
+       test_config core.commentchar auto &&
+       write_script copy-edit-script.sh <<-\EOF &&
+       cp "$1" edit-script
+       EOF
+       test_set_editor "$(pwd)/copy-edit-script.sh" &&
+       test_when_finished "git rebase --abort || :" &&
+       git rebase -i HEAD^ &&
+       test -z "$(grep -ve "^#" -e "^\$" -e "^pick" edit-script)"
+'
+
 test_expect_success 'rebase -i, with <onto> and <upstream> specified as :/quuxery' '
        test_when_finished "git branch -D torebase" &&
        git checkout -b torebase branch1 &&
@@ -1006,6 +1025,22 @@ test_expect_success 'rebase -i with --strategy and -X' '
        test $(cat file1) = Z
 '
 
+test_expect_success 'interrupted rebase -i with --strategy and -X' '
+       git checkout -b conflict-merge-use-theirs-interrupted conflict-branch &&
+       git reset --hard HEAD^ &&
+       >breakpoint &&
+       git add breakpoint &&
+       git commit -m "breakpoint for interactive mode" &&
+       echo five >conflict &&
+       echo Z >file1 &&
+       git commit -a -m "one file conflict" &&
+       set_fake_editor &&
+       FAKE_LINES="edit 1 2" git rebase -i --strategy=recursive -Xours conflict-branch &&
+       git rebase --continue &&
+       test $(git show conflict-branch:conflict) = $(cat conflict) &&
+       test $(cat file1) = Z
+'
+
 test_expect_success 'rebase -i error on commits with \ in message' '
        current_head=$(git rev-parse HEAD) &&
        test_when_finished "git rebase --abort; git reset --hard $current_head; rm -f error" &&
@@ -1052,7 +1087,7 @@ test_expect_success 'todo count' '
        EOF
        test_set_editor "$(pwd)/dump-raw.sh" &&
        git rebase -i HEAD~4 >actual &&
-       grep "^# Rebase ..* onto ..* ([0-9]" actual
+       test_i18ngrep "^# Rebase ..* onto ..* ([0-9]" actual
 '
 
 test_expect_success 'rebase -i commits that overwrite untracked files (pick)' '
@@ -1123,4 +1158,162 @@ test_expect_success 'rebase --continue removes CHERRY_PICK_HEAD' '
        test ! -f .git/CHERRY_PICK_HEAD
 '
 
+rebase_setup_and_clean () {
+       test_when_finished "
+               git checkout master &&
+               test_might_fail git branch -D $1 &&
+               test_might_fail git rebase --abort
+       " &&
+       git checkout -b $1 master
+}
+
+test_expect_success 'drop' '
+       rebase_setup_and_clean drop-test &&
+       set_fake_editor &&
+       FAKE_LINES="1 drop 2 3 drop 4 5" git rebase -i --root &&
+       test E = $(git cat-file commit HEAD | sed -ne \$p) &&
+       test C = $(git cat-file commit HEAD^ | sed -ne \$p) &&
+       test A = $(git cat-file commit HEAD^^ | sed -ne \$p)
+'
+
+cat >expect <<EOF
+Successfully rebased and updated refs/heads/missing-commit.
+EOF
+
+test_expect_success 'rebase -i respects rebase.missingCommitsCheck = ignore' '
+       test_config rebase.missingCommitsCheck ignore &&
+       rebase_setup_and_clean missing-commit &&
+       set_fake_editor &&
+       FAKE_LINES="1 2 3 4" \
+               git rebase -i --root 2>actual &&
+       test D = $(git cat-file commit HEAD | sed -ne \$p) &&
+       test_i18ncmp expect actual
+'
+
+cat >expect <<EOF
+Warning: some commits may have been dropped accidentally.
+Dropped commits (newer to older):
+ - $(git rev-list --pretty=oneline --abbrev-commit -1 master)
+To avoid this message, use "drop" to explicitly remove a commit.
+
+Use 'git config rebase.missingCommitsCheck' to change the level of warnings.
+The possible behaviours are: ignore, warn, error.
+
+Successfully rebased and updated refs/heads/missing-commit.
+EOF
+
+test_expect_success 'rebase -i respects rebase.missingCommitsCheck = warn' '
+       test_config rebase.missingCommitsCheck warn &&
+       rebase_setup_and_clean missing-commit &&
+       set_fake_editor &&
+       FAKE_LINES="1 2 3 4" \
+               git rebase -i --root 2>actual &&
+       test_i18ncmp expect actual &&
+       test D = $(git cat-file commit HEAD | sed -ne \$p)
+'
+
+cat >expect <<EOF
+Warning: some commits may have been dropped accidentally.
+Dropped commits (newer to older):
+ - $(git rev-list --pretty=oneline --abbrev-commit -1 master)
+ - $(git rev-list --pretty=oneline --abbrev-commit -1 master~2)
+To avoid this message, use "drop" to explicitly remove a commit.
+
+Use 'git config rebase.missingCommitsCheck' to change the level of warnings.
+The possible behaviours are: ignore, warn, error.
+
+You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'.
+Or you can abort the rebase with 'git rebase --abort'.
+EOF
+
+test_expect_success 'rebase -i respects rebase.missingCommitsCheck = error' '
+       test_config rebase.missingCommitsCheck error &&
+       rebase_setup_and_clean missing-commit &&
+       set_fake_editor &&
+       test_must_fail env FAKE_LINES="1 2 4" \
+               git rebase -i --root 2>actual &&
+       test_i18ncmp expect actual &&
+       cp .git/rebase-merge/git-rebase-todo.backup \
+               .git/rebase-merge/git-rebase-todo &&
+       FAKE_LINES="1 2 drop 3 4 drop 5" \
+               git rebase --edit-todo &&
+       git rebase --continue &&
+       test D = $(git cat-file commit HEAD | sed -ne \$p) &&
+       test B = $(git cat-file commit HEAD^ | sed -ne \$p)
+'
+
+cat >expect <<EOF
+Warning: the command isn't recognized in the following line:
+ - badcmd $(git rev-list --oneline -1 master~1)
+
+You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'.
+Or you can abort the rebase with 'git rebase --abort'.
+EOF
+
+test_expect_success 'static check of bad command' '
+       rebase_setup_and_clean bad-cmd &&
+       set_fake_editor &&
+       test_must_fail env FAKE_LINES="1 2 3 bad 4 5" \
+               git rebase -i --root 2>actual &&
+       test_i18ncmp expect actual &&
+       FAKE_LINES="1 2 3 drop 4 5" git rebase --edit-todo &&
+       git rebase --continue &&
+       test E = $(git cat-file commit HEAD | sed -ne \$p) &&
+       test C = $(git cat-file commit HEAD^ | sed -ne \$p)
+'
+
+test_expect_success 'tabs and spaces are accepted in the todolist' '
+       rebase_setup_and_clean indented-comment &&
+       write_script add-indent.sh <<-\EOF &&
+       (
+               # Turn single spaces into space/tab mix
+               sed "1s/ /      /g; 2s/ /  /g; 3s/ /    /g" "$1"
+               printf "\n\t# comment\n #more\n\t # comment\n"
+       ) >"$1.new"
+       mv "$1.new" "$1"
+       EOF
+       test_set_editor "$(pwd)/add-indent.sh" &&
+       git rebase -i HEAD^^^ &&
+       test E = $(git cat-file commit HEAD | sed -ne \$p)
+'
+
+cat >expect <<EOF
+Warning: the SHA-1 is missing or isn't a commit in the following line:
+ - edit XXXXXXX False commit
+
+You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'.
+Or you can abort the rebase with 'git rebase --abort'.
+EOF
+
+test_expect_success 'static check of bad SHA-1' '
+       rebase_setup_and_clean bad-sha &&
+       set_fake_editor &&
+       test_must_fail env FAKE_LINES="1 2 edit fakesha 3 4 5 #" \
+               git rebase -i --root 2>actual &&
+       test_i18ncmp expect actual &&
+       FAKE_LINES="1 2 4 5 6" git rebase --edit-todo &&
+       git rebase --continue &&
+       test E = $(git cat-file commit HEAD | sed -ne \$p)
+'
+
+test_expect_success 'editor saves as CR/LF' '
+       git checkout -b with-crlf &&
+       write_script add-crs.sh <<-\EOF &&
+       sed -e "s/\$/Q/" <"$1" | tr Q "\\015" >"$1".new &&
+       mv -f "$1".new "$1"
+       EOF
+       (
+               test_set_editor "$(pwd)/add-crs.sh" &&
+               git rebase -i HEAD^
+       )
+'
+
+SQ="'"
+test_expect_success 'rebase -i --gpg-sign=<key-id>' '
+       set_fake_editor &&
+       FAKE_LINES="edit 1" git rebase -i --gpg-sign="\"S I Gner\"" HEAD^ \
+               >out 2>err &&
+       test_i18ngrep "$SQ-S\"S I Gner\"$SQ" err
+'
+
 test_done