1#!/bin/sh 2# 3# Copyright (c) 2007 Johannes E. Schindelin 4# 5 6test_description='git rebase interactive 7 8This test runs git rebase "interactively", by faking an edit, and verifies 9that the result still makes sense. 10 11Initial setup: 12 13 one - two - three - four (conflict-branch) 14 / 15 A - B - C - D - E (primary) 16 | \ 17 | F - G - H (branch1) 18 | \ 19 |\ I (branch2) 20 | \ 21 | J - K - L - M (no-conflict-branch) 22 \ 23 N - O - P (no-ff-branch) 24 25 where A, B, D and G all touch file1, and one, two, three, four all 26 touch file "conflict". 27' 28GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master 29export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 30 31. ./test-lib.sh 32 33. "$TEST_DIRECTORY"/lib-rebase.sh 34 35test_expect_success 'setup' ' 36 git switch -C primary && 37 test_commit A file1 && 38 test_commit B file1 && 39 test_commit C file2 && 40 test_commit D file1 && 41 test_commit E file3 && 42 git checkout -b branch1 A && 43 test_commit F file4 && 44 test_commit G file1 && 45 test_commit H file5 && 46 git checkout -b branch2 F && 47 test_commit I file6 && 48 git checkout -b conflict-branch A && 49 test_commit one conflict && 50 test_commit two conflict && 51 test_commit three conflict && 52 test_commit four conflict && 53 git checkout -b no-conflict-branch A && 54 test_commit J fileJ && 55 test_commit K fileK && 56 test_commit L fileL && 57 test_commit M fileM && 58 git checkout -b no-ff-branch A && 59 test_commit N fileN && 60 test_commit O fileO && 61 test_commit P fileP 62' 63 64# "exec" commands are run with the user shell by default, but this may 65# be non-POSIX. For example, if SHELL=zsh then ">file" doesn't work 66# to create a file. Unsetting SHELL avoids such non-portable behavior 67# in tests. It must be exported for it to take effect where needed. 68SHELL= 69export SHELL 70 71test_expect_success 'rebase --keep-empty' ' 72 git checkout -b emptybranch primary && 73 git commit --allow-empty -m "empty" && 74 git rebase --keep-empty -i HEAD~2 && 75 git log --oneline >actual && 76 test_line_count = 6 actual 77' 78 79test_expect_success 'rebase -i with empty todo list' ' 80 cat >expect <<-\EOF && 81 error: nothing to do 82 EOF 83 ( 84 set_fake_editor && 85 test_must_fail env FAKE_LINES="#" \ 86 git rebase -i HEAD^ >output 2>&1 87 ) && 88 tail -n 1 output >actual && # Ignore output about changing todo list 89 test_cmp expect actual 90' 91 92test_expect_success 'rebase -i with the exec command' ' 93 git checkout primary && 94 ( 95 set_fake_editor && 96 FAKE_LINES="1 exec_>touch-one 97 2 exec_>touch-two exec_false exec_>touch-three 98 3 4 exec_>\"touch-file__name_with_spaces\";_>touch-after-semicolon 5" && 99 export FAKE_LINES && 100 test_must_fail git rebase -i A 101 ) && 102 test_path_is_file touch-one && 103 test_path_is_file touch-two && 104 # Missing because we should have stopped by now. 105 test_path_is_missing touch-three && 106 test_cmp_rev C HEAD && 107 git rebase --continue && 108 test_path_is_file touch-three && 109 test_path_is_file "touch-file name with spaces" && 110 test_path_is_file touch-after-semicolon && 111 test_cmp_rev primary HEAD && 112 rm -f touch-* 113' 114 115test_expect_success 'rebase -i with the exec command runs from tree root' ' 116 git checkout primary && 117 mkdir subdir && (cd subdir && 118 set_fake_editor && 119 FAKE_LINES="1 exec_>touch-subdir" \ 120 git rebase -i HEAD^ 121 ) && 122 test_path_is_file touch-subdir && 123 rm -fr subdir 124' 125 126test_expect_success 'rebase -i with exec allows git commands in subdirs' ' 127 test_when_finished "rm -rf subdir" && 128 test_when_finished "git rebase --abort ||:" && 129 git checkout primary && 130 mkdir subdir && (cd subdir && 131 set_fake_editor && 132 FAKE_LINES="1 x_cd_subdir_&&_git_rev-parse_--is-inside-work-tree" \ 133 git rebase -i HEAD^ 134 ) 135' 136 137test_expect_success 'rebase -i sets work tree properly' ' 138 test_when_finished "rm -rf subdir" && 139 test_when_finished "test_might_fail git rebase --abort" && 140 mkdir subdir && 141 git rebase -x "(cd subdir && git rev-parse --show-toplevel)" HEAD^ \ 142 >actual && 143 ! grep "/subdir$" actual 144' 145 146test_expect_success 'rebase -i with the exec command checks tree cleanness' ' 147 git checkout primary && 148 ( 149 set_fake_editor && 150 test_must_fail env FAKE_LINES="exec_echo_foo_>file1 1" \ 151 git rebase -i HEAD^ 152 ) && 153 test_cmp_rev primary^ HEAD && 154 git reset --hard && 155 git rebase --continue 156' 157 158test_expect_success 'rebase -x with empty command fails' ' 159 test_when_finished "git rebase --abort ||:" && 160 test_must_fail env git rebase -x "" @ 2>actual && 161 test_write_lines "error: empty exec command" >expected && 162 test_cmp expected actual && 163 test_must_fail env git rebase -x " " @ 2>actual && 164 test_cmp expected actual 165' 166 167test_expect_success 'rebase -x with newline in command fails' ' 168 test_when_finished "git rebase --abort ||:" && 169 test_must_fail env git rebase -x "a${LF}b" @ 2>actual && 170 test_write_lines "error: exec commands cannot contain newlines" \ 171 >expected && 172 test_cmp expected actual 173' 174 175test_expect_success 'rebase -i with exec of inexistent command' ' 176 git checkout primary && 177 test_when_finished "git rebase --abort" && 178 ( 179 set_fake_editor && 180 test_must_fail env FAKE_LINES="exec_this-command-does-not-exist 1" \ 181 git rebase -i HEAD^ >actual 2>&1 182 ) && 183 ! grep "Maybe git-rebase is broken" actual 184' 185 186test_expect_success 'implicit interactive rebase does not invoke sequence editor' ' 187 test_when_finished "git rebase --abort ||:" && 188 GIT_SEQUENCE_EDITOR="echo bad >" git rebase -x"echo one" @^ 189' 190 191test_expect_success 'no changes are a nop' ' 192 git checkout branch2 && 193 git rebase -i F && 194 test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" && 195 test_cmp_rev I HEAD 196' 197 198test_expect_success 'test the [branch] option' ' 199 git checkout -b dead-end && 200 git rm file6 && 201 git commit -m "stop here" && 202 git rebase -i F branch2 && 203 test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" && 204 test_cmp_rev I branch2 && 205 test_cmp_rev I HEAD 206' 207 208test_expect_success 'test --onto <branch>' ' 209 git checkout -b test-onto branch2 && 210 git rebase -i --onto branch1 F && 211 test "$(git symbolic-ref -q HEAD)" = "refs/heads/test-onto" && 212 test_cmp_rev HEAD^ branch1 && 213 test_cmp_rev I branch2 214' 215 216test_expect_success 'rebase on top of a non-conflicting commit' ' 217 git checkout branch1 && 218 git tag original-branch1 && 219 git rebase -i branch2 && 220 test file6 = $(git diff --name-only original-branch1) && 221 test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch1" && 222 test_cmp_rev I branch2 && 223 test_cmp_rev I HEAD~2 224' 225 226test_expect_success 'reflog for the branch shows state before rebase' ' 227 test_cmp_rev branch1@{1} original-branch1 228' 229 230test_expect_success 'reflog for the branch shows correct finish message' ' 231 printf "rebase (finish): refs/heads/branch1 onto %s\n" \ 232 "$(git rev-parse branch2)" >expected && 233 git log -g --pretty=%gs -1 refs/heads/branch1 >actual && 234 test_cmp expected actual 235' 236 237test_expect_success 'exchange two commits' ' 238 ( 239 set_fake_editor && 240 FAKE_LINES="2 1" git rebase -i HEAD~2 241 ) && 242 test H = $(git cat-file commit HEAD^ | sed -ne \$p) && 243 test G = $(git cat-file commit HEAD | sed -ne \$p) && 244 blob1=$(git rev-parse --short HEAD^:file1) && 245 blob2=$(git rev-parse --short HEAD:file1) && 246 commit=$(git rev-parse --short HEAD) 247' 248 249test_expect_success 'stop on conflicting pick' ' 250 cat >expect <<-EOF && 251 diff --git a/file1 b/file1 252 index $blob1..$blob2 100644 253 --- a/file1 254 +++ b/file1 255 @@ -1 +1 @@ 256 -A 257 +G 258 EOF 259 cat >expect2 <<-EOF && 260 <<<<<<< HEAD 261 D 262 ======= 263 G 264 >>>>>>> $commit (G) 265 EOF 266 git tag new-branch1 && 267 test_must_fail git rebase -i primary && 268 test "$(git rev-parse HEAD~3)" = "$(git rev-parse primary)" && 269 test_cmp expect .git/rebase-merge/patch && 270 test_cmp expect2 file1 && 271 test "$(git diff --name-status | 272 sed -n -e "/^U/s/^U[^a-z]*//p")" = file1 && 273 test 4 = $(grep -v "^#" < .git/rebase-merge/done | wc -l) && 274 test 0 = $(grep -c "^[^#]" < .git/rebase-merge/git-rebase-todo) 275' 276 277test_expect_success 'show conflicted patch' ' 278 GIT_TRACE=1 git rebase --show-current-patch >/dev/null 2>stderr && 279 grep "show.*REBASE_HEAD" stderr && 280 # the original stopped-sha1 is abbreviated 281 stopped_sha1="$(git rev-parse $(cat ".git/rebase-merge/stopped-sha"))" && 282 test "$(git rev-parse REBASE_HEAD)" = "$stopped_sha1" 283' 284 285test_expect_success 'abort' ' 286 git rebase --abort && 287 test_cmp_rev new-branch1 HEAD && 288 test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch1" && 289 test_path_is_missing .git/rebase-merge 290' 291 292test_expect_success 'abort with error when new base cannot be checked out' ' 293 git rm --cached file1 && 294 git commit -m "remove file in base" && 295 test_must_fail git rebase -i primary > output 2>&1 && 296 test_i18ngrep "The following untracked working tree files would be overwritten by checkout:" \ 297 output && 298 test_i18ngrep "file1" output && 299 test_path_is_missing .git/rebase-merge && 300 rm file1 && 301 git reset --hard HEAD^ 302' 303 304test_expect_success 'retain authorship' ' 305 echo A > file7 && 306 git add file7 && 307 test_tick && 308 GIT_AUTHOR_NAME="Twerp Snog" git commit -m "different author" && 309 git tag twerp && 310 git rebase -i --onto primary HEAD^ && 311 git show HEAD | grep "^Author: Twerp Snog" 312' 313 314test_expect_success 'retain authorship w/ conflicts' ' 315 oGIT_AUTHOR_NAME=$GIT_AUTHOR_NAME && 316 test_when_finished "GIT_AUTHOR_NAME=\$oGIT_AUTHOR_NAME" && 317 318 git reset --hard twerp && 319 test_commit a conflict a conflict-a && 320 git reset --hard twerp && 321 322 GIT_AUTHOR_NAME=AttributeMe && 323 export GIT_AUTHOR_NAME && 324 test_commit b conflict b conflict-b && 325 GIT_AUTHOR_NAME=$oGIT_AUTHOR_NAME && 326 327 test_must_fail git rebase -i conflict-a && 328 echo resolved >conflict && 329 git add conflict && 330 git rebase --continue && 331 test_cmp_rev conflict-a^0 HEAD^ && 332 git show >out && 333 grep AttributeMe out 334' 335 336test_expect_success 'squash' ' 337 git reset --hard twerp && 338 echo B > file7 && 339 test_tick && 340 GIT_AUTHOR_NAME="Nitfol" git commit -m "nitfol" file7 && 341 echo "******************************" && 342 ( 343 set_fake_editor && 344 FAKE_LINES="1 squash 2" EXPECT_HEADER_COUNT=2 \ 345 git rebase -i --onto primary HEAD~2 346 ) && 347 test B = $(cat file7) && 348 test_cmp_rev HEAD^ primary 349' 350 351test_expect_success 'retain authorship when squashing' ' 352 git show HEAD | grep "^Author: Twerp Snog" 353' 354 355test_expect_success '--continue tries to commit' ' 356 git reset --hard D && 357 test_tick && 358 ( 359 set_fake_editor && 360 test_must_fail git rebase -i --onto new-branch1 HEAD^ && 361 echo resolved > file1 && 362 git add file1 && 363 FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue 364 ) && 365 test_cmp_rev HEAD^ new-branch1 && 366 git show HEAD | grep chouette 367' 368 369test_expect_success 'verbose flag is heeded, even after --continue' ' 370 git reset --hard primary@{1} && 371 test_tick && 372 test_must_fail git rebase -v -i --onto new-branch1 HEAD^ && 373 echo resolved > file1 && 374 git add file1 && 375 git rebase --continue > output && 376 grep "^ file1 | 2 +-$" output 377' 378 379test_expect_success 'multi-squash only fires up editor once' ' 380 base=$(git rev-parse HEAD~4) && 381 ( 382 set_fake_editor && 383 FAKE_COMMIT_AMEND="ONCE" \ 384 FAKE_LINES="1 squash 2 squash 3 squash 4" \ 385 EXPECT_HEADER_COUNT=4 \ 386 git rebase -i $base 387 ) && 388 test $base = $(git rev-parse HEAD^) && 389 test 1 = $(git show | grep ONCE | wc -l) 390' 391 392test_expect_success 'multi-fixup does not fire up editor' ' 393 git checkout -b multi-fixup E && 394 base=$(git rev-parse HEAD~4) && 395 ( 396 set_fake_editor && 397 FAKE_COMMIT_AMEND="NEVER" \ 398 FAKE_LINES="1 fixup 2 fixup 3 fixup 4" \ 399 git rebase -i $base 400 ) && 401 test $base = $(git rev-parse HEAD^) && 402 test 0 = $(git show | grep NEVER | wc -l) && 403 git checkout @{-1} && 404 git branch -D multi-fixup 405' 406 407test_expect_success 'commit message used after conflict' ' 408 git checkout -b conflict-fixup conflict-branch && 409 base=$(git rev-parse HEAD~4) && 410 ( 411 set_fake_editor && 412 test_must_fail env FAKE_LINES="1 fixup 3 fixup 4" \ 413 git rebase -i $base && 414 echo three > conflict && 415 git add conflict && 416 FAKE_COMMIT_AMEND="ONCE" EXPECT_HEADER_COUNT=2 \ 417 git rebase --continue 418 ) && 419 test $base = $(git rev-parse HEAD^) && 420 test 1 = $(git show | grep ONCE | wc -l) && 421 git checkout @{-1} && 422 git branch -D conflict-fixup 423' 424 425test_expect_success 'commit message retained after conflict' ' 426 git checkout -b conflict-squash conflict-branch && 427 base=$(git rev-parse HEAD~4) && 428 ( 429 set_fake_editor && 430 test_must_fail env FAKE_LINES="1 fixup 3 squash 4" \ 431 git rebase -i $base && 432 echo three > conflict && 433 git add conflict && 434 FAKE_COMMIT_AMEND="TWICE" EXPECT_HEADER_COUNT=2 \ 435 git rebase --continue 436 ) && 437 test $base = $(git rev-parse HEAD^) && 438 test 2 = $(git show | grep TWICE | wc -l) && 439 git checkout @{-1} && 440 git branch -D conflict-squash 441' 442 443test_expect_success 'squash and fixup generate correct log messages' ' 444 cat >expect-squash-fixup <<-\EOF && 445 B 446 447 D 448 449 ONCE 450 EOF 451 git checkout -b squash-fixup E && 452 base=$(git rev-parse HEAD~4) && 453 ( 454 set_fake_editor && 455 FAKE_COMMIT_AMEND="ONCE" \ 456 FAKE_LINES="1 fixup 2 squash 3 fixup 4" \ 457 EXPECT_HEADER_COUNT=4 \ 458 git rebase -i $base 459 ) && 460 git cat-file commit HEAD | sed -e 1,/^\$/d > actual-squash-fixup && 461 test_cmp expect-squash-fixup actual-squash-fixup && 462 git cat-file commit HEAD@{2} | 463 grep "^# This is a combination of 3 commits\." && 464 git cat-file commit HEAD@{3} | 465 grep "^# This is a combination of 2 commits\." && 466 git checkout @{-1} && 467 git branch -D squash-fixup 468' 469 470test_expect_success 'squash ignores comments' ' 471 git checkout -b skip-comments E && 472 base=$(git rev-parse HEAD~4) && 473 ( 474 set_fake_editor && 475 FAKE_COMMIT_AMEND="ONCE" \ 476 FAKE_LINES="# 1 # squash 2 # squash 3 # squash 4 #" \ 477 EXPECT_HEADER_COUNT=4 \ 478 git rebase -i $base 479 ) && 480 test $base = $(git rev-parse HEAD^) && 481 test 1 = $(git show | grep ONCE | wc -l) && 482 git checkout @{-1} && 483 git branch -D skip-comments 484' 485 486test_expect_success 'squash ignores blank lines' ' 487 git checkout -b skip-blank-lines E && 488 base=$(git rev-parse HEAD~4) && 489 ( 490 set_fake_editor && 491 FAKE_COMMIT_AMEND="ONCE" \ 492 FAKE_LINES="> 1 > squash 2 > squash 3 > squash 4 >" \ 493 EXPECT_HEADER_COUNT=4 \ 494 git rebase -i $base 495 ) && 496 test $base = $(git rev-parse HEAD^) && 497 test 1 = $(git show | grep ONCE | wc -l) && 498 git checkout @{-1} && 499 git branch -D skip-blank-lines 500' 501 502test_expect_success 'squash works as expected' ' 503 git checkout -b squash-works no-conflict-branch && 504 one=$(git rev-parse HEAD~3) && 505 ( 506 set_fake_editor && 507 FAKE_LINES="1 s 3 2" EXPECT_HEADER_COUNT=2 git rebase -i HEAD~3 508 ) && 509 test $one = $(git rev-parse HEAD~2) 510' 511 512test_expect_success 'interrupted squash works as expected' ' 513 git checkout -b interrupted-squash conflict-branch && 514 one=$(git rev-parse HEAD~3) && 515 ( 516 set_fake_editor && 517 test_must_fail env FAKE_LINES="1 squash 3 2" \ 518 git rebase -i HEAD~3 519 ) && 520 test_write_lines one two four > conflict && 521 git add conflict && 522 test_must_fail git rebase --continue && 523 echo resolved > conflict && 524 git add conflict && 525 git rebase --continue && 526 test $one = $(git rev-parse HEAD~2) 527' 528 529test_expect_success 'interrupted squash works as expected (case 2)' ' 530 git checkout -b interrupted-squash2 conflict-branch && 531 one=$(git rev-parse HEAD~3) && 532 ( 533 set_fake_editor && 534 test_must_fail env FAKE_LINES="3 squash 1 2" \ 535 git rebase -i HEAD~3 536 ) && 537 test_write_lines one four > conflict && 538 git add conflict && 539 test_must_fail git rebase --continue && 540 test_write_lines one two four > conflict && 541 git add conflict && 542 test_must_fail git rebase --continue && 543 echo resolved > conflict && 544 git add conflict && 545 git rebase --continue && 546 test $one = $(git rev-parse HEAD~2) 547' 548 549test_expect_success '--continue tries to commit, even for "edit"' ' 550 echo unrelated > file7 && 551 git add file7 && 552 test_tick && 553 git commit -m "unrelated change" && 554 parent=$(git rev-parse HEAD^) && 555 test_tick && 556 ( 557 set_fake_editor && 558 FAKE_LINES="edit 1" git rebase -i HEAD^ && 559 echo edited > file7 && 560 git add file7 && 561 FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue 562 ) && 563 test edited = $(git show HEAD:file7) && 564 git show HEAD | grep chouette && 565 test $parent = $(git rev-parse HEAD^) 566' 567 568test_expect_success 'aborted --continue does not squash commits after "edit"' ' 569 old=$(git rev-parse HEAD) && 570 test_tick && 571 ( 572 set_fake_editor && 573 FAKE_LINES="edit 1" git rebase -i HEAD^ && 574 echo "edited again" > file7 && 575 git add file7 && 576 test_must_fail env FAKE_COMMIT_MESSAGE=" " git rebase --continue 577 ) && 578 test $old = $(git rev-parse HEAD) && 579 git rebase --abort 580' 581 582test_expect_success 'auto-amend only edited commits after "edit"' ' 583 test_tick && 584 ( 585 set_fake_editor && 586 FAKE_LINES="edit 1" git rebase -i HEAD^ && 587 echo "edited again" > file7 && 588 git add file7 && 589 FAKE_COMMIT_MESSAGE="edited file7 again" git commit && 590 echo "and again" > file7 && 591 git add file7 && 592 test_tick && 593 test_must_fail env FAKE_COMMIT_MESSAGE="and again" \ 594 git rebase --continue 595 ) && 596 git rebase --abort 597' 598 599test_expect_success 'clean error after failed "exec"' ' 600 test_tick && 601 test_when_finished "git rebase --abort || :" && 602 ( 603 set_fake_editor && 604 test_must_fail env FAKE_LINES="1 exec_false" git rebase -i HEAD^ 605 ) && 606 echo "edited again" > file7 && 607 git add file7 && 608 test_must_fail git rebase --continue 2>error && 609 test_i18ngrep "you have staged changes in your working tree" error 610' 611 612test_expect_success 'rebase a detached HEAD' ' 613 grandparent=$(git rev-parse HEAD~2) && 614 git checkout $(git rev-parse HEAD) && 615 test_tick && 616 ( 617 set_fake_editor && 618 FAKE_LINES="2 1" git rebase -i HEAD~2 619 ) && 620 test $grandparent = $(git rev-parse HEAD~2) 621' 622 623test_expect_success 'rebase a commit violating pre-commit' ' 624 625 mkdir -p .git/hooks && 626 write_script .git/hooks/pre-commit <<-\EOF && 627 test -z "$(git diff --cached --check)" 628 EOF 629 echo "monde! " >> file1 && 630 test_tick && 631 test_must_fail git commit -m doesnt-verify file1 && 632 git commit -m doesnt-verify --no-verify file1 && 633 test_tick && 634 ( 635 set_fake_editor && 636 FAKE_LINES=2 git rebase -i HEAD~2 637 ) 638' 639 640test_expect_success 'rebase with a file named HEAD in worktree' ' 641 642 rm -fr .git/hooks && 643 git reset --hard && 644 git checkout -b branch3 A && 645 646 ( 647 GIT_AUTHOR_NAME="Squashed Away" && 648 export GIT_AUTHOR_NAME && 649 >HEAD && 650 git add HEAD && 651 git commit -m "Add head" && 652 >BODY && 653 git add BODY && 654 git commit -m "Add body" 655 ) && 656 657 ( 658 set_fake_editor && 659 FAKE_LINES="1 squash 2" git rebase -i @{-1} 660 ) && 661 test "$(git show -s --pretty=format:%an)" = "Squashed Away" 662 663' 664 665test_expect_success 'do "noop" when there is nothing to cherry-pick' ' 666 667 git checkout -b branch4 HEAD && 668 GIT_EDITOR=: git commit --amend \ 669 --author="Somebody else <somebody@else.com>" && 670 test $(git rev-parse branch3) != $(git rev-parse branch4) && 671 git rebase -i branch3 && 672 test_cmp_rev branch3 branch4 673 674' 675 676test_expect_success 'submodule rebase setup' ' 677 git checkout A && 678 mkdir sub && 679 ( 680 cd sub && git init && >elif && 681 git add elif && git commit -m "submodule initial" 682 ) && 683 echo 1 >file1 && 684 git add file1 sub && 685 test_tick && 686 git commit -m "One" && 687 echo 2 >file1 && 688 test_tick && 689 git commit -a -m "Two" && 690 ( 691 cd sub && echo 3 >elif && 692 git commit -a -m "submodule second" 693 ) && 694 test_tick && 695 git commit -a -m "Three changes submodule" 696' 697 698test_expect_success 'submodule rebase -i' ' 699 ( 700 set_fake_editor && 701 FAKE_LINES="1 squash 2 3" git rebase -i A 702 ) 703' 704 705test_expect_success 'submodule conflict setup' ' 706 git tag submodule-base && 707 git checkout HEAD^ && 708 ( 709 cd sub && git checkout HEAD^ && echo 4 >elif && 710 git add elif && git commit -m "submodule conflict" 711 ) && 712 git add sub && 713 test_tick && 714 git commit -m "Conflict in submodule" && 715 git tag submodule-topic 716' 717 718test_expect_success 'rebase -i continue with only submodule staged' ' 719 test_must_fail git rebase -i submodule-base && 720 git add sub && 721 git rebase --continue && 722 test $(git rev-parse submodule-base) != $(git rev-parse HEAD) 723' 724 725test_expect_success 'rebase -i continue with unstaged submodule' ' 726 git checkout submodule-topic && 727 git reset --hard && 728 test_must_fail git rebase -i submodule-base && 729 git reset && 730 git rebase --continue && 731 test_cmp_rev submodule-base HEAD 732' 733 734test_expect_success 'avoid unnecessary reset' ' 735 git checkout primary && 736 git reset --hard && 737 test-tool chmtime =123456789 file3 && 738 git update-index --refresh && 739 HEAD=$(git rev-parse HEAD) && 740 git rebase -i HEAD~4 && 741 test $HEAD = $(git rev-parse HEAD) && 742 MTIME=$(test-tool chmtime --get file3) && 743 test 123456789 = $MTIME 744' 745 746test_expect_success 'reword' ' 747 git checkout -b reword-branch primary && 748 ( 749 set_fake_editor && 750 FAKE_LINES="1 2 3 reword 4" FAKE_COMMIT_MESSAGE="E changed" \ 751 git rebase -i A && 752 git show HEAD | grep "E changed" && 753 test $(git rev-parse primary) != $(git rev-parse HEAD) && 754 test_cmp_rev primary^ HEAD^ && 755 FAKE_LINES="1 2 reword 3 4" FAKE_COMMIT_MESSAGE="D changed" \ 756 git rebase -i A && 757 git show HEAD^ | grep "D changed" && 758 FAKE_LINES="reword 1 2 3 4" FAKE_COMMIT_MESSAGE="B changed" \ 759 git rebase -i A && 760 git show HEAD~3 | grep "B changed" && 761 FAKE_LINES="1 r 2 pick 3 p 4" FAKE_COMMIT_MESSAGE="C changed" \ 762 git rebase -i A 763 ) && 764 git show HEAD~2 | grep "C changed" 765' 766 767test_expect_success 'no uncommited changes when rewording the todo list is reloaded' ' 768 git checkout E && 769 test_when_finished "git checkout @{-1}" && 770 ( 771 set_fake_editor && 772 GIT_SEQUENCE_EDITOR="\"$PWD/fake-editor.sh\"" && 773 export GIT_SEQUENCE_EDITOR && 774 set_reword_editor && 775 FAKE_LINES="reword 1 reword 2" git rebase -i C 776 ) && 777 check_reworded_commits D E 778' 779 780test_expect_success 'rebase -i can copy notes' ' 781 git config notes.rewrite.rebase true && 782 git config notes.rewriteRef "refs/notes/*" && 783 test_commit n1 && 784 test_commit n2 && 785 test_commit n3 && 786 git notes add -m"a note" n3 && 787 git rebase -i --onto n1 n2 && 788 test "a note" = "$(git notes show HEAD)" 789' 790 791test_expect_success 'rebase -i can copy notes over a fixup' ' 792 cat >expect <<-\EOF && 793 an earlier note 794 795 a note 796 EOF 797 git reset --hard n3 && 798 git notes add -m"an earlier note" n2 && 799 ( 800 set_fake_editor && 801 GIT_NOTES_REWRITE_MODE=concatenate FAKE_LINES="1 f 2" \ 802 git rebase -i n1 803 ) && 804 git notes show > output && 805 test_cmp expect output 806' 807 808test_expect_success 'rebase while detaching HEAD' ' 809 git symbolic-ref HEAD && 810 grandparent=$(git rev-parse HEAD~2) && 811 test_tick && 812 ( 813 set_fake_editor && 814 FAKE_LINES="2 1" git rebase -i HEAD~2 HEAD^0 815 ) && 816 test $grandparent = $(git rev-parse HEAD~2) && 817 test_must_fail git symbolic-ref HEAD 818' 819 820test_tick # Ensure that the rebased commits get a different timestamp. 821test_expect_success 'always cherry-pick with --no-ff' ' 822 git checkout no-ff-branch && 823 git tag original-no-ff-branch && 824 git rebase -i --no-ff A && 825 for p in 0 1 2 826 do 827 test ! $(git rev-parse HEAD~$p) = $(git rev-parse original-no-ff-branch~$p) && 828 git diff HEAD~$p original-no-ff-branch~$p > out && 829 test_must_be_empty out 830 done && 831 test_cmp_rev HEAD~3 original-no-ff-branch~3 && 832 git diff HEAD~3 original-no-ff-branch~3 > out && 833 test_must_be_empty out 834' 835 836test_expect_success 'set up commits with funny messages' ' 837 git checkout -b funny A && 838 echo >>file1 && 839 test_tick && 840 git commit -a -m "end with slash\\" && 841 echo >>file1 && 842 test_tick && 843 git commit -a -m "something (\000) that looks like octal" && 844 echo >>file1 && 845 test_tick && 846 git commit -a -m "something (\n) that looks like a newline" && 847 echo >>file1 && 848 test_tick && 849 git commit -a -m "another commit" 850' 851 852test_expect_success 'rebase-i history with funny messages' ' 853 git rev-list A..funny >expect && 854 test_tick && 855 ( 856 set_fake_editor && 857 FAKE_LINES="1 2 3 4" git rebase -i A 858 ) && 859 git rev-list A.. >actual && 860 test_cmp expect actual 861' 862 863test_expect_success 'prepare for rebase -i --exec' ' 864 git checkout primary && 865 git checkout -b execute && 866 test_commit one_exec main.txt one_exec && 867 test_commit two_exec main.txt two_exec && 868 test_commit three_exec main.txt three_exec 869' 870 871test_expect_success 'running "git rebase -i --exec git show HEAD"' ' 872 ( 873 set_fake_editor && 874 git rebase -i --exec "git show HEAD" HEAD~2 >actual && 875 FAKE_LINES="1 exec_git_show_HEAD 2 exec_git_show_HEAD" && 876 export FAKE_LINES && 877 git rebase -i HEAD~2 >expect 878 ) && 879 sed -e "1,9d" expect >expected && 880 test_cmp expected actual 881' 882 883test_expect_success 'running "git rebase --exec git show HEAD -i"' ' 884 git reset --hard execute && 885 ( 886 set_fake_editor && 887 git rebase --exec "git show HEAD" -i HEAD~2 >actual && 888 FAKE_LINES="1 exec_git_show_HEAD 2 exec_git_show_HEAD" && 889 export FAKE_LINES && 890 git rebase -i HEAD~2 >expect 891 ) && 892 sed -e "1,9d" expect >expected && 893 test_cmp expected actual 894' 895 896test_expect_success 'running "git rebase -ix git show HEAD"' ' 897 git reset --hard execute && 898 ( 899 set_fake_editor && 900 git rebase -ix "git show HEAD" HEAD~2 >actual && 901 FAKE_LINES="1 exec_git_show_HEAD 2 exec_git_show_HEAD" && 902 export FAKE_LINES && 903 git rebase -i HEAD~2 >expect 904 ) && 905 sed -e "1,9d" expect >expected && 906 test_cmp expected actual 907' 908 909 910test_expect_success 'rebase -ix with several <CMD>' ' 911 git reset --hard execute && 912 ( 913 set_fake_editor && 914 git rebase -ix "git show HEAD; pwd" HEAD~2 >actual && 915 FAKE_LINES="1 exec_git_show_HEAD;_pwd 2 exec_git_show_HEAD;_pwd" && 916 export FAKE_LINES && 917 git rebase -i HEAD~2 >expect 918 ) && 919 sed -e "1,9d" expect >expected && 920 test_cmp expected actual 921' 922 923test_expect_success 'rebase -ix with several instances of --exec' ' 924 git reset --hard execute && 925 ( 926 set_fake_editor && 927 git rebase -i --exec "git show HEAD" --exec "pwd" HEAD~2 >actual && 928 FAKE_LINES="1 exec_git_show_HEAD exec_pwd 2 929 exec_git_show_HEAD exec_pwd" && 930 export FAKE_LINES && 931 git rebase -i HEAD~2 >expect 932 ) && 933 sed -e "1,11d" expect >expected && 934 test_cmp expected actual 935' 936 937test_expect_success 'rebase -ix with --autosquash' ' 938 git reset --hard execute && 939 git checkout -b autosquash && 940 echo second >second.txt && 941 git add second.txt && 942 git commit -m "fixup! two_exec" && 943 echo bis >bis.txt && 944 git add bis.txt && 945 git commit -m "fixup! two_exec" && 946 git checkout -b autosquash_actual && 947 git rebase -i --exec "git show HEAD" --autosquash HEAD~4 >actual && 948 git checkout autosquash && 949 ( 950 set_fake_editor && 951 git checkout -b autosquash_expected && 952 FAKE_LINES="1 fixup 3 fixup 4 exec_git_show_HEAD 2 exec_git_show_HEAD" && 953 export FAKE_LINES && 954 git rebase -i HEAD~4 >expect 955 ) && 956 sed -e "1,13d" expect >expected && 957 test_cmp expected actual 958' 959 960test_expect_success 'rebase --exec works without -i ' ' 961 git reset --hard execute && 962 rm -rf exec_output && 963 EDITOR="echo >invoked_editor" git rebase --exec "echo a line >>exec_output" HEAD~2 2>actual && 964 test_i18ngrep "Successfully rebased and updated" actual && 965 test_line_count = 2 exec_output && 966 test_path_is_missing invoked_editor 967' 968 969test_expect_success 'rebase -i --exec without <CMD>' ' 970 git reset --hard execute && 971 test_must_fail git rebase -i --exec 2>actual && 972 test_i18ngrep "requires a value" actual && 973 git checkout primary 974' 975 976test_expect_success 'rebase -i --root re-order and drop commits' ' 977 git checkout E && 978 ( 979 set_fake_editor && 980 FAKE_LINES="3 1 2 5" git rebase -i --root 981 ) && 982 test E = $(git cat-file commit HEAD | sed -ne \$p) && 983 test B = $(git cat-file commit HEAD^ | sed -ne \$p) && 984 test A = $(git cat-file commit HEAD^^ | sed -ne \$p) && 985 test C = $(git cat-file commit HEAD^^^ | sed -ne \$p) && 986 test 0 = $(git cat-file commit HEAD^^^ | grep -c ^parent\ ) 987' 988 989test_expect_success 'rebase -i --root retain root commit author and message' ' 990 git checkout A && 991 echo B >file7 && 992 git add file7 && 993 GIT_AUTHOR_NAME="Twerp Snog" git commit -m "different author" && 994 ( 995 set_fake_editor && 996 FAKE_LINES="2" git rebase -i --root 997 ) && 998 git cat-file commit HEAD | grep -q "^author Twerp Snog" && 999 git cat-file commit HEAD | grep -q "^different author$" 1000' 1001 1002test_expect_success 'rebase -i --root temporary sentinel commit' ' 1003 git checkout B && 1004 ( 1005 set_fake_editor && 1006 test_must_fail env FAKE_LINES="2" git rebase -i --root 1007 ) && 1008 git cat-file commit HEAD | grep "^tree $EMPTY_TREE" && 1009 git rebase --abort 1010' 1011 1012test_expect_success 'rebase -i --root fixup root commit' ' 1013 git checkout B && 1014 ( 1015 set_fake_editor && 1016 FAKE_LINES="1 fixup 2" git rebase -i --root 1017 ) && 1018 test A = $(git cat-file commit HEAD | sed -ne \$p) && 1019 test B = $(git show HEAD:file1) && 1020 test 0 = $(git cat-file commit HEAD | grep -c ^parent\ ) 1021' 1022 1023test_expect_success 'rebase -i --root reword original root commit' ' 1024 test_when_finished "test_might_fail git rebase --abort" && 1025 git checkout -b reword-original-root-branch primary && 1026 ( 1027 set_fake_editor && 1028 FAKE_LINES="reword 1 2" FAKE_COMMIT_MESSAGE="A changed" \ 1029 git rebase -i --root 1030 ) && 1031 git show HEAD^ | grep "A changed" && 1032 test -z "$(git show -s --format=%p HEAD^)" 1033' 1034 1035test_expect_success 'rebase -i --root reword new root commit' ' 1036 test_when_finished "test_might_fail git rebase --abort" && 1037 git checkout -b reword-now-root-branch primary && 1038 ( 1039 set_fake_editor && 1040 FAKE_LINES="reword 3 1" FAKE_COMMIT_MESSAGE="C changed" \ 1041 git rebase -i --root 1042 ) && 1043 git show HEAD^ | grep "C changed" && 1044 test -z "$(git show -s --format=%p HEAD^)" 1045' 1046 1047test_expect_success 'rebase -i --root when root has untracked file conflict' ' 1048 test_when_finished "reset_rebase" && 1049 git checkout -b failing-root-pick A && 1050 echo x >file2 && 1051 git rm file1 && 1052 git commit -m "remove file 1 add file 2" && 1053 echo z >file1 && 1054 ( 1055 set_fake_editor && 1056 test_must_fail env FAKE_LINES="1 2" git rebase -i --root 1057 ) && 1058 rm file1 && 1059 git rebase --continue && 1060 test "$(git log -1 --format=%B)" = "remove file 1 add file 2" && 1061 test "$(git rev-list --count HEAD)" = 2 1062' 1063 1064test_expect_success 'rebase -i --root reword root when root has untracked file conflict' ' 1065 test_when_finished "reset_rebase" && 1066 echo z>file1 && 1067 ( 1068 set_fake_editor && 1069 test_must_fail env FAKE_LINES="reword 1 2" \ 1070 FAKE_COMMIT_MESSAGE="Modified A" git rebase -i --root && 1071 rm file1 && 1072 FAKE_COMMIT_MESSAGE="Reworded A" git rebase --continue 1073 ) && 1074 test "$(git log -1 --format=%B HEAD^)" = "Reworded A" && 1075 test "$(git rev-list --count HEAD)" = 2 1076' 1077 1078test_expect_success 'rebase --edit-todo does not work on non-interactive rebase' ' 1079 git checkout reword-original-root-branch && 1080 git reset --hard && 1081 git checkout conflict-branch && 1082 ( 1083 set_fake_editor && 1084 test_must_fail git rebase -f --apply --onto HEAD~2 HEAD~ && 1085 test_must_fail git rebase --edit-todo 1086 ) && 1087 git rebase --abort 1088' 1089 1090test_expect_success 'rebase --edit-todo can be used to modify todo' ' 1091 git reset --hard && 1092 git checkout no-conflict-branch^0 && 1093 ( 1094 set_fake_editor && 1095 FAKE_LINES="edit 1 2 3" git rebase -i HEAD~3 && 1096 FAKE_LINES="2 1" git rebase --edit-todo && 1097 git rebase --continue 1098 ) && 1099 test M = $(git cat-file commit HEAD^ | sed -ne \$p) && 1100 test L = $(git cat-file commit HEAD | sed -ne \$p) 1101' 1102 1103test_expect_success 'rebase -i produces readable reflog' ' 1104 git reset --hard && 1105 git branch -f branch-reflog-test H && 1106 git rebase -i --onto I F branch-reflog-test && 1107 cat >expect <<-\EOF && 1108 rebase (finish): returning to refs/heads/branch-reflog-test 1109 rebase (pick): H 1110 rebase (pick): G 1111 rebase (start): checkout I 1112 EOF 1113 git reflog -n4 HEAD | 1114 sed "s/[^:]*: //" >actual && 1115 test_cmp expect actual 1116' 1117 1118test_expect_success 'rebase -i respects core.commentchar' ' 1119 git reset --hard && 1120 git checkout E^0 && 1121 test_config core.commentchar "\\" && 1122 write_script remove-all-but-first.sh <<-\EOF && 1123 sed -e "2,\$s/^/\\\\/" "$1" >"$1.tmp" && 1124 mv "$1.tmp" "$1" 1125 EOF 1126 ( 1127 test_set_editor "$(pwd)/remove-all-but-first.sh" && 1128 git rebase -i B 1129 ) && 1130 test B = $(git cat-file commit HEAD^ | sed -ne \$p) 1131' 1132 1133test_expect_success 'rebase -i respects core.commentchar=auto' ' 1134 test_config core.commentchar auto && 1135 write_script copy-edit-script.sh <<-\EOF && 1136 cp "$1" edit-script 1137 EOF 1138 test_when_finished "git rebase --abort || :" && 1139 ( 1140 test_set_editor "$(pwd)/copy-edit-script.sh" && 1141 git rebase -i HEAD^ 1142 ) && 1143 test -z "$(grep -ve "^#" -e "^\$" -e "^pick" edit-script)" 1144' 1145 1146test_expect_success 'rebase -i, with <onto> and <upstream> specified as :/quuxery' ' 1147 test_when_finished "git branch -D torebase" && 1148 git checkout -b torebase branch1 && 1149 upstream=$(git rev-parse ":/J") && 1150 onto=$(git rev-parse ":/A") && 1151 git rebase --onto $onto $upstream && 1152 git reset --hard branch1 && 1153 git rebase --onto ":/A" ":/J" && 1154 git checkout branch1 1155' 1156 1157test_expect_success 'rebase -i with --strategy and -X' ' 1158 git checkout -b conflict-merge-use-theirs conflict-branch && 1159 git reset --hard HEAD^ && 1160 echo five >conflict && 1161 echo Z >file1 && 1162 git commit -a -m "one file conflict" && 1163 EDITOR=true git rebase -i --strategy=recursive -Xours conflict-branch && 1164 test $(git show conflict-branch:conflict) = $(cat conflict) && 1165 test $(cat file1) = Z 1166' 1167 1168test_expect_success 'interrupted rebase -i with --strategy and -X' ' 1169 git checkout -b conflict-merge-use-theirs-interrupted conflict-branch && 1170 git reset --hard HEAD^ && 1171 >breakpoint && 1172 git add breakpoint && 1173 git commit -m "breakpoint for interactive mode" && 1174 echo five >conflict && 1175 echo Z >file1 && 1176 git commit -a -m "one file conflict" && 1177 ( 1178 set_fake_editor && 1179 FAKE_LINES="edit 1 2" git rebase -i --strategy=recursive \ 1180 -Xours conflict-branch 1181 ) && 1182 git rebase --continue && 1183 test $(git show conflict-branch:conflict) = $(cat conflict) && 1184 test $(cat file1) = Z 1185' 1186 1187test_expect_success 'rebase -i error on commits with \ in message' ' 1188 current_head=$(git rev-parse HEAD) && 1189 test_when_finished "git rebase --abort; git reset --hard $current_head; rm -f error" && 1190 test_commit TO-REMOVE will-conflict old-content && 1191 test_commit "\temp" will-conflict new-content dummy && 1192 test_must_fail env EDITOR=true git rebase -i HEAD^ --onto HEAD^^ 2>error && 1193 test_expect_code 1 grep " emp" error 1194' 1195 1196test_expect_success 'short commit ID setup' ' 1197 test_when_finished "git checkout primary" && 1198 git checkout --orphan collide && 1199 git rm -rf . && 1200 ( 1201 unset test_tick && 1202 test_commit collide1 collide && 1203 test_commit --notick collide2 collide && 1204 test_commit --notick collide3 collide 1205 ) 1206' 1207 1208if test -n "$GIT_TEST_FIND_COLLIDER" 1209then 1210 author="$(unset test_tick; test_tick; git var GIT_AUTHOR_IDENT)" 1211 committer="$(unset test_tick; test_tick; git var GIT_COMMITTER_IDENT)" 1212 blob="$(git rev-parse collide2:collide)" 1213 from="$(git rev-parse collide1^0)" 1214 repl="commit refs/heads/collider-&\\n" 1215 repl="${repl}author $author\\ncommitter $committer\\n" 1216 repl="${repl}data <<EOF\\ncollide2 &\\nEOF\\n" 1217 repl="${repl}from $from\\nM 100644 $blob collide\\n" 1218 test_seq 1 32768 | sed "s|.*|$repl|" >script && 1219 git fast-import <script && 1220 git pack-refs && 1221 git for-each-ref >refs && 1222 grep "^$(test_oid t3404_collision)" <refs >matches && 1223 cat matches && 1224 test_line_count -gt 2 matches || { 1225 echo "Could not find a collider" >&2 1226 exit 1 1227 } 1228fi 1229 1230test_expect_success 'short commit ID collide' ' 1231 test_oid_cache <<-EOF && 1232 # collision-related constants 1233 t3404_collision sha1:6bcd 1234 t3404_collision sha256:0161 1235 t3404_collider sha1:ac4f2ee 1236 t3404_collider sha256:16697 1237 EOF 1238 test_when_finished "reset_rebase && git checkout primary" && 1239 git checkout collide && 1240 colliding_id=$(test_oid t3404_collision) && 1241 hexsz=$(test_oid hexsz) && 1242 test $colliding_id = "$(git rev-parse HEAD | cut -c 1-4)" && 1243 test_config core.abbrev 4 && 1244 ( 1245 unset test_tick && 1246 test_tick && 1247 set_fake_editor && 1248 FAKE_COMMIT_MESSAGE="collide2 $(test_oid t3404_collider)" \ 1249 FAKE_LINES="reword 1 break 2" git rebase -i HEAD~2 && 1250 test $colliding_id = "$(git rev-parse HEAD | cut -c 1-4)" && 1251 grep "^pick $colliding_id " \ 1252 .git/rebase-merge/git-rebase-todo.tmp && 1253 grep "^pick [0-9a-f]\{$hexsz\}" \ 1254 .git/rebase-merge/git-rebase-todo && 1255 grep "^pick [0-9a-f]\{$hexsz\}" \ 1256 .git/rebase-merge/git-rebase-todo.backup && 1257 git rebase --continue 1258 ) && 1259 collide2="$(git rev-parse HEAD~1 | cut -c 1-4)" && 1260 collide3="$(git rev-parse collide3 | cut -c 1-4)" && 1261 test "$collide2" = "$collide3" 1262' 1263 1264test_expect_success 'respect core.abbrev' ' 1265 git config core.abbrev 12 && 1266 ( 1267 set_cat_todo_editor && 1268 test_must_fail git rebase -i HEAD~4 >todo-list 1269 ) && 1270 test 4 = $(grep -c "pick [0-9a-f]\{12,\}" todo-list) 1271' 1272 1273test_expect_success 'todo count' ' 1274 write_script dump-raw.sh <<-\EOF && 1275 cat "$1" 1276 EOF 1277 ( 1278 test_set_editor "$(pwd)/dump-raw.sh" && 1279 git rebase -i HEAD~4 >actual 1280 ) && 1281 test_i18ngrep "^# Rebase ..* onto ..* ([0-9]" actual 1282' 1283 1284test_expect_success 'rebase -i commits that overwrite untracked files (pick)' ' 1285 git checkout --force branch2 && 1286 git clean -f && 1287 ( 1288 set_fake_editor && 1289 FAKE_LINES="edit 1 2" git rebase -i A 1290 ) && 1291 test_cmp_rev HEAD F && 1292 test_path_is_missing file6 && 1293 >file6 && 1294 test_must_fail git rebase --continue && 1295 test_cmp_rev HEAD F && 1296 rm file6 && 1297 git rebase --continue && 1298 test_cmp_rev HEAD I 1299' 1300 1301test_expect_success 'rebase -i commits that overwrite untracked files (squash)' ' 1302 git checkout --force branch2 && 1303 git clean -f && 1304 git tag original-branch2 && 1305 ( 1306 set_fake_editor && 1307 FAKE_LINES="edit 1 squash 2" git rebase -i A 1308 ) && 1309 test_cmp_rev HEAD F && 1310 test_path_is_missing file6 && 1311 >file6 && 1312 test_must_fail git rebase --continue && 1313 test_cmp_rev HEAD F && 1314 rm file6 && 1315 git rebase --continue && 1316 test $(git cat-file commit HEAD | sed -ne \$p) = I && 1317 git reset --hard original-branch2 1318' 1319 1320test_expect_success 'rebase -i commits that overwrite untracked files (no ff)' ' 1321 git checkout --force branch2 && 1322 git clean -f && 1323 ( 1324 set_fake_editor && 1325 FAKE_LINES="edit 1 2" git rebase -i --no-ff A 1326 ) && 1327 test $(git cat-file commit HEAD | sed -ne \$p) = F && 1328 test_path_is_missing file6 && 1329 >file6 && 1330 test_must_fail git rebase --continue && 1331 test $(git cat-file commit HEAD | sed -ne \$p) = F && 1332 rm file6 && 1333 git rebase --continue && 1334 test $(git cat-file commit HEAD | sed -ne \$p) = I 1335' 1336 1337test_expect_success 'rebase --continue removes CHERRY_PICK_HEAD' ' 1338 git checkout -b commit-to-skip && 1339 for double in X 3 1 1340 do 1341 test_seq 5 | sed "s/$double/&&/" >seq && 1342 git add seq && 1343 test_tick && 1344 git commit -m seq-$double 1345 done && 1346 git tag seq-onto && 1347 git reset --hard HEAD~2 && 1348 git cherry-pick seq-onto && 1349 ( 1350 set_fake_editor && 1351 test_must_fail env FAKE_LINES= git rebase -i seq-onto 1352 ) && 1353 test -d .git/rebase-merge && 1354 git rebase --continue && 1355 git diff --exit-code seq-onto && 1356 test ! -d .git/rebase-merge && 1357 test ! -f .git/CHERRY_PICK_HEAD 1358' 1359 1360rebase_setup_and_clean () { 1361 test_when_finished " 1362 git checkout primary && 1363 test_might_fail git branch -D $1 && 1364 test_might_fail git rebase --abort 1365 " && 1366 git checkout -b $1 ${2:-primary} 1367} 1368 1369test_expect_success 'drop' ' 1370 rebase_setup_and_clean drop-test && 1371 ( 1372 set_fake_editor && 1373 FAKE_LINES="1 drop 2 3 d 4 5" git rebase -i --root 1374 ) && 1375 test E = $(git cat-file commit HEAD | sed -ne \$p) && 1376 test C = $(git cat-file commit HEAD^ | sed -ne \$p) && 1377 test A = $(git cat-file commit HEAD^^ | sed -ne \$p) 1378' 1379 1380test_expect_success 'rebase -i respects rebase.missingCommitsCheck = ignore' ' 1381 test_config rebase.missingCommitsCheck ignore && 1382 rebase_setup_and_clean missing-commit && 1383 ( 1384 set_fake_editor && 1385 FAKE_LINES="1 2 3 4" git rebase -i --root 2>actual 1386 ) && 1387 test D = $(git cat-file commit HEAD | sed -ne \$p) && 1388 test_i18ngrep \ 1389 "Successfully rebased and updated refs/heads/missing-commit" \ 1390 actual 1391' 1392 1393test_expect_success 'rebase -i respects rebase.missingCommitsCheck = warn' ' 1394 cat >expect <<-EOF && 1395 Warning: some commits may have been dropped accidentally. 1396 Dropped commits (newer to older): 1397 - $(git rev-list --pretty=oneline --abbrev-commit -1 primary) 1398 To avoid this message, use "drop" to explicitly remove a commit. 1399 EOF 1400 test_config rebase.missingCommitsCheck warn && 1401 rebase_setup_and_clean missing-commit && 1402 ( 1403 set_fake_editor && 1404 FAKE_LINES="1 2 3 4" git rebase -i --root 2>actual.2 1405 ) && 1406 head -n4 actual.2 >actual && 1407 test_cmp expect actual && 1408 test D = $(git cat-file commit HEAD | sed -ne \$p) 1409' 1410 1411test_expect_success 'rebase -i respects rebase.missingCommitsCheck = error' ' 1412 cat >expect <<-EOF && 1413 Warning: some commits may have been dropped accidentally. 1414 Dropped commits (newer to older): 1415 - $(git rev-list --pretty=oneline --abbrev-commit -1 primary) 1416 - $(git rev-list --pretty=oneline --abbrev-commit -1 primary~2) 1417 To avoid this message, use "drop" to explicitly remove a commit. 1418 1419 Use '\''git config rebase.missingCommitsCheck'\'' to change the level of warnings. 1420 The possible behaviours are: ignore, warn, error. 1421 1422 You can fix this with '\''git rebase --edit-todo'\'' and then run '\''git rebase --continue'\''. 1423 Or you can abort the rebase with '\''git rebase --abort'\''. 1424 EOF 1425 test_config rebase.missingCommitsCheck error && 1426 rebase_setup_and_clean missing-commit && 1427 ( 1428 set_fake_editor && 1429 test_must_fail env FAKE_LINES="1 2 4" \ 1430 git rebase -i --root 2>actual && 1431 test_cmp expect actual && 1432 cp .git/rebase-merge/git-rebase-todo.backup \ 1433 .git/rebase-merge/git-rebase-todo && 1434 FAKE_LINES="1 2 drop 3 4 drop 5" git rebase --edit-todo 1435 ) && 1436 git rebase --continue && 1437 test D = $(git cat-file commit HEAD | sed -ne \$p) && 1438 test B = $(git cat-file commit HEAD^ | sed -ne \$p) 1439' 1440 1441test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = ignore' ' 1442 test_config rebase.missingCommitsCheck ignore && 1443 rebase_setup_and_clean missing-commit && 1444 ( 1445 set_fake_editor && 1446 FAKE_LINES="break 1 2 3 4 5" git rebase -i --root && 1447 FAKE_LINES="1 2 3 4" git rebase --edit-todo && 1448 git rebase --continue 2>actual 1449 ) && 1450 test D = $(git cat-file commit HEAD | sed -ne \$p) && 1451 test_i18ngrep \ 1452 "Successfully rebased and updated refs/heads/missing-commit" \ 1453 actual 1454' 1455 1456test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = warn' ' 1457 cat >expect <<-EOF && 1458 error: invalid line 1: badcmd $(git rev-list --pretty=oneline --abbrev-commit -1 primary~4) 1459 Warning: some commits may have been dropped accidentally. 1460 Dropped commits (newer to older): 1461 - $(git rev-list --pretty=oneline --abbrev-commit -1 primary) 1462 - $(git rev-list --pretty=oneline --abbrev-commit -1 primary~4) 1463 To avoid this message, use "drop" to explicitly remove a commit. 1464 EOF 1465 head -n4 expect >expect.2 && 1466 tail -n1 expect >>expect.2 && 1467 tail -n4 expect.2 >expect.3 && 1468 test_config rebase.missingCommitsCheck warn && 1469 rebase_setup_and_clean missing-commit && 1470 ( 1471 set_fake_editor && 1472 test_must_fail env FAKE_LINES="bad 1 2 3 4 5" \ 1473 git rebase -i --root && 1474 cp .git/rebase-merge/git-rebase-todo.backup orig && 1475 FAKE_LINES="2 3 4" git rebase --edit-todo 2>actual.2 && 1476 head -n6 actual.2 >actual && 1477 test_cmp expect actual && 1478 cp orig .git/rebase-merge/git-rebase-todo && 1479 FAKE_LINES="1 2 3 4" git rebase --edit-todo 2>actual.2 && 1480 head -n4 actual.2 >actual && 1481 test_cmp expect.3 actual && 1482 git rebase --continue 2>actual 1483 ) && 1484 test D = $(git cat-file commit HEAD | sed -ne \$p) && 1485 test_i18ngrep \ 1486 "Successfully rebased and updated refs/heads/missing-commit" \ 1487 actual 1488' 1489 1490test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = error' ' 1491 cat >expect <<-EOF && 1492 error: invalid line 1: badcmd $(git rev-list --pretty=oneline --abbrev-commit -1 primary~4) 1493 Warning: some commits may have been dropped accidentally. 1494 Dropped commits (newer to older): 1495 - $(git rev-list --pretty=oneline --abbrev-commit -1 primary) 1496 - $(git rev-list --pretty=oneline --abbrev-commit -1 primary~4) 1497 To avoid this message, use "drop" to explicitly remove a commit. 1498 1499 Use '\''git config rebase.missingCommitsCheck'\'' to change the level of warnings. 1500 The possible behaviours are: ignore, warn, error. 1501 1502 You can fix this with '\''git rebase --edit-todo'\'' and then run '\''git rebase --continue'\''. 1503 Or you can abort the rebase with '\''git rebase --abort'\''. 1504 EOF 1505 tail -n11 expect >expect.2 && 1506 head -n3 expect.2 >expect.3 && 1507 tail -n7 expect.2 >>expect.3 && 1508 test_config rebase.missingCommitsCheck error && 1509 rebase_setup_and_clean missing-commit && 1510 ( 1511 set_fake_editor && 1512 test_must_fail env FAKE_LINES="bad 1 2 3 4 5" \ 1513 git rebase -i --root && 1514 cp .git/rebase-merge/git-rebase-todo.backup orig && 1515 test_must_fail env FAKE_LINES="2 3 4" \ 1516 git rebase --edit-todo 2>actual && 1517 test_cmp expect actual && 1518 test_must_fail git rebase --continue 2>actual && 1519 test_cmp expect.2 actual && 1520 test_must_fail git rebase --edit-todo && 1521 cp orig .git/rebase-merge/git-rebase-todo && 1522 test_must_fail env FAKE_LINES="1 2 3 4" \ 1523 git rebase --edit-todo 2>actual && 1524 test_cmp expect.3 actual && 1525 test_must_fail git rebase --continue 2>actual && 1526 test_cmp expect.3 actual && 1527 cp orig .git/rebase-merge/git-rebase-todo && 1528 FAKE_LINES="1 2 3 4 drop 5" git rebase --edit-todo && 1529 git rebase --continue 2>actual 1530 ) && 1531 test D = $(git cat-file commit HEAD | sed -ne \$p) && 1532 test_i18ngrep \ 1533 "Successfully rebased and updated refs/heads/missing-commit" \ 1534 actual 1535' 1536 1537test_expect_success 'rebase.missingCommitsCheck = error after resolving conflicts' ' 1538 test_config rebase.missingCommitsCheck error && 1539 ( 1540 set_fake_editor && 1541 FAKE_LINES="drop 1 break 2 3 4" git rebase -i A E 1542 ) && 1543 git rebase --edit-todo && 1544 test_must_fail git rebase --continue && 1545 echo x >file1 && 1546 git add file1 && 1547 git rebase --continue 1548' 1549 1550test_expect_success 'rebase.missingCommitsCheck = error when editing for a second time' ' 1551 test_config rebase.missingCommitsCheck error && 1552 ( 1553 set_fake_editor && 1554 FAKE_LINES="1 break 2 3" git rebase -i A D && 1555 cp .git/rebase-merge/git-rebase-todo todo && 1556 test_must_fail env FAKE_LINES=2 git rebase --edit-todo && 1557 GIT_SEQUENCE_EDITOR="cp todo" git rebase --edit-todo && 1558 git rebase --continue 1559 ) 1560' 1561 1562test_expect_success 'respects rebase.abbreviateCommands with fixup, squash and exec' ' 1563 rebase_setup_and_clean abbrevcmd && 1564 test_commit "first" file1.txt "first line" first && 1565 test_commit "second" file1.txt "another line" second && 1566 test_commit "fixup! first" file2.txt "first line again" first_fixup && 1567 test_commit "squash! second" file1.txt "another line here" second_squash && 1568 cat >expected <<-EOF && 1569 p $(git rev-list --abbrev-commit -1 first) first 1570 f $(git rev-list --abbrev-commit -1 first_fixup) fixup! first 1571 x git show HEAD 1572 p $(git rev-list --abbrev-commit -1 second) second 1573 s $(git rev-list --abbrev-commit -1 second_squash) squash! second 1574 x git show HEAD 1575 EOF 1576 git checkout abbrevcmd && 1577 test_config rebase.abbreviateCommands true && 1578 ( 1579 set_cat_todo_editor && 1580 test_must_fail git rebase -i --exec "git show HEAD" \ 1581 --autosquash primary >actual 1582 ) && 1583 test_cmp expected actual 1584' 1585 1586test_expect_success 'static check of bad command' ' 1587 rebase_setup_and_clean bad-cmd && 1588 ( 1589 set_fake_editor && 1590 test_must_fail env FAKE_LINES="1 2 3 bad 4 5" \ 1591 git rebase -i --root 2>actual && 1592 test_i18ngrep "badcmd $(git rev-list --oneline -1 primary~1)" \ 1593 actual && 1594 test_i18ngrep "You can fix this with .git rebase --edit-todo.." \ 1595 actual && 1596 FAKE_LINES="1 2 3 drop 4 5" git rebase --edit-todo 1597 ) && 1598 git rebase --continue && 1599 test E = $(git cat-file commit HEAD | sed -ne \$p) && 1600 test C = $(git cat-file commit HEAD^ | sed -ne \$p) 1601' 1602 1603test_expect_success 'tabs and spaces are accepted in the todolist' ' 1604 rebase_setup_and_clean indented-comment && 1605 write_script add-indent.sh <<-\EOF && 1606 ( 1607 # Turn single spaces into space/tab mix 1608 sed "1s/ / /g; 2s/ / /g; 3s/ / /g" "$1" 1609 printf "\n\t# comment\n #more\n\t # comment\n" 1610 ) >"$1.new" 1611 mv "$1.new" "$1" 1612 EOF 1613 ( 1614 test_set_editor "$(pwd)/add-indent.sh" && 1615 git rebase -i HEAD^^^ 1616 ) && 1617 test E = $(git cat-file commit HEAD | sed -ne \$p) 1618' 1619 1620test_expect_success 'static check of bad SHA-1' ' 1621 rebase_setup_and_clean bad-sha && 1622 ( 1623 set_fake_editor && 1624 test_must_fail env FAKE_LINES="1 2 edit fakesha 3 4 5 #" \ 1625 git rebase -i --root 2>actual && 1626 test_i18ngrep "edit XXXXXXX False commit" actual && 1627 test_i18ngrep "You can fix this with .git rebase --edit-todo.." \ 1628 actual && 1629 FAKE_LINES="1 2 4 5 6" git rebase --edit-todo 1630 ) && 1631 git rebase --continue && 1632 test E = $(git cat-file commit HEAD | sed -ne \$p) 1633' 1634 1635test_expect_success 'editor saves as CR/LF' ' 1636 git checkout -b with-crlf && 1637 write_script add-crs.sh <<-\EOF && 1638 sed -e "s/\$/Q/" <"$1" | tr Q "\\015" >"$1".new && 1639 mv -f "$1".new "$1" 1640 EOF 1641 ( 1642 test_set_editor "$(pwd)/add-crs.sh" && 1643 git rebase -i HEAD^ 1644 ) 1645' 1646 1647test_expect_success 'rebase -i --gpg-sign=<key-id>' ' 1648 test_when_finished "test_might_fail git rebase --abort" && 1649 ( 1650 set_fake_editor && 1651 FAKE_LINES="edit 1" git rebase -i --gpg-sign="\"S I Gner\"" \ 1652 HEAD^ >out 2>err 1653 ) && 1654 test_i18ngrep "$SQ-S\"S I Gner\"$SQ" err 1655' 1656 1657test_expect_success 'rebase -i --gpg-sign=<key-id> overrides commit.gpgSign' ' 1658 test_when_finished "test_might_fail git rebase --abort" && 1659 test_config commit.gpgsign true && 1660 ( 1661 set_fake_editor && 1662 FAKE_LINES="edit 1" git rebase -i --gpg-sign="\"S I Gner\"" \ 1663 HEAD^ >out 2>err 1664 ) && 1665 test_i18ngrep "$SQ-S\"S I Gner\"$SQ" err 1666' 1667 1668test_expect_success 'valid author header after --root swap' ' 1669 rebase_setup_and_clean author-header no-conflict-branch && 1670 git commit --amend --author="Au ${SQ}thor <author@example.com>" --no-edit && 1671 git cat-file commit HEAD | grep ^author >expected && 1672 ( 1673 set_fake_editor && 1674 FAKE_LINES="5 1" git rebase -i --root 1675 ) && 1676 git cat-file commit HEAD^ | grep ^author >actual && 1677 test_cmp expected actual 1678' 1679 1680test_expect_success 'valid author header when author contains single quote' ' 1681 rebase_setup_and_clean author-header no-conflict-branch && 1682 git commit --amend --author="Au ${SQ}thor <author@example.com>" --no-edit && 1683 git cat-file commit HEAD | grep ^author >expected && 1684 ( 1685 set_fake_editor && 1686 FAKE_LINES="2" git rebase -i HEAD~2 1687 ) && 1688 git cat-file commit HEAD | grep ^author >actual && 1689 test_cmp expected actual 1690' 1691 1692test_expect_success 'post-commit hook is called' ' 1693 test_when_finished "rm -f .git/hooks/post-commit" && 1694 >actual && 1695 mkdir -p .git/hooks && 1696 write_script .git/hooks/post-commit <<-\EOS && 1697 git rev-parse HEAD >>actual 1698 EOS 1699 ( 1700 set_fake_editor && 1701 FAKE_LINES="edit 4 1 reword 2 fixup 3" git rebase -i A E && 1702 echo x>file3 && 1703 git add file3 && 1704 FAKE_COMMIT_MESSAGE=edited git rebase --continue 1705 ) && 1706 git rev-parse HEAD@{5} HEAD@{4} HEAD@{3} HEAD@{2} HEAD@{1} HEAD \ 1707 >expect && 1708 test_cmp expect actual 1709' 1710 1711test_expect_success 'correct error message for partial commit after empty pick' ' 1712 test_when_finished "git rebase --abort" && 1713 ( 1714 set_fake_editor && 1715 FAKE_LINES="2 1 1" && 1716 export FAKE_LINES && 1717 test_must_fail git rebase -i A D 1718 ) && 1719 echo x >file1 && 1720 test_must_fail git commit file1 2>err && 1721 test_i18ngrep "cannot do a partial commit during a rebase." err 1722' 1723 1724test_expect_success 'correct error message for commit --amend after empty pick' ' 1725 test_when_finished "git rebase --abort" && 1726 ( 1727 set_fake_editor && 1728 FAKE_LINES="1 1" && 1729 export FAKE_LINES && 1730 test_must_fail git rebase -i A D 1731 ) && 1732 echo x>file1 && 1733 test_must_fail git commit -a --amend 2>err && 1734 test_i18ngrep "middle of a rebase -- cannot amend." err 1735' 1736 1737test_expect_success 'todo has correct onto hash' ' 1738 GIT_SEQUENCE_EDITOR=cat git rebase -i no-conflict-branch~4 no-conflict-branch >actual && 1739 onto=$(git rev-parse --short HEAD~4) && 1740 test_i18ngrep "^# Rebase ..* onto $onto" actual 1741' 1742 1743test_expect_success 'ORIG_HEAD is updated correctly' ' 1744 test_when_finished "git checkout primary && git branch -D test-orig-head" && 1745 git checkout -b test-orig-head A && 1746 git commit --allow-empty -m A1 && 1747 git commit --allow-empty -m A2 && 1748 git commit --allow-empty -m A3 && 1749 git commit --allow-empty -m A4 && 1750 git rebase primary && 1751 test_cmp_rev ORIG_HEAD test-orig-head@{1} 1752' 1753 1754# This must be the last test in this file 1755test_expect_success '$EDITOR and friends are unchanged' ' 1756 test_editor_unchanged 1757' 1758 1759test_done 1760