Git fork
at reftables-rust 2321 lines 67 kB view raw
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' 28 29. ./test-lib.sh 30 31. "$TEST_DIRECTORY"/lib-rebase.sh 32 33test_expect_success 'setup' ' 34 git switch -C primary && 35 test_commit A file1 && 36 test_commit B file1 && 37 test_commit C file2 && 38 test_commit D file1 && 39 test_commit E file3 && 40 git checkout -b branch1 A && 41 test_commit F file4 && 42 test_commit G file1 && 43 test_commit H file5 && 44 git checkout -b branch2 F && 45 test_commit I file6 && 46 git checkout -b conflict-branch A && 47 test_commit one conflict && 48 test_commit two conflict && 49 test_commit three conflict && 50 test_commit four conflict && 51 git checkout -b no-conflict-branch A && 52 test_commit J fileJ && 53 test_commit K fileK && 54 test_commit L fileL && 55 test_commit M fileM && 56 git checkout -b no-ff-branch A && 57 test_commit N fileN && 58 test_commit O fileO && 59 test_commit P fileP 60' 61 62# "exec" commands are run with the user shell by default, but this may 63# be non-POSIX. For example, if SHELL=zsh then ">file" doesn't work 64# to create a file. Unsetting SHELL avoids such non-portable behavior 65# in tests. It must be exported for it to take effect where needed. 66SHELL= 67export SHELL 68 69test_expect_success 'rebase --keep-empty' ' 70 git checkout -b emptybranch primary && 71 git commit --allow-empty -m "empty" && 72 git rebase --keep-empty -i HEAD~2 && 73 git log --oneline >actual && 74 test_line_count = 6 actual 75' 76 77test_expect_success 'rebase -i with empty todo list' ' 78 cat >expect <<-\EOF && 79 error: nothing to do 80 EOF 81 ( 82 set_fake_editor && 83 test_must_fail env FAKE_LINES="#" \ 84 git rebase -i HEAD^ >output 2>&1 85 ) && 86 tail -n 1 output >actual && # Ignore output about changing todo list 87 test_cmp expect actual 88' 89 90test_expect_success 'rebase -i with the exec command' ' 91 git checkout primary && 92 ( 93 set_fake_editor && 94 FAKE_LINES="1 exec_>touch-one 95 2 exec_>touch-two exec_false exec_>touch-three 96 3 4 exec_>\"touch-file__name_with_spaces\";_>touch-after-semicolon 5" && 97 export FAKE_LINES && 98 test_must_fail git rebase -i A 99 ) && 100 test_path_is_file touch-one && 101 test_path_is_file touch-two && 102 # Missing because we should have stopped by now. 103 test_path_is_missing touch-three && 104 test_cmp_rev C HEAD && 105 git rebase --continue && 106 test_path_is_file touch-three && 107 test_path_is_file "touch-file name with spaces" && 108 test_path_is_file touch-after-semicolon && 109 test_cmp_rev primary HEAD && 110 rm -f touch-* 111' 112 113test_expect_success 'rebase -i with the exec command runs from tree root' ' 114 git checkout primary && 115 mkdir subdir && (cd subdir && 116 set_fake_editor && 117 FAKE_LINES="1 exec_>touch-subdir" \ 118 git rebase -i HEAD^ 119 ) && 120 test_path_is_file touch-subdir && 121 rm -fr subdir 122' 123 124test_expect_success 'rebase -i with exec allows git commands in subdirs' ' 125 test_when_finished "rm -rf subdir" && 126 test_when_finished "git rebase --abort ||:" && 127 git checkout primary && 128 mkdir subdir && (cd subdir && 129 set_fake_editor && 130 FAKE_LINES="1 x_cd_subdir_&&_git_rev-parse_--is-inside-work-tree" \ 131 git rebase -i HEAD^ 132 ) 133' 134 135test_expect_success 'rebase -i sets work tree properly' ' 136 test_when_finished "rm -rf subdir" && 137 test_when_finished "test_might_fail git rebase --abort" && 138 mkdir subdir && 139 git rebase -x "(cd subdir && git rev-parse --show-toplevel)" HEAD^ \ 140 >actual && 141 ! grep "/subdir$" actual 142' 143 144test_expect_success 'rebase -i with the exec command checks tree cleanness' ' 145 git checkout primary && 146 ( 147 set_fake_editor && 148 test_must_fail env FAKE_LINES="exec_echo_foo_>file1 1" \ 149 git rebase -i HEAD^ 150 ) && 151 test_cmp_rev primary^ HEAD && 152 git reset --hard && 153 git rebase --continue 154' 155 156test_expect_success 'cherry-pick works with rebase --exec' ' 157 test_when_finished "git cherry-pick --abort; \ 158 git rebase --abort; \ 159 git checkout primary" && 160 echo "exec git cherry-pick G" >todo && 161 ( 162 set_replace_editor todo && 163 test_must_fail git rebase -i D D 164 ) && 165 test_cmp_rev G CHERRY_PICK_HEAD 166' 167 168test_expect_success 'rebase -x with empty command fails' ' 169 test_when_finished "git rebase --abort ||:" && 170 test_must_fail env git rebase -x "" @ 2>actual && 171 test_write_lines "error: empty exec command" >expected && 172 test_cmp expected actual && 173 test_must_fail env git rebase -x " " @ 2>actual && 174 test_cmp expected actual 175' 176 177test_expect_success 'rebase -x with newline in command fails' ' 178 test_when_finished "git rebase --abort ||:" && 179 test_must_fail env git rebase -x "a${LF}b" @ 2>actual && 180 test_write_lines "error: exec commands cannot contain newlines" \ 181 >expected && 182 test_cmp expected actual 183' 184 185test_expect_success 'rebase -i with exec of inexistent command' ' 186 git checkout primary && 187 test_when_finished "git rebase --abort" && 188 ( 189 set_fake_editor && 190 test_must_fail env FAKE_LINES="exec_this-command-does-not-exist 1" \ 191 git rebase -i HEAD^ >actual 2>&1 192 ) && 193 ! grep "Maybe git-rebase is broken" actual 194' 195 196test_expect_success 'implicit interactive rebase does not invoke sequence editor' ' 197 test_when_finished "git rebase --abort ||:" && 198 GIT_SEQUENCE_EDITOR="echo bad >" git rebase -x"echo one" @^ 199' 200 201test_expect_success 'no changes are a nop' ' 202 git checkout branch2 && 203 git rebase -i F && 204 test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" && 205 test_cmp_rev I HEAD 206' 207 208test_expect_success 'test the [branch] option' ' 209 git checkout -b dead-end && 210 git rm file6 && 211 git commit -m "stop here" && 212 git rebase -i F branch2 && 213 test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" && 214 test_cmp_rev I branch2 && 215 test_cmp_rev I HEAD 216' 217 218test_expect_success 'test --onto <branch>' ' 219 git checkout -b test-onto branch2 && 220 git rebase -i --onto branch1 F && 221 test "$(git symbolic-ref -q HEAD)" = "refs/heads/test-onto" && 222 test_cmp_rev HEAD^ branch1 && 223 test_cmp_rev I branch2 224' 225 226test_expect_success 'rebase on top of a non-conflicting commit' ' 227 git checkout branch1 && 228 git tag original-branch1 && 229 git rebase -i branch2 && 230 test file6 = $(git diff --name-only original-branch1) && 231 test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch1" && 232 test_cmp_rev I branch2 && 233 test_cmp_rev I HEAD~2 234' 235 236test_expect_success 'reflog for the branch shows state before rebase' ' 237 test_cmp_rev branch1@{1} original-branch1 238' 239 240test_expect_success 'reflog for the branch shows correct finish message' ' 241 printf "rebase (finish): refs/heads/branch1 onto %s\n" \ 242 "$(git rev-parse branch2)" >expected && 243 git log -g --pretty=%gs -1 refs/heads/branch1 >actual && 244 test_cmp expected actual 245' 246 247test_expect_success 'exchange two commits' ' 248 ( 249 set_fake_editor && 250 FAKE_LINES="2 1" git rebase -i HEAD~2 251 ) && 252 test H = $(git cat-file commit HEAD^ | sed -ne \$p) && 253 test G = $(git cat-file commit HEAD | sed -ne \$p) && 254 blob1=$(git rev-parse --short HEAD^:file1) && 255 blob2=$(git rev-parse --short HEAD:file1) && 256 commit=$(git rev-parse --short HEAD) 257' 258 259test_expect_success 'stop on conflicting pick' ' 260 cat >expect <<-EOF && 261 diff --git a/file1 b/file1 262 index $blob1..$blob2 100644 263 --- a/file1 264 +++ b/file1 265 @@ -1 +1 @@ 266 -A 267 +G 268 EOF 269 cat >expect2 <<-EOF && 270 <<<<<<< HEAD 271 D 272 ======= 273 G 274 >>>>>>> $commit (G) 275 EOF 276 git tag new-branch1 && 277 test_must_fail git rebase -i primary && 278 test "$(git rev-parse HEAD~3)" = "$(git rev-parse primary)" && 279 test_cmp expect .git/rebase-merge/patch && 280 test_cmp expect2 file1 && 281 test "$(git diff --name-status | 282 sed -n -e "/^U/s/^U[^a-z]*//p")" = file1 && 283 grep -v "^#" <.git/rebase-merge/done >actual && 284 test_line_count = 4 actual && 285 test 0 = $(grep -c "^[^#]" <.git/rebase-merge/git-rebase-todo) 286' 287 288test_expect_success 'show conflicted patch' ' 289 GIT_TRACE=1 git rebase --show-current-patch >/dev/null 2>stderr && 290 grep "show.*REBASE_HEAD" stderr && 291 # the original stopped-sha1 is abbreviated 292 stopped_sha1="$(git rev-parse $(cat ".git/rebase-merge/stopped-sha"))" && 293 test "$(git rev-parse REBASE_HEAD)" = "$stopped_sha1" 294' 295 296test_expect_success 'abort' ' 297 git rebase --abort && 298 test_cmp_rev new-branch1 HEAD && 299 test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch1" && 300 test_path_is_missing .git/rebase-merge 301' 302 303test_expect_success 'abort with error when new base cannot be checked out' ' 304 git rm --cached file1 && 305 git commit -m "remove file in base" && 306 test_must_fail git rebase -i primary > output 2>&1 && 307 test_grep "The following untracked working tree files would be overwritten by checkout:" \ 308 output && 309 test_grep "file1" output && 310 test_path_is_missing .git/rebase-merge && 311 rm file1 && 312 git reset --hard HEAD^ 313' 314 315test_expect_success 'retain authorship' ' 316 echo A > file7 && 317 git add file7 && 318 test_tick && 319 GIT_AUTHOR_NAME="Twerp Snog" git commit -m "different author" && 320 git tag twerp && 321 git rebase -i --onto primary HEAD^ && 322 git show HEAD >actual && 323 grep "^Author: Twerp Snog" actual 324' 325 326test_expect_success 'retain authorship w/ conflicts' ' 327 oGIT_AUTHOR_NAME=$GIT_AUTHOR_NAME && 328 test_when_finished "GIT_AUTHOR_NAME=\$oGIT_AUTHOR_NAME" && 329 330 git reset --hard twerp && 331 test_commit a conflict a conflict-a && 332 git reset --hard twerp && 333 334 GIT_AUTHOR_NAME=AttributeMe && 335 export GIT_AUTHOR_NAME && 336 test_commit b conflict b conflict-b && 337 GIT_AUTHOR_NAME=$oGIT_AUTHOR_NAME && 338 339 test_must_fail git rebase -i conflict-a && 340 echo resolved >conflict && 341 git add conflict && 342 git rebase --continue && 343 test_cmp_rev conflict-a^0 HEAD^ && 344 git show >out && 345 grep AttributeMe out 346' 347 348test_expect_success 'squash' ' 349 git reset --hard twerp && 350 echo B > file7 && 351 test_tick && 352 GIT_AUTHOR_NAME="Nitfol" git commit -m "nitfol" file7 && 353 echo "******************************" && 354 ( 355 set_fake_editor && 356 FAKE_LINES="1 squash 2" EXPECT_HEADER_COUNT=2 \ 357 git rebase -i --onto primary HEAD~2 358 ) && 359 test B = $(cat file7) && 360 test_cmp_rev HEAD^ primary 361' 362 363test_expect_success 'retain authorship when squashing' ' 364 git show HEAD >actual && 365 grep "^Author: Twerp Snog" actual 366' 367 368test_expect_success '--continue tries to commit' ' 369 git reset --hard D && 370 test_tick && 371 ( 372 set_fake_editor && 373 test_must_fail git rebase -i --onto new-branch1 HEAD^ && 374 echo resolved > file1 && 375 git add file1 && 376 FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue 377 ) && 378 test_cmp_rev HEAD^ new-branch1 && 379 git show HEAD >actual && 380 grep chouette actual 381' 382 383test_expect_success 'verbose flag is heeded, even after --continue' ' 384 git reset --hard primary@{1} && 385 test_tick && 386 test_must_fail git rebase -v -i --onto new-branch1 HEAD^ && 387 echo resolved > file1 && 388 git add file1 && 389 git rebase --continue > output && 390 grep "^ file1 | 2 +-$" output 391' 392 393test_expect_success 'multi-squash only fires up editor once' ' 394 base=$(git rev-parse HEAD~4) && 395 ( 396 set_fake_editor && 397 FAKE_COMMIT_AMEND="ONCE" \ 398 FAKE_LINES="1 squash 2 squash 3 squash 4" \ 399 EXPECT_HEADER_COUNT=4 \ 400 git rebase -i $base 401 ) && 402 test $base = $(git rev-parse HEAD^) && 403 git show >output && 404 grep ONCE output >actual && 405 test_line_count = 1 actual 406' 407 408test_expect_success 'multi-fixup does not fire up editor' ' 409 git checkout -b multi-fixup E && 410 base=$(git rev-parse HEAD~4) && 411 ( 412 set_fake_editor && 413 FAKE_COMMIT_AMEND="NEVER" \ 414 FAKE_LINES="1 fixup 2 fixup 3 fixup 4" \ 415 git rebase -i $base 416 ) && 417 test $base = $(git rev-parse HEAD^) && 418 git show >output && 419 ! grep NEVER output && 420 git checkout @{-1} && 421 git branch -D multi-fixup 422' 423 424test_expect_success 'commit message used after conflict' ' 425 git checkout -b conflict-fixup conflict-branch && 426 base=$(git rev-parse HEAD~4) && 427 ( 428 set_fake_editor && 429 test_must_fail env FAKE_LINES="1 fixup 3 fixup 4" \ 430 git rebase -i $base && 431 echo three > conflict && 432 git add conflict && 433 FAKE_COMMIT_AMEND="ONCE" EXPECT_HEADER_COUNT=2 \ 434 git rebase --continue 435 ) && 436 test $base = $(git rev-parse HEAD^) && 437 git show >output && 438 grep ONCE output >actual && 439 test_line_count = 1 actual && 440 git checkout @{-1} && 441 git branch -D conflict-fixup 442' 443 444test_expect_success 'commit message retained after conflict' ' 445 git checkout -b conflict-squash conflict-branch && 446 base=$(git rev-parse HEAD~4) && 447 ( 448 set_fake_editor && 449 test_must_fail env FAKE_LINES="1 fixup 3 squash 4" \ 450 git rebase -i $base && 451 echo three > conflict && 452 git add conflict && 453 FAKE_COMMIT_AMEND="TWICE" EXPECT_HEADER_COUNT=2 \ 454 git rebase --continue 455 ) && 456 test $base = $(git rev-parse HEAD^) && 457 git show >output && 458 grep TWICE output >actual && 459 test_line_count = 2 actual && 460 git checkout @{-1} && 461 git branch -D conflict-squash 462' 463 464test_expect_success 'squash and fixup generate correct log messages' ' 465 cat >expect-squash-fixup <<-\EOF && 466 B 467 468 D 469 470 ONCE 471 EOF 472 git checkout -b squash-fixup E && 473 base=$(git rev-parse HEAD~4) && 474 ( 475 set_fake_editor && 476 FAKE_COMMIT_AMEND="ONCE" \ 477 FAKE_LINES="1 fixup 2 squash 3 fixup 4" \ 478 EXPECT_HEADER_COUNT=4 \ 479 git rebase -i $base 480 ) && 481 git cat-file commit HEAD | sed -e 1,/^\$/d > actual-squash-fixup && 482 test_cmp expect-squash-fixup actual-squash-fixup && 483 git cat-file commit HEAD@{2} >actual && 484 grep "^# This is a combination of 3 commits\." actual && 485 git cat-file commit HEAD@{3} >actual && 486 grep "^# This is a combination of 2 commits\." actual && 487 git checkout @{-1} && 488 git branch -D squash-fixup 489' 490 491test_expect_success 'squash ignores comments' ' 492 git checkout -b skip-comments E && 493 base=$(git rev-parse HEAD~4) && 494 ( 495 set_fake_editor && 496 FAKE_COMMIT_AMEND="ONCE" \ 497 FAKE_LINES="# 1 # squash 2 # squash 3 # squash 4 #" \ 498 EXPECT_HEADER_COUNT=4 \ 499 git rebase -i $base 500 ) && 501 test $base = $(git rev-parse HEAD^) && 502 git show >output && 503 grep ONCE output >actual && 504 test_line_count = 1 actual && 505 git checkout @{-1} && 506 git branch -D skip-comments 507' 508 509test_expect_success 'squash ignores blank lines' ' 510 git checkout -b skip-blank-lines E && 511 base=$(git rev-parse HEAD~4) && 512 ( 513 set_fake_editor && 514 FAKE_COMMIT_AMEND="ONCE" \ 515 FAKE_LINES="> 1 > squash 2 > squash 3 > squash 4 >" \ 516 EXPECT_HEADER_COUNT=4 \ 517 git rebase -i $base 518 ) && 519 test $base = $(git rev-parse HEAD^) && 520 git show >output && 521 grep ONCE output >actual && 522 test_line_count = 1 actual && 523 git checkout @{-1} && 524 git branch -D skip-blank-lines 525' 526 527test_expect_success 'squash works as expected' ' 528 git checkout -b squash-works no-conflict-branch && 529 one=$(git rev-parse HEAD~3) && 530 ( 531 set_fake_editor && 532 FAKE_LINES="1 s 3 2" EXPECT_HEADER_COUNT=2 git rebase -i HEAD~3 533 ) && 534 test $one = $(git rev-parse HEAD~2) 535' 536 537test_expect_success 'interrupted squash works as expected' ' 538 git checkout -b interrupted-squash conflict-branch && 539 one=$(git rev-parse HEAD~3) && 540 ( 541 set_fake_editor && 542 test_must_fail env FAKE_LINES="1 squash 3 2" \ 543 git rebase -i HEAD~3 544 ) && 545 test_write_lines one two four > conflict && 546 git add conflict && 547 test_must_fail git rebase --continue && 548 echo resolved > conflict && 549 git add conflict && 550 git rebase --continue && 551 test $one = $(git rev-parse HEAD~2) 552' 553 554test_expect_success 'interrupted squash works as expected (case 2)' ' 555 git checkout -b interrupted-squash2 conflict-branch && 556 one=$(git rev-parse HEAD~3) && 557 ( 558 set_fake_editor && 559 test_must_fail env FAKE_LINES="3 squash 1 2" \ 560 git rebase -i HEAD~3 561 ) && 562 test_write_lines one four > conflict && 563 git add conflict && 564 test_must_fail git rebase --continue && 565 test_write_lines one two four > conflict && 566 git add conflict && 567 test_must_fail git rebase --continue && 568 echo resolved > conflict && 569 git add conflict && 570 git rebase --continue && 571 test $one = $(git rev-parse HEAD~2) 572' 573 574test_expect_success '--continue tries to commit, even for "edit"' ' 575 echo unrelated > file7 && 576 git add file7 && 577 test_tick && 578 git commit -m "unrelated change" && 579 parent=$(git rev-parse HEAD^) && 580 test_tick && 581 ( 582 set_fake_editor && 583 FAKE_LINES="edit 1" git rebase -i HEAD^ && 584 echo edited > file7 && 585 git add file7 && 586 FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue 587 ) && 588 test edited = $(git show HEAD:file7) && 589 git show HEAD >actual && 590 grep chouette actual && 591 test $parent = $(git rev-parse HEAD^) 592' 593 594test_expect_success 'aborted --continue does not squash commits after "edit"' ' 595 old=$(git rev-parse HEAD) && 596 test_tick && 597 ( 598 set_fake_editor && 599 FAKE_LINES="edit 1" git rebase -i HEAD^ && 600 echo "edited again" > file7 && 601 git add file7 && 602 test_must_fail env FAKE_COMMIT_MESSAGE=" " git rebase --continue 603 ) && 604 test $old = $(git rev-parse HEAD) && 605 git rebase --abort 606' 607 608test_expect_success 'auto-amend only edited commits after "edit"' ' 609 test_tick && 610 ( 611 set_fake_editor && 612 FAKE_LINES="edit 1" git rebase -i HEAD^ && 613 echo "edited again" > file7 && 614 git add file7 && 615 FAKE_COMMIT_MESSAGE="edited file7 again" git commit && 616 echo "and again" > file7 && 617 git add file7 && 618 test_tick && 619 test_must_fail env FAKE_COMMIT_MESSAGE="and again" \ 620 git rebase --continue 621 ) && 622 git rebase --abort 623' 624 625test_expect_success 'clean error after failed "exec"' ' 626 test_tick && 627 test_when_finished "git rebase --abort || :" && 628 ( 629 set_fake_editor && 630 test_must_fail env FAKE_LINES="1 exec_false" git rebase -i HEAD^ 631 ) && 632 echo "edited again" > file7 && 633 git add file7 && 634 test_must_fail git rebase --continue 2>error && 635 test_grep "you have staged changes in your working tree" error && 636 test_grep ! "could not open.*for reading" error 637' 638 639test_expect_success 'rebase a detached HEAD' ' 640 grandparent=$(git rev-parse HEAD~2) && 641 git checkout $(git rev-parse HEAD) && 642 test_tick && 643 ( 644 set_fake_editor && 645 FAKE_LINES="2 1" git rebase -i HEAD~2 646 ) && 647 test $grandparent = $(git rev-parse HEAD~2) 648' 649 650test_expect_success 'rebase a commit violating pre-commit' ' 651 test_hook pre-commit <<-\EOF && 652 test -z "$(git diff --cached --check)" 653 EOF 654 echo "monde! " >> file1 && 655 test_tick && 656 test_must_fail git commit -m doesnt-verify file1 && 657 git commit -m doesnt-verify --no-verify file1 && 658 test_tick && 659 ( 660 set_fake_editor && 661 FAKE_LINES=2 git rebase -i HEAD~2 662 ) 663' 664 665test_expect_success 'rebase with a file named HEAD in worktree' ' 666 git reset --hard && 667 git checkout -b branch3 A && 668 669 ( 670 GIT_AUTHOR_NAME="Squashed Away" && 671 export GIT_AUTHOR_NAME && 672 >HEAD && 673 git add HEAD && 674 git commit -m "Add head" && 675 >BODY && 676 git add BODY && 677 git commit -m "Add body" 678 ) && 679 680 ( 681 set_fake_editor && 682 FAKE_LINES="1 squash 2" git rebase -i @{-1} 683 ) && 684 test "$(git show -s --pretty=format:%an)" = "Squashed Away" 685 686' 687 688test_expect_success 'do "noop" when there is nothing to cherry-pick' ' 689 690 git checkout -b branch4 HEAD && 691 GIT_EDITOR=: git commit --amend \ 692 --author="Somebody else <somebody@else.com>" && 693 test $(git rev-parse branch3) != $(git rev-parse branch4) && 694 git rebase -i branch3 && 695 test_cmp_rev branch3 branch4 696 697' 698 699test_expect_success 'submodule rebase setup' ' 700 git checkout A && 701 mkdir sub && 702 ( 703 cd sub && git init && >elif && 704 git add elif && git commit -m "submodule initial" 705 ) && 706 echo 1 >file1 && 707 git add file1 sub && 708 test_tick && 709 git commit -m "One" && 710 echo 2 >file1 && 711 test_tick && 712 git commit -a -m "Two" && 713 ( 714 cd sub && echo 3 >elif && 715 git commit -a -m "submodule second" 716 ) && 717 test_tick && 718 git commit -a -m "Three changes submodule" 719' 720 721test_expect_success 'submodule rebase -i' ' 722 ( 723 set_fake_editor && 724 FAKE_LINES="1 squash 2 3" git rebase -i A 725 ) 726' 727 728test_expect_success 'submodule conflict setup' ' 729 git tag submodule-base && 730 git checkout HEAD^ && 731 ( 732 cd sub && git checkout HEAD^ && echo 4 >elif && 733 git add elif && git commit -m "submodule conflict" 734 ) && 735 git add sub && 736 test_tick && 737 git commit -m "Conflict in submodule" && 738 git tag submodule-topic 739' 740 741test_expect_success 'rebase -i continue with only submodule staged' ' 742 test_must_fail git rebase -i submodule-base && 743 git add sub && 744 git rebase --continue && 745 test $(git rev-parse submodule-base) != $(git rev-parse HEAD) 746' 747 748test_expect_success 'rebase -i continue with unstaged submodule' ' 749 git checkout submodule-topic && 750 git reset --hard && 751 test_must_fail git rebase -i submodule-base && 752 git reset && 753 git rebase --continue && 754 test_cmp_rev submodule-base HEAD 755' 756 757test_expect_success 'avoid unnecessary reset' ' 758 git checkout primary && 759 git reset --hard && 760 test-tool chmtime =123456789 file3 && 761 git update-index --refresh && 762 HEAD=$(git rev-parse HEAD) && 763 git rebase -i HEAD~4 && 764 test $HEAD = $(git rev-parse HEAD) && 765 MTIME=$(test-tool chmtime --get file3) && 766 test 123456789 = $MTIME 767' 768 769test_expect_success 'reword' ' 770 git checkout -b reword-branch primary && 771 ( 772 set_fake_editor && 773 FAKE_LINES="1 2 3 reword 4" FAKE_COMMIT_MESSAGE="E changed" \ 774 git rebase -i A && 775 git show HEAD >actual && 776 grep "E changed" actual && 777 test $(git rev-parse primary) != $(git rev-parse HEAD) && 778 test_cmp_rev primary^ HEAD^ && 779 FAKE_LINES="1 2 reword 3 4" FAKE_COMMIT_MESSAGE="D changed" \ 780 git rebase -i A && 781 git show HEAD^ >actual && 782 grep "D changed" actual && 783 FAKE_LINES="reword 1 2 3 4" FAKE_COMMIT_MESSAGE="B changed" \ 784 git rebase -i A && 785 git show HEAD~3 >actual && 786 grep "B changed" actual && 787 FAKE_LINES="1 r 2 pick 3 p 4" FAKE_COMMIT_MESSAGE="C changed" \ 788 git rebase -i A 789 ) && 790 git show HEAD~2 >actual && 791 grep "C changed" actual 792' 793 794test_expect_success 'reword fast-forwarded empty commit' ' 795 git commit --allow-empty -m "empty commit" --only && 796 ( 797 set_fake_editor && 798 FAKE_COMMIT_AMEND=edited FAKE_LINES="reword 1" \ 799 git rebase -i HEAD^ 800 ) && 801 test_commit_message HEAD <<-\EOF 802 empty commit 803 804 edited 805 EOF 806' 807 808test_expect_success 'no uncommitted changes when rewording and the todo list is reloaded' ' 809 git checkout E && 810 test_when_finished "git checkout @{-1}" && 811 ( 812 set_fake_editor && 813 GIT_SEQUENCE_EDITOR="\"$PWD/fake-editor.sh\"" && 814 export GIT_SEQUENCE_EDITOR && 815 set_reword_editor && 816 FAKE_LINES="reword 1 reword 2" git rebase -i C 817 ) && 818 check_reworded_commits D E 819' 820 821test_expect_success 'rebase -i can copy notes' ' 822 git config notes.rewrite.rebase true && 823 git config notes.rewriteRef "refs/notes/*" && 824 test_commit n1 && 825 test_commit n2 && 826 test_commit n3 && 827 git notes add -m"a note" n3 && 828 git rebase -i --onto n1 n2 && 829 test "a note" = "$(git notes show HEAD)" 830' 831 832test_expect_success 'rebase -i can copy notes over a fixup' ' 833 cat >expect <<-\EOF && 834 an earlier note 835 836 a note 837 EOF 838 git reset --hard n3 && 839 git notes add -m"an earlier note" n2 && 840 ( 841 set_fake_editor && 842 GIT_NOTES_REWRITE_MODE=concatenate FAKE_LINES="1 f 2" \ 843 git rebase -i n1 844 ) && 845 git notes show > output && 846 test_cmp expect output 847' 848 849test_expect_success 'rebase while detaching HEAD' ' 850 git symbolic-ref HEAD && 851 grandparent=$(git rev-parse HEAD~2) && 852 test_tick && 853 ( 854 set_fake_editor && 855 FAKE_LINES="2 1" git rebase -i HEAD~2 HEAD^0 856 ) && 857 test $grandparent = $(git rev-parse HEAD~2) && 858 test_must_fail git symbolic-ref HEAD 859' 860 861test_tick # Ensure that the rebased commits get a different timestamp. 862test_expect_success 'always cherry-pick with --no-ff' ' 863 git checkout no-ff-branch && 864 git tag original-no-ff-branch && 865 git rebase -i --no-ff A && 866 for p in 0 1 2 867 do 868 test ! $(git rev-parse HEAD~$p) = $(git rev-parse original-no-ff-branch~$p) && 869 git diff HEAD~$p original-no-ff-branch~$p > out && 870 test_must_be_empty out || return 1 871 done && 872 test_cmp_rev HEAD~3 original-no-ff-branch~3 && 873 git diff HEAD~3 original-no-ff-branch~3 > out && 874 test_must_be_empty out 875' 876 877test_expect_success 'set up commits with funny messages' ' 878 git checkout -b funny A && 879 echo >>file1 && 880 test_tick && 881 git commit -a -m "end with slash\\" && 882 echo >>file1 && 883 test_tick && 884 git commit -a -m "something (\000) that looks like octal" && 885 echo >>file1 && 886 test_tick && 887 git commit -a -m "something (\n) that looks like a newline" && 888 echo >>file1 && 889 test_tick && 890 git commit -a -m "another commit" 891' 892 893test_expect_success 'rebase-i history with funny messages' ' 894 git rev-list A..funny >expect && 895 test_tick && 896 ( 897 set_fake_editor && 898 FAKE_LINES="1 2 3 4" git rebase -i A 899 ) && 900 git rev-list A.. >actual && 901 test_cmp expect actual 902' 903 904test_expect_success 'prepare for rebase -i --exec' ' 905 git checkout primary && 906 git checkout -b execute && 907 test_commit one_exec main.txt one_exec && 908 test_commit two_exec main.txt two_exec && 909 test_commit three_exec main.txt three_exec 910' 911 912test_expect_success 'running "git rebase -i --exec git show HEAD"' ' 913 ( 914 set_fake_editor && 915 git rebase -i --exec "git show HEAD" HEAD~2 >actual && 916 FAKE_LINES="1 exec_git_show_HEAD 2 exec_git_show_HEAD" && 917 export FAKE_LINES && 918 git rebase -i HEAD~2 >expect 919 ) && 920 sed -e "1,9d" expect >expected && 921 test_cmp expected actual 922' 923 924test_expect_success 'running "git rebase --exec git show HEAD -i"' ' 925 git reset --hard execute && 926 ( 927 set_fake_editor && 928 git rebase --exec "git show HEAD" -i HEAD~2 >actual && 929 FAKE_LINES="1 exec_git_show_HEAD 2 exec_git_show_HEAD" && 930 export FAKE_LINES && 931 git rebase -i HEAD~2 >expect 932 ) && 933 sed -e "1,9d" expect >expected && 934 test_cmp expected actual 935' 936 937test_expect_success 'running "git rebase -ix git show HEAD"' ' 938 git reset --hard execute && 939 ( 940 set_fake_editor && 941 git rebase -ix "git show HEAD" HEAD~2 >actual && 942 FAKE_LINES="1 exec_git_show_HEAD 2 exec_git_show_HEAD" && 943 export FAKE_LINES && 944 git rebase -i HEAD~2 >expect 945 ) && 946 sed -e "1,9d" expect >expected && 947 test_cmp expected actual 948' 949 950 951test_expect_success 'rebase -ix with several <CMD>' ' 952 git reset --hard execute && 953 ( 954 set_fake_editor && 955 git rebase -ix "git show HEAD; pwd" HEAD~2 >actual && 956 FAKE_LINES="1 exec_git_show_HEAD;_pwd 2 exec_git_show_HEAD;_pwd" && 957 export FAKE_LINES && 958 git rebase -i HEAD~2 >expect 959 ) && 960 sed -e "1,9d" expect >expected && 961 test_cmp expected actual 962' 963 964test_expect_success 'rebase -ix with several instances of --exec' ' 965 git reset --hard execute && 966 ( 967 set_fake_editor && 968 git rebase -i --exec "git show HEAD" --exec "pwd" HEAD~2 >actual && 969 FAKE_LINES="1 exec_git_show_HEAD exec_pwd 2 970 exec_git_show_HEAD exec_pwd" && 971 export FAKE_LINES && 972 git rebase -i HEAD~2 >expect 973 ) && 974 sed -e "1,11d" expect >expected && 975 test_cmp expected actual 976' 977 978test_expect_success 'rebase -ix with --autosquash' ' 979 git reset --hard execute && 980 git checkout -b autosquash && 981 echo second >second.txt && 982 git add second.txt && 983 git commit -m "fixup! two_exec" && 984 echo bis >bis.txt && 985 git add bis.txt && 986 git commit -m "fixup! two_exec" && 987 git checkout -b autosquash_actual && 988 git rebase -i --exec "git show HEAD" --autosquash HEAD~4 >actual && 989 git checkout autosquash && 990 ( 991 set_fake_editor && 992 git checkout -b autosquash_expected && 993 FAKE_LINES="1 fixup 3 fixup 4 exec_git_show_HEAD 2 exec_git_show_HEAD" && 994 export FAKE_LINES && 995 git rebase -i HEAD~4 >expect 996 ) && 997 sed -e "1,13d" expect >expected && 998 test_cmp expected actual 999' 1000 1001test_expect_success 'rebase --exec works without -i ' ' 1002 git reset --hard execute && 1003 rm -rf exec_output && 1004 EDITOR="echo >invoked_editor" git rebase --exec "echo a line >>exec_output" HEAD~2 2>actual && 1005 test_grep "Successfully rebased and updated" actual && 1006 test_line_count = 2 exec_output && 1007 test_path_is_missing invoked_editor 1008' 1009 1010test_expect_success 'rebase -i --exec without <CMD>' ' 1011 git reset --hard execute && 1012 test_must_fail git rebase -i --exec 2>actual && 1013 test_grep "requires a value" actual && 1014 git checkout primary 1015' 1016 1017test_expect_success 'rebase -i --root re-order and drop commits' ' 1018 git checkout E && 1019 ( 1020 set_fake_editor && 1021 FAKE_LINES="3 1 2 5" git rebase -i --root 1022 ) && 1023 test E = $(git cat-file commit HEAD | sed -ne \$p) && 1024 test B = $(git cat-file commit HEAD^ | sed -ne \$p) && 1025 test A = $(git cat-file commit HEAD^^ | sed -ne \$p) && 1026 test C = $(git cat-file commit HEAD^^^ | sed -ne \$p) && 1027 test 0 = $(git cat-file commit HEAD^^^ | grep -c ^parent\ ) 1028' 1029 1030test_expect_success 'rebase -i --root retain root commit author and message' ' 1031 git checkout A && 1032 echo B >file7 && 1033 git add file7 && 1034 GIT_AUTHOR_NAME="Twerp Snog" git commit -m "different author" && 1035 ( 1036 set_fake_editor && 1037 FAKE_LINES="2" git rebase -i --root 1038 ) && 1039 git cat-file commit HEAD >output && 1040 grep -q "^author Twerp Snog" output && 1041 git cat-file commit HEAD >actual && 1042 grep -q "^different author$" actual 1043' 1044 1045test_expect_success 'rebase -i --root temporary sentinel commit' ' 1046 git checkout B && 1047 ( 1048 set_fake_editor && 1049 test_must_fail env FAKE_LINES="2" git rebase -i --root 1050 ) && 1051 git cat-file commit HEAD >actual && 1052 grep "^tree $EMPTY_TREE" actual && 1053 git rebase --abort 1054' 1055 1056test_expect_success 'rebase -i --root fixup root commit' ' 1057 git checkout B && 1058 ( 1059 set_fake_editor && 1060 FAKE_LINES="1 fixup 2" git rebase -i --root 1061 ) && 1062 test A = $(git cat-file commit HEAD | sed -ne \$p) && 1063 test B = $(git show HEAD:file1) && 1064 test 0 = $(git cat-file commit HEAD | grep -c ^parent\ ) 1065' 1066 1067test_expect_success 'rebase -i --root reword original root commit' ' 1068 test_when_finished "test_might_fail git rebase --abort" && 1069 git checkout -b reword-original-root-branch primary && 1070 ( 1071 set_fake_editor && 1072 FAKE_LINES="reword 1 2" FAKE_COMMIT_MESSAGE="A changed" \ 1073 git rebase -i --root 1074 ) && 1075 git show HEAD^ >actual && 1076 grep "A changed" actual && 1077 test -z "$(git show -s --format=%p HEAD^)" 1078' 1079 1080test_expect_success 'rebase -i --root reword new root commit' ' 1081 test_when_finished "test_might_fail git rebase --abort" && 1082 git checkout -b reword-now-root-branch primary && 1083 ( 1084 set_fake_editor && 1085 FAKE_LINES="reword 3 1" FAKE_COMMIT_MESSAGE="C changed" \ 1086 git rebase -i --root 1087 ) && 1088 git show HEAD^ >actual && 1089 grep "C changed" actual && 1090 test -z "$(git show -s --format=%p HEAD^)" 1091' 1092 1093test_expect_success 'rebase -i --root when root has untracked file conflict' ' 1094 test_when_finished "reset_rebase" && 1095 git checkout -b failing-root-pick A && 1096 echo x >file2 && 1097 git rm file1 && 1098 git commit -m "remove file 1 add file 2" && 1099 echo z >file1 && 1100 ( 1101 set_fake_editor && 1102 test_must_fail env FAKE_LINES="1 2" git rebase -i --root 1103 ) && 1104 rm file1 && 1105 git rebase --continue && 1106 test "$(git log -1 --format=%B)" = "remove file 1 add file 2" && 1107 test "$(git rev-list --count HEAD)" = 2 1108' 1109 1110test_expect_success 'rebase -i --root reword root when root has untracked file conflict' ' 1111 test_when_finished "reset_rebase" && 1112 echo z>file1 && 1113 ( 1114 set_fake_editor && 1115 test_must_fail env FAKE_LINES="reword 1 2" \ 1116 FAKE_COMMIT_MESSAGE="Modified A" git rebase -i --root && 1117 rm file1 && 1118 FAKE_COMMIT_MESSAGE="Reworded A" git rebase --continue 1119 ) && 1120 test "$(git log -1 --format=%B HEAD^)" = "Reworded A" && 1121 test "$(git rev-list --count HEAD)" = 2 1122' 1123 1124test_expect_success 'rebase --edit-todo does not work on non-interactive rebase' ' 1125 git checkout reword-original-root-branch && 1126 git reset --hard && 1127 git checkout conflict-branch && 1128 ( 1129 set_fake_editor && 1130 test_must_fail git rebase -f --apply --onto HEAD~2 HEAD~ && 1131 test_must_fail git rebase --edit-todo 1132 ) && 1133 git rebase --abort 1134' 1135 1136test_expect_success 'rebase --edit-todo can be used to modify todo' ' 1137 git reset --hard && 1138 git checkout no-conflict-branch^0 && 1139 ( 1140 set_fake_editor && 1141 FAKE_LINES="edit 1 2 3" git rebase -i HEAD~3 && 1142 FAKE_LINES="2 1" git rebase --edit-todo && 1143 git rebase --continue 1144 ) && 1145 test M = $(git cat-file commit HEAD^ | sed -ne \$p) && 1146 test L = $(git cat-file commit HEAD | sed -ne \$p) 1147' 1148 1149test_expect_success 'rebase -i produces readable reflog' ' 1150 git reset --hard && 1151 git branch -f branch-reflog-test H && 1152 git rebase -i --onto I F branch-reflog-test && 1153 cat >expect <<-\EOF && 1154 rebase (finish): returning to refs/heads/branch-reflog-test 1155 rebase (pick): H 1156 rebase (pick): G 1157 rebase (start): checkout I 1158 EOF 1159 git reflog -n4 HEAD | 1160 sed "s/[^:]*: //" >actual && 1161 test_cmp expect actual 1162' 1163 1164test_expect_success 'rebase -i respects core.commentchar' ' 1165 git reset --hard && 1166 git checkout E^0 && 1167 test_config core.commentchar "\\" && 1168 write_script remove-all-but-first.sh <<-\EOF && 1169 sed -e "2,\$s/^/\\\\/" "$1" >"$1.tmp" && 1170 mv "$1.tmp" "$1" 1171 EOF 1172 ( 1173 test_set_editor "$(pwd)/remove-all-but-first.sh" && 1174 git rebase -i B 1175 ) && 1176 test B = $(git cat-file commit HEAD^ | sed -ne \$p) 1177' 1178 1179test_expect_success !WITH_BREAKING_CHANGES 'rebase -i respects core.commentchar=auto' ' 1180 test_config core.commentchar auto && 1181 write_script copy-edit-script.sh <<-\EOF && 1182 cp "$1" edit-script 1183 EOF 1184 test_when_finished "git rebase --abort || :" && 1185 ( 1186 test_set_editor "$(pwd)/copy-edit-script.sh" && 1187 git rebase -i HEAD^ 2>err 1188 ) && 1189 sed -n "s/^hint: *\$//p; s/^hint: //p; s/^warning: //p" err >actual && 1190 cat >expect <<-EOF && 1191 Support for ${SQ}core.commentChar=auto${SQ} is deprecated and will be removed in Git 3.0 1192 1193 To use the default comment string (#) please run 1194 1195 git config unset core.commentChar 1196 1197 To set a custom comment string please run 1198 1199 git config set core.commentChar <comment string> 1200 1201 where ${SQ}<comment string>${SQ} is the string you wish to use. 1202 EOF 1203 test_cmp expect actual && 1204 test -z "$(grep -ve "^#" -e "^\$" -e "^pick" edit-script)" 1205' 1206 1207test_expect_success 'rebase -i, with <onto> and <upstream> specified as :/quuxery' ' 1208 test_when_finished "git branch -D torebase" && 1209 git checkout -b torebase branch1 && 1210 upstream=$(git rev-parse ":/J") && 1211 onto=$(git rev-parse ":/A") && 1212 git rebase --onto $onto $upstream && 1213 git reset --hard branch1 && 1214 git rebase --onto ":/A" ":/J" && 1215 git checkout branch1 1216' 1217 1218test_expect_success 'rebase -i with --strategy and -X' ' 1219 git checkout -b conflict-merge-use-theirs conflict-branch && 1220 git reset --hard HEAD^ && 1221 echo five >conflict && 1222 echo Z >file1 && 1223 git commit -a -m "one file conflict" && 1224 EDITOR=true git rebase -i --strategy=recursive -Xours conflict-branch && 1225 test $(git show conflict-branch:conflict) = $(cat conflict) && 1226 test $(cat file1) = Z 1227' 1228 1229test_expect_success 'interrupted rebase -i with --strategy and -X' ' 1230 git checkout -b conflict-merge-use-theirs-interrupted conflict-branch && 1231 git reset --hard HEAD^ && 1232 >breakpoint && 1233 git add breakpoint && 1234 git commit -m "breakpoint for interactive mode" && 1235 echo five >conflict && 1236 echo Z >file1 && 1237 git commit -a -m "one file conflict" && 1238 ( 1239 set_fake_editor && 1240 FAKE_LINES="edit 1 2" git rebase -i --strategy=recursive \ 1241 -Xours conflict-branch 1242 ) && 1243 git rebase --continue && 1244 test $(git show conflict-branch:conflict) = $(cat conflict) && 1245 test $(cat file1) = Z 1246' 1247 1248test_expect_success 'rebase -i error on commits with \ in message' ' 1249 current_head=$(git rev-parse HEAD) && 1250 test_when_finished "git rebase --abort; git reset --hard $current_head; rm -f error" && 1251 test_commit TO-REMOVE will-conflict old-content && 1252 test_commit "\temp" will-conflict new-content dummy && 1253 test_must_fail env EDITOR=true git rebase -i HEAD^ --onto HEAD^^ 2>error && 1254 test_expect_code 1 grep " emp" error 1255' 1256 1257test_expect_success 'short commit ID setup' ' 1258 test_when_finished "git checkout primary" && 1259 git checkout --orphan collide && 1260 git rm -rf . && 1261 ( 1262 unset test_tick && 1263 test_commit collide1 collide && 1264 test_commit --notick collide2 collide && 1265 test_commit --notick collide3 collide 1266 ) 1267' 1268 1269if test -n "$GIT_TEST_FIND_COLLIDER" 1270then 1271 author="$(unset test_tick; test_tick; git var GIT_AUTHOR_IDENT)" 1272 committer="$(unset test_tick; test_tick; git var GIT_COMMITTER_IDENT)" 1273 blob="$(git rev-parse collide2:collide)" 1274 from="$(git rev-parse collide1^0)" 1275 repl="commit refs/heads/collider-&\\n" 1276 repl="${repl}author $author\\ncommitter $committer\\n" 1277 repl="${repl}data <<EOF\\ncollide2 &\\nEOF\\n" 1278 repl="${repl}from $from\\nM 100644 $blob collide\\n" 1279 test_seq 1 32768 | sed "s|.*|$repl|" >script && 1280 git fast-import <script && 1281 git pack-refs && 1282 git for-each-ref >refs && 1283 grep "^$(test_oid t3404_collision)" <refs >matches && 1284 cat matches && 1285 test_line_count -gt 2 matches || { 1286 echo "Could not find a collider" >&2 1287 exit 1 1288 } 1289fi 1290 1291test_expect_success 'short commit ID collide' ' 1292 test_oid_cache <<-EOF && 1293 # collision-related constants 1294 t3404_collision sha1:6bcd 1295 t3404_collision sha256:0161 1296 t3404_collider sha1:ac4f2ee 1297 t3404_collider sha256:16697 1298 EOF 1299 test_when_finished "reset_rebase && git checkout primary" && 1300 git checkout collide && 1301 colliding_id=$(test_oid t3404_collision) && 1302 hexsz=$(test_oid hexsz) && 1303 test $colliding_id = "$(git rev-parse HEAD | cut -c 1-4)" && 1304 test_config core.abbrev 4 && 1305 ( 1306 unset test_tick && 1307 test_tick && 1308 set_fake_editor && 1309 FAKE_COMMIT_MESSAGE="collide2 $(test_oid t3404_collider)" \ 1310 FAKE_LINES="reword 1 break 2" git rebase -i HEAD~2 && 1311 test $colliding_id = "$(git rev-parse HEAD | cut -c 1-4)" && 1312 grep "^pick $colliding_id " \ 1313 .git/rebase-merge/git-rebase-todo.tmp && 1314 grep -E "^pick [0-9a-f]{$hexsz}" \ 1315 .git/rebase-merge/git-rebase-todo && 1316 grep -E "^pick [0-9a-f]{$hexsz}" \ 1317 .git/rebase-merge/git-rebase-todo.backup && 1318 git rebase --continue 1319 ) && 1320 collide2="$(git rev-parse HEAD~1 | cut -c 1-4)" && 1321 collide3="$(git rev-parse collide3 | cut -c 1-4)" && 1322 test "$collide2" = "$collide3" 1323' 1324 1325test_expect_success 'respect core.abbrev' ' 1326 git config core.abbrev 12 && 1327 ( 1328 set_cat_todo_editor && 1329 test_must_fail git rebase -i HEAD~4 >todo-list 1330 ) && 1331 test 4 = $(grep -c -E "pick [0-9a-f]{12,}" todo-list) 1332' 1333 1334test_expect_success 'todo count' ' 1335 write_script dump-raw.sh <<-\EOF && 1336 cat "$1" 1337 EOF 1338 ( 1339 test_set_editor "$(pwd)/dump-raw.sh" && 1340 git rebase -i HEAD~4 >actual 1341 ) && 1342 test_grep "^# Rebase ..* onto ..* ([0-9]" actual 1343' 1344 1345test_expect_success 'rebase -i commits that overwrite untracked files (pick)' ' 1346 git checkout --force A && 1347 git clean -f && 1348 cat >todo <<-EOF && 1349 exec >file2 1350 pick $(git rev-parse B) B 1351 pick $(git rev-parse C) C 1352 pick $(git rev-parse D) D 1353 exec cat .git/rebase-merge/done >actual 1354 EOF 1355 ( 1356 set_replace_editor todo && 1357 test_must_fail git rebase -i A 1358 ) && 1359 test_cmp_rev HEAD B && 1360 test_cmp_rev REBASE_HEAD C && 1361 head -n3 todo >expect && 1362 test_cmp expect .git/rebase-merge/done && 1363 rm file2 && 1364 test_path_is_missing .git/rebase-merge/patch && 1365 echo changed >file1 && 1366 git add file1 && 1367 test_must_fail git rebase --continue 2>err && 1368 grep "error: you have staged changes in your working tree" err && 1369 git reset --hard HEAD && 1370 git rebase --continue && 1371 test_cmp_rev HEAD D && 1372 tail -n3 todo >>expect && 1373 test_cmp expect actual 1374' 1375 1376test_expect_success 'rebase -i commits that overwrite untracked files (squash)' ' 1377 git checkout --force branch2 && 1378 git clean -f && 1379 git tag original-branch2 && 1380 ( 1381 set_fake_editor && 1382 FAKE_LINES="edit 1 squash 2" git rebase -i A 1383 ) && 1384 test_cmp_rev HEAD F && 1385 test_path_is_missing file6 && 1386 >file6 && 1387 test_must_fail git rebase --continue && 1388 test_cmp_rev HEAD F && 1389 test_cmp_rev REBASE_HEAD I && 1390 rm file6 && 1391 test_path_is_missing .git/rebase-merge/patch && 1392 echo changed >file1 && 1393 git add file1 && 1394 test_must_fail git rebase --continue 2>err && 1395 grep "error: you have staged changes in your working tree" err && 1396 git reset --hard HEAD && 1397 git rebase --continue && 1398 test $(git cat-file commit HEAD | sed -ne \$p) = I && 1399 git reset --hard original-branch2 1400' 1401 1402test_expect_success 'rebase -i commits that overwrite untracked files (no ff)' ' 1403 git checkout --force branch2 && 1404 git clean -f && 1405 ( 1406 set_fake_editor && 1407 FAKE_LINES="edit 1 2" git rebase -i --no-ff A 1408 ) && 1409 test $(git cat-file commit HEAD | sed -ne \$p) = F && 1410 test_path_is_missing file6 && 1411 >file6 && 1412 test_must_fail git rebase --continue && 1413 test $(git cat-file commit HEAD | sed -ne \$p) = F && 1414 test_cmp_rev REBASE_HEAD I && 1415 rm file6 && 1416 test_path_is_missing .git/rebase-merge/patch && 1417 echo changed >file1 && 1418 git add file1 && 1419 test_must_fail git rebase --continue 2>err && 1420 grep "error: you have staged changes in your working tree" err && 1421 git reset --hard HEAD && 1422 git rebase --continue && 1423 test $(git cat-file commit HEAD | sed -ne \$p) = I 1424' 1425 1426test_expect_success 'rebase --continue removes CHERRY_PICK_HEAD' ' 1427 git checkout -b commit-to-skip && 1428 for double in X 3 1 1429 do 1430 test_seq 5 | sed "s/$double/&&/" >seq && 1431 git add seq && 1432 test_tick && 1433 git commit -m seq-$double || return 1 1434 done && 1435 git tag seq-onto && 1436 git reset --hard HEAD~2 && 1437 git cherry-pick seq-onto && 1438 ( 1439 set_fake_editor && 1440 test_must_fail env FAKE_LINES= git rebase -i seq-onto 1441 ) && 1442 test -d .git/rebase-merge && 1443 git rebase --continue && 1444 git diff --exit-code seq-onto && 1445 test ! -d .git/rebase-merge && 1446 test ! -f .git/CHERRY_PICK_HEAD 1447' 1448 1449rebase_setup_and_clean () { 1450 test_when_finished " 1451 git checkout primary && 1452 test_might_fail git branch -D $1 && 1453 test_might_fail git rebase --abort 1454 " && 1455 git checkout -b $1 ${2:-primary} 1456} 1457 1458test_expect_success 'drop' ' 1459 rebase_setup_and_clean drop-test && 1460 ( 1461 set_fake_editor && 1462 FAKE_LINES="1 drop 2 3 d 4 5" git rebase -i --root 1463 ) && 1464 test E = $(git cat-file commit HEAD | sed -ne \$p) && 1465 test C = $(git cat-file commit HEAD^ | sed -ne \$p) && 1466 test A = $(git cat-file commit HEAD^^ | sed -ne \$p) 1467' 1468 1469test_expect_success 'rebase -i respects rebase.missingCommitsCheck = ignore' ' 1470 test_config rebase.missingCommitsCheck ignore && 1471 rebase_setup_and_clean missing-commit && 1472 ( 1473 set_fake_editor && 1474 FAKE_LINES="1 2 3 4" git rebase -i --root 2>actual 1475 ) && 1476 test D = $(git cat-file commit HEAD | sed -ne \$p) && 1477 test_grep \ 1478 "Successfully rebased and updated refs/heads/missing-commit" \ 1479 actual 1480' 1481 1482test_expect_success 'rebase -i respects rebase.missingCommitsCheck = warn' ' 1483 cat >expect <<-EOF && 1484 Warning: some commits may have been dropped accidentally. 1485 Dropped commits (newer to older): 1486 - $(git log --format="%h # %s" -1 primary) 1487 To avoid this message, use "drop" to explicitly remove a commit. 1488 EOF 1489 test_config rebase.missingCommitsCheck warn && 1490 rebase_setup_and_clean missing-commit && 1491 ( 1492 set_fake_editor && 1493 FAKE_LINES="1 2 3 4" git rebase -i --root 2>actual.2 1494 ) && 1495 head -n4 actual.2 >actual && 1496 test_cmp expect actual && 1497 test D = $(git cat-file commit HEAD | sed -ne \$p) 1498' 1499 1500test_expect_success 'rebase -i respects rebase.missingCommitsCheck = error' ' 1501 cat >expect <<-EOF && 1502 Warning: some commits may have been dropped accidentally. 1503 Dropped commits (newer to older): 1504 - $(git log --format="%h # %s" -1 primary) 1505 - $(git log --format="%h # %s" -1 primary~2) 1506 To avoid this message, use "drop" to explicitly remove a commit. 1507 1508 Use '\''git config rebase.missingCommitsCheck'\'' to change the level of warnings. 1509 The possible behaviours are: ignore, warn, error. 1510 1511 You can fix this with '\''git rebase --edit-todo'\'' and then run '\''git rebase --continue'\''. 1512 Or you can abort the rebase with '\''git rebase --abort'\''. 1513 EOF 1514 test_config rebase.missingCommitsCheck error && 1515 rebase_setup_and_clean missing-commit && 1516 ( 1517 set_fake_editor && 1518 test_must_fail env FAKE_LINES="1 2 4" \ 1519 git rebase -i --root 2>actual && 1520 test_cmp expect actual && 1521 cp .git/rebase-merge/git-rebase-todo.backup \ 1522 .git/rebase-merge/git-rebase-todo && 1523 FAKE_LINES="1 2 drop 3 4 drop 5" git rebase --edit-todo 1524 ) && 1525 git rebase --continue && 1526 test D = $(git cat-file commit HEAD | sed -ne \$p) && 1527 test B = $(git cat-file commit HEAD^ | sed -ne \$p) 1528' 1529 1530test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = ignore' ' 1531 test_config rebase.missingCommitsCheck ignore && 1532 rebase_setup_and_clean missing-commit && 1533 ( 1534 set_fake_editor && 1535 FAKE_LINES="break 1 2 3 4 5" git rebase -i --root && 1536 FAKE_LINES="1 2 3 4" git rebase --edit-todo && 1537 git rebase --continue 2>actual 1538 ) && 1539 test D = $(git cat-file commit HEAD | sed -ne \$p) && 1540 test_grep \ 1541 "Successfully rebased and updated refs/heads/missing-commit" \ 1542 actual 1543' 1544 1545test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = warn' ' 1546 cat >expect <<-EOF && 1547 error: invalid command '\''pickled'\'' 1548 error: invalid line 1: pickled $(git log --format="%h # %s" -1 primary~4) 1549 Warning: some commits may have been dropped accidentally. 1550 Dropped commits (newer to older): 1551 - $(git log --format="%h # %s" -1 primary) 1552 - $(git log --format="%h # %s" -1 primary~4) 1553 To avoid this message, use "drop" to explicitly remove a commit. 1554 EOF 1555 head -n5 expect >expect.2 && 1556 tail -n1 expect >>expect.2 && 1557 tail -n4 expect.2 >expect.3 && 1558 test_config rebase.missingCommitsCheck warn && 1559 rebase_setup_and_clean missing-commit && 1560 ( 1561 set_fake_editor && 1562 test_must_fail env FAKE_LINES="bad 1 2 3 4 5" \ 1563 git rebase -i --root && 1564 cp .git/rebase-merge/git-rebase-todo.backup orig && 1565 FAKE_LINES="2 3 4" git rebase --edit-todo 2>actual.2 && 1566 head -n7 actual.2 >actual && 1567 test_cmp expect actual && 1568 cp orig .git/rebase-merge/git-rebase-todo && 1569 FAKE_LINES="1 2 3 4" git rebase --edit-todo 2>actual.2 && 1570 head -n4 actual.2 >actual && 1571 test_cmp expect.3 actual && 1572 git rebase --continue 2>actual 1573 ) && 1574 test D = $(git cat-file commit HEAD | sed -ne \$p) && 1575 test_grep \ 1576 "Successfully rebased and updated refs/heads/missing-commit" \ 1577 actual 1578' 1579 1580test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = error' ' 1581 cat >expect <<-EOF && 1582 error: invalid command '\''pickled'\'' 1583 error: invalid line 1: pickled $(git log --format="%h # %s" -1 primary~4) 1584 Warning: some commits may have been dropped accidentally. 1585 Dropped commits (newer to older): 1586 - $(git log --format="%h # %s" -1 primary) 1587 - $(git log --format="%h # %s" -1 primary~4) 1588 To avoid this message, use "drop" to explicitly remove a commit. 1589 1590 Use '\''git config rebase.missingCommitsCheck'\'' to change the level of warnings. 1591 The possible behaviours are: ignore, warn, error. 1592 1593 You can fix this with '\''git rebase --edit-todo'\'' and then run '\''git rebase --continue'\''. 1594 Or you can abort the rebase with '\''git rebase --abort'\''. 1595 EOF 1596 tail -n11 expect >expect.2 && 1597 head -n3 expect.2 >expect.3 && 1598 tail -n7 expect.2 >>expect.3 && 1599 test_config rebase.missingCommitsCheck error && 1600 rebase_setup_and_clean missing-commit && 1601 ( 1602 set_fake_editor && 1603 test_must_fail env FAKE_LINES="bad 1 2 3 4 5" \ 1604 git rebase -i --root && 1605 cp .git/rebase-merge/git-rebase-todo.backup orig && 1606 test_must_fail env FAKE_LINES="2 3 4" \ 1607 git rebase --edit-todo 2>actual && 1608 test_cmp expect actual && 1609 test_must_fail git rebase --continue 2>actual && 1610 test_cmp expect.2 actual && 1611 test_must_fail git rebase --edit-todo && 1612 cp orig .git/rebase-merge/git-rebase-todo && 1613 test_must_fail env FAKE_LINES="1 2 3 4" \ 1614 git rebase --edit-todo 2>actual && 1615 test_cmp expect.3 actual && 1616 test_must_fail git rebase --continue 2>actual && 1617 test_cmp expect.3 actual && 1618 cp orig .git/rebase-merge/git-rebase-todo && 1619 FAKE_LINES="1 2 3 4 drop 5" git rebase --edit-todo && 1620 git rebase --continue 2>actual 1621 ) && 1622 test D = $(git cat-file commit HEAD | sed -ne \$p) && 1623 test_grep \ 1624 "Successfully rebased and updated refs/heads/missing-commit" \ 1625 actual 1626' 1627 1628test_expect_success 'rebase.missingCommitsCheck = error after resolving conflicts' ' 1629 test_config rebase.missingCommitsCheck error && 1630 ( 1631 set_fake_editor && 1632 FAKE_LINES="drop 1 break 2 3 4" git rebase -i A E 1633 ) && 1634 git rebase --edit-todo && 1635 test_must_fail git rebase --continue && 1636 echo x >file1 && 1637 git add file1 && 1638 git rebase --continue 1639' 1640 1641test_expect_success 'rebase.missingCommitsCheck = error when editing for a second time' ' 1642 test_config rebase.missingCommitsCheck error && 1643 ( 1644 set_fake_editor && 1645 FAKE_LINES="1 break 2 3" git rebase -i A D && 1646 cp .git/rebase-merge/git-rebase-todo todo && 1647 test_must_fail env FAKE_LINES=2 git rebase --edit-todo && 1648 GIT_SEQUENCE_EDITOR="cp todo" git rebase --edit-todo && 1649 git rebase --continue 1650 ) 1651' 1652 1653test_expect_success 'respects rebase.abbreviateCommands with fixup, squash and exec' ' 1654 rebase_setup_and_clean abbrevcmd && 1655 test_commit "first" file1.txt "first line" first && 1656 test_commit "second" file1.txt "another line" second && 1657 test_commit "fixup! first" file2.txt "first line again" first_fixup && 1658 test_commit "squash! second" file1.txt "another line here" second_squash && 1659 cat >expected <<-EOF && 1660 p $(git rev-list --abbrev-commit -1 first) # first 1661 f $(git rev-list --abbrev-commit -1 first_fixup) # fixup! first 1662 x git show HEAD 1663 p $(git rev-list --abbrev-commit -1 second) # second 1664 s $(git rev-list --abbrev-commit -1 second_squash) # squash! second 1665 x git show HEAD 1666 EOF 1667 git checkout abbrevcmd && 1668 test_config rebase.abbreviateCommands true && 1669 ( 1670 set_cat_todo_editor && 1671 test_must_fail git rebase -i --exec "git show HEAD" \ 1672 --autosquash primary >actual 1673 ) && 1674 test_cmp expected actual 1675' 1676 1677test_expect_success 'static check of bad command' ' 1678 rebase_setup_and_clean bad-cmd && 1679 ( 1680 set_fake_editor && 1681 test_must_fail env FAKE_LINES="1 2 3 bad 4 5" \ 1682 git rebase -i --root 2>actual && 1683 test_grep "pickled $(git log --format="%h # %s" -1 primary~1)" \ 1684 actual && 1685 test_grep "You can fix this with .git rebase --edit-todo.." \ 1686 actual && 1687 FAKE_LINES="1 2 3 drop 4 5" git rebase --edit-todo 1688 ) && 1689 git rebase --continue && 1690 test E = $(git cat-file commit HEAD | sed -ne \$p) && 1691 test C = $(git cat-file commit HEAD^ | sed -ne \$p) 1692' 1693 1694test_expect_success 'the first command cannot be a fixup' ' 1695 rebase_setup_and_clean fixup-first && 1696 1697 cat >orig <<-EOF && 1698 fixup $(git log -1 --format="%h %s" B) 1699 pick $(git log -1 --format="%h %s" C) 1700 EOF 1701 1702 ( 1703 set_replace_editor orig && 1704 test_must_fail git rebase -i A 2>actual 1705 ) && 1706 grep "cannot .fixup. without a previous commit" actual && 1707 grep "You can fix this with .git rebase --edit-todo.." actual && 1708 # verify that the todo list has not been truncated 1709 grep -v "^#" .git/rebase-merge/git-rebase-todo >actual && 1710 test_cmp orig actual && 1711 1712 test_must_fail git rebase --edit-todo 2>actual && 1713 grep "cannot .fixup. without a previous commit" actual && 1714 grep "You can fix this with .git rebase --edit-todo.." actual && 1715 # verify that the todo list has not been truncated 1716 grep -v "^#" .git/rebase-merge/git-rebase-todo >actual && 1717 test_cmp orig actual 1718' 1719 1720test_expect_success 'tabs and spaces are accepted in the todolist' ' 1721 rebase_setup_and_clean indented-comment && 1722 write_script add-indent.sh <<-\EOF && 1723 ( 1724 # Turn single spaces into space/tab mix 1725 sed "1s/ / /g; 2s/ / /g; 3s/ / /g" "$1" 1726 printf "\n\t# comment\n #more\n\t # comment\n" 1727 ) >"$1.new" 1728 mv "$1.new" "$1" 1729 EOF 1730 ( 1731 test_set_editor "$(pwd)/add-indent.sh" && 1732 git rebase -i HEAD^^^ 1733 ) && 1734 test E = $(git cat-file commit HEAD | sed -ne \$p) 1735' 1736 1737test_expect_success 'static check of bad SHA-1' ' 1738 rebase_setup_and_clean bad-sha && 1739 ( 1740 set_fake_editor && 1741 test_must_fail env FAKE_LINES="1 2 edit fakesha 3 4 5 #" \ 1742 git rebase -i --root 2>actual && 1743 test_grep "edit XXXXXXX False commit" actual && 1744 test_grep "You can fix this with .git rebase --edit-todo.." \ 1745 actual && 1746 FAKE_LINES="1 2 4 5 6" git rebase --edit-todo 1747 ) && 1748 git rebase --continue && 1749 test E = $(git cat-file commit HEAD | sed -ne \$p) 1750' 1751 1752test_expect_success 'editor saves as CR/LF' ' 1753 git checkout -b with-crlf && 1754 write_script add-crs.sh <<-\EOF && 1755 sed -e "s/\$/Q/" <"$1" | tr Q "\\015" >"$1".new && 1756 mv -f "$1".new "$1" 1757 EOF 1758 ( 1759 test_set_editor "$(pwd)/add-crs.sh" && 1760 git rebase -i HEAD^ 1761 ) 1762' 1763 1764test_expect_success 'rebase -i --gpg-sign=<key-id>' ' 1765 test_when_finished "test_might_fail git rebase --abort" && 1766 ( 1767 set_fake_editor && 1768 FAKE_LINES="edit 1" git rebase -i --gpg-sign="\"S I Gner\"" \ 1769 HEAD^ >out 2>err 1770 ) && 1771 test_grep "$SQ-S\"S I Gner\"$SQ" err 1772' 1773 1774test_expect_success 'rebase -i --gpg-sign=<key-id> overrides commit.gpgSign' ' 1775 test_when_finished "test_might_fail git rebase --abort" && 1776 test_config commit.gpgsign true && 1777 ( 1778 set_fake_editor && 1779 FAKE_LINES="edit 1" git rebase -i --gpg-sign="\"S I Gner\"" \ 1780 HEAD^ >out 2>err 1781 ) && 1782 test_grep "$SQ-S\"S I Gner\"$SQ" err 1783' 1784 1785test_expect_success 'valid author header after --root swap' ' 1786 rebase_setup_and_clean author-header no-conflict-branch && 1787 git commit --amend --author="Au ${SQ}thor <author@example.com>" --no-edit && 1788 git cat-file commit HEAD | grep ^author >expected && 1789 ( 1790 set_fake_editor && 1791 FAKE_LINES="5 1" git rebase -i --root 1792 ) && 1793 git cat-file commit HEAD^ | grep ^author >actual && 1794 test_cmp expected actual 1795' 1796 1797test_expect_success 'valid author header when author contains single quote' ' 1798 rebase_setup_and_clean author-header no-conflict-branch && 1799 git commit --amend --author="Au ${SQ}thor <author@example.com>" --no-edit && 1800 git cat-file commit HEAD | grep ^author >expected && 1801 ( 1802 set_fake_editor && 1803 FAKE_LINES="2" git rebase -i HEAD~2 1804 ) && 1805 git cat-file commit HEAD | grep ^author >actual && 1806 test_cmp expected actual 1807' 1808 1809test_expect_success 'post-commit hook is called' ' 1810 >actual && 1811 test_hook post-commit <<-\EOS && 1812 git rev-parse HEAD >>actual 1813 EOS 1814 ( 1815 set_fake_editor && 1816 FAKE_LINES="edit 4 1 reword 2 fixup 3" git rebase -i A E && 1817 echo x>file3 && 1818 git add file3 && 1819 FAKE_COMMIT_MESSAGE=edited git rebase --continue 1820 ) && 1821 git rev-parse HEAD@{5} HEAD@{4} HEAD@{3} HEAD@{2} HEAD@{1} HEAD \ 1822 >expect && 1823 test_cmp expect actual 1824' 1825 1826test_expect_success 'correct error message for partial commit after empty pick' ' 1827 test_when_finished "git rebase --abort" && 1828 ( 1829 set_fake_editor && 1830 FAKE_LINES="2 1 1" && 1831 export FAKE_LINES && 1832 test_must_fail git rebase -i A D 1833 ) && 1834 echo x >file1 && 1835 test_must_fail git commit file1 2>err && 1836 test_grep "cannot do a partial commit during a rebase." err 1837' 1838 1839test_expect_success 'correct error message for commit --amend after empty pick' ' 1840 test_when_finished "git rebase --abort" && 1841 ( 1842 set_fake_editor && 1843 FAKE_LINES="1 1" && 1844 export FAKE_LINES && 1845 test_must_fail git rebase -i A D 1846 ) && 1847 echo x>file1 && 1848 test_must_fail git commit -a --amend 2>err && 1849 test_grep "middle of a rebase -- cannot amend." err 1850' 1851 1852test_expect_success 'todo has correct onto hash' ' 1853 GIT_SEQUENCE_EDITOR=cat git rebase -i no-conflict-branch~4 no-conflict-branch >actual && 1854 onto=$(git rev-parse --short HEAD~4) && 1855 test_grep "^# Rebase ..* onto $onto" actual 1856' 1857 1858test_expect_success 'ORIG_HEAD is updated correctly' ' 1859 test_when_finished "git checkout primary && git branch -D test-orig-head" && 1860 git checkout -b test-orig-head A && 1861 git commit --allow-empty -m A1 && 1862 git commit --allow-empty -m A2 && 1863 git commit --allow-empty -m A3 && 1864 git commit --allow-empty -m A4 && 1865 git rebase primary && 1866 test_cmp_rev ORIG_HEAD test-orig-head@{1} 1867' 1868 1869test_expect_success '--update-refs adds label and update-ref commands' ' 1870 git checkout -b update-refs no-conflict-branch && 1871 git branch -f base HEAD~4 && 1872 git branch -f first HEAD~3 && 1873 git branch -f second HEAD~3 && 1874 git branch -f third HEAD~1 && 1875 git commit --allow-empty --fixup=third && 1876 git branch -f is-not-reordered && 1877 git commit --allow-empty --fixup=HEAD~4 && 1878 git branch -f shared-tip && 1879 ( 1880 set_cat_todo_editor && 1881 1882 cat >expect <<-EOF && 1883 pick $(git log -1 --format=%h J) # J 1884 fixup $(git log -1 --format=%h update-refs) # fixup! J # empty 1885 update-ref refs/heads/second 1886 update-ref refs/heads/first 1887 pick $(git log -1 --format=%h K) # K 1888 pick $(git log -1 --format=%h L) # L 1889 fixup $(git log -1 --format=%h is-not-reordered) # fixup! L # empty 1890 update-ref refs/heads/third 1891 pick $(git log -1 --format=%h M) # M 1892 update-ref refs/heads/no-conflict-branch 1893 update-ref refs/heads/is-not-reordered 1894 update-ref refs/heads/shared-tip 1895 EOF 1896 1897 test_must_fail git rebase -i --autosquash --update-refs primary >todo && 1898 test_cmp expect todo && 1899 1900 test_must_fail git -c rebase.autosquash=true \ 1901 -c rebase.updaterefs=true \ 1902 rebase -i primary >todo && 1903 1904 test_cmp expect todo 1905 ) 1906' 1907 1908test_expect_success '--update-refs adds commands with --rebase-merges' ' 1909 git checkout -b update-refs-with-merge no-conflict-branch && 1910 git branch -f base HEAD~4 && 1911 git branch -f first HEAD~3 && 1912 git branch -f second HEAD~3 && 1913 git branch -f third HEAD~1 && 1914 git merge -m merge branch2 && 1915 git branch -f merge-branch && 1916 git commit --fixup=third --allow-empty && 1917 ( 1918 set_cat_todo_editor && 1919 1920 cat >expect <<-EOF && 1921 label onto 1922 reset onto 1923 pick $(git log -1 --format=%h branch2~1) # F 1924 pick $(git log -1 --format=%h branch2) # I 1925 update-ref refs/heads/branch2 1926 label branch2 1927 reset onto 1928 pick $(git log -1 --format=%h refs/heads/second) # J 1929 update-ref refs/heads/second 1930 update-ref refs/heads/first 1931 pick $(git log -1 --format=%h refs/heads/third~1) # K 1932 pick $(git log -1 --format=%h refs/heads/third) # L 1933 fixup $(git log -1 --format=%h update-refs-with-merge) # fixup! L # empty 1934 update-ref refs/heads/third 1935 pick $(git log -1 --format=%h HEAD~2) # M 1936 update-ref refs/heads/no-conflict-branch 1937 merge -C $(git log -1 --format=%h HEAD~1) branch2 # merge 1938 update-ref refs/heads/merge-branch 1939 EOF 1940 1941 test_must_fail git rebase -i --autosquash \ 1942 --rebase-merges=rebase-cousins \ 1943 --update-refs primary >todo && 1944 1945 test_cmp expect todo && 1946 1947 test_must_fail git -c rebase.autosquash=true \ 1948 -c rebase.updaterefs=true \ 1949 rebase -i \ 1950 --rebase-merges=rebase-cousins \ 1951 primary >todo && 1952 1953 test_cmp expect todo 1954 ) 1955' 1956 1957test_expect_success '--update-refs updates refs correctly' ' 1958 git checkout -B update-refs no-conflict-branch && 1959 git branch -f base HEAD~4 && 1960 git branch -f first HEAD~3 && 1961 git branch -f second HEAD~3 && 1962 git branch -f third HEAD~1 && 1963 test_commit extra2 fileX && 1964 git commit --amend --fixup=L && 1965 1966 git rebase -i --autosquash --update-refs primary 2>err && 1967 1968 test_cmp_rev HEAD~3 refs/heads/first && 1969 test_cmp_rev HEAD~3 refs/heads/second && 1970 test_cmp_rev HEAD~1 refs/heads/third && 1971 test_cmp_rev HEAD refs/heads/no-conflict-branch && 1972 1973 q_to_tab >expect <<-\EOF && 1974 Successfully rebased and updated refs/heads/update-refs. 1975 Updated the following refs with --update-refs: 1976 Qrefs/heads/first 1977 Qrefs/heads/no-conflict-branch 1978 Qrefs/heads/second 1979 Qrefs/heads/third 1980 EOF 1981 1982 # Clear "Rebasing (X/Y)" progress lines and drop leading tabs. 1983 sed "s/Rebasing.*Successfully/Successfully/g" <err >err.trimmed && 1984 test_cmp expect err.trimmed 1985' 1986 1987test_expect_success 'respect user edits to update-ref steps' ' 1988 git checkout -B update-refs-break no-conflict-branch && 1989 git branch -f base HEAD~4 && 1990 git branch -f first HEAD~3 && 1991 git branch -f second HEAD~3 && 1992 git branch -f third HEAD~1 && 1993 git branch -f unseen base && 1994 1995 # First, we will add breaks to the expected todo file 1996 cat >fake-todo-1 <<-EOF && 1997 pick $(git rev-parse HEAD~3) 1998 break 1999 update-ref refs/heads/second 2000 update-ref refs/heads/first 2001 2002 pick $(git rev-parse HEAD~2) 2003 pick $(git rev-parse HEAD~1) 2004 update-ref refs/heads/third 2005 2006 pick $(git rev-parse HEAD) 2007 update-ref refs/heads/no-conflict-branch 2008 EOF 2009 2010 # Second, we will drop some update-refs commands (and move one) 2011 cat >fake-todo-2 <<-EOF && 2012 update-ref refs/heads/second 2013 2014 pick $(git rev-parse HEAD~2) 2015 update-ref refs/heads/third 2016 pick $(git rev-parse HEAD~1) 2017 break 2018 2019 pick $(git rev-parse HEAD) 2020 EOF 2021 2022 # Third, we will: 2023 # * insert a new one (new-branch), 2024 # * re-add an old one (first), and 2025 # * add a second instance of a previously-stored one (second) 2026 cat >fake-todo-3 <<-EOF && 2027 update-ref refs/heads/unseen 2028 update-ref refs/heads/new-branch 2029 pick $(git rev-parse HEAD) 2030 update-ref refs/heads/first 2031 update-ref refs/heads/second 2032 EOF 2033 2034 ( 2035 set_replace_editor fake-todo-1 && 2036 git rebase -i --update-refs primary && 2037 2038 # These branches are currently locked. 2039 for b in first second third no-conflict-branch 2040 do 2041 test_must_fail git branch -f $b base || return 1 2042 done && 2043 2044 set_replace_editor fake-todo-2 && 2045 git rebase --edit-todo && 2046 2047 # These branches are currently locked. 2048 for b in second third 2049 do 2050 test_must_fail git branch -f $b base || return 1 2051 done && 2052 2053 # These branches are currently unlocked for checkout. 2054 for b in first no-conflict-branch 2055 do 2056 git worktree add wt-$b $b && 2057 git worktree remove wt-$b || return 1 2058 done && 2059 2060 git rebase --continue && 2061 2062 set_replace_editor fake-todo-3 && 2063 git rebase --edit-todo && 2064 2065 # These branches are currently locked. 2066 for b in second third first unseen 2067 do 2068 test_must_fail git branch -f $b base || return 1 2069 done && 2070 2071 # These branches are currently unlocked for checkout. 2072 for b in no-conflict-branch 2073 do 2074 git worktree add wt-$b $b && 2075 git worktree remove wt-$b || return 1 2076 done && 2077 2078 git rebase --continue 2079 ) && 2080 2081 test_cmp_rev HEAD~2 refs/heads/third && 2082 test_cmp_rev HEAD~1 refs/heads/unseen && 2083 test_cmp_rev HEAD~1 refs/heads/new-branch && 2084 test_cmp_rev HEAD refs/heads/first && 2085 test_cmp_rev HEAD refs/heads/second && 2086 test_cmp_rev HEAD refs/heads/no-conflict-branch 2087' 2088 2089test_expect_success '--update-refs: all update-ref lines removed' ' 2090 git checkout -b test-refs-not-removed no-conflict-branch && 2091 git branch -f base HEAD~4 && 2092 git branch -f first HEAD~3 && 2093 git branch -f second HEAD~3 && 2094 git branch -f third HEAD~1 && 2095 git branch -f tip && 2096 2097 test_commit test-refs-not-removed && 2098 git commit --amend --fixup first && 2099 2100 git rev-parse first second third tip no-conflict-branch >expect-oids && 2101 2102 ( 2103 set_cat_todo_editor && 2104 test_must_fail git rebase -i --update-refs base >todo.raw && 2105 sed -e "/^update-ref/d" <todo.raw >todo 2106 ) && 2107 ( 2108 set_replace_editor todo && 2109 git rebase -i --update-refs base 2110 ) && 2111 2112 # Ensure refs are not deleted and their OIDs have not changed 2113 git rev-parse first second third tip no-conflict-branch >actual-oids && 2114 test_cmp expect-oids actual-oids 2115' 2116 2117test_expect_success '--update-refs: all update-ref lines removed, then some re-added' ' 2118 git checkout -b test-refs-not-removed2 no-conflict-branch && 2119 git branch -f base HEAD~4 && 2120 git branch -f first HEAD~3 && 2121 git branch -f second HEAD~3 && 2122 git branch -f third HEAD~1 && 2123 git branch -f tip && 2124 2125 test_commit test-refs-not-removed2 && 2126 git commit --amend --fixup first && 2127 2128 git rev-parse first second third >expect-oids && 2129 2130 ( 2131 set_cat_todo_editor && 2132 test_must_fail git rebase -i \ 2133 --autosquash --update-refs \ 2134 base >todo.raw && 2135 sed -e "/^update-ref/d" <todo.raw >todo 2136 ) && 2137 2138 # Add a break to the end of the todo so we can edit later 2139 echo "break" >>todo && 2140 2141 ( 2142 set_replace_editor todo && 2143 git rebase -i --autosquash --update-refs base && 2144 echo "update-ref refs/heads/tip" >todo && 2145 git rebase --edit-todo && 2146 git rebase --continue 2147 ) && 2148 2149 # Ensure first/second/third are unchanged, but tip is updated 2150 git rev-parse first second third >actual-oids && 2151 test_cmp expect-oids actual-oids && 2152 test_cmp_rev HEAD tip 2153' 2154 2155test_expect_success '--update-refs: --edit-todo with no update-ref lines' ' 2156 git checkout -b test-refs-not-removed3 no-conflict-branch && 2157 git branch -f base HEAD~4 && 2158 git branch -f first HEAD~3 && 2159 git branch -f second HEAD~3 && 2160 git branch -f third HEAD~1 && 2161 git branch -f tip && 2162 2163 test_commit test-refs-not-removed3 && 2164 git commit --amend --fixup first && 2165 2166 git rev-parse first second third tip no-conflict-branch >expect-oids && 2167 2168 ( 2169 set_cat_todo_editor && 2170 test_must_fail git rebase -i \ 2171 --autosquash --update-refs \ 2172 base >todo.raw && 2173 sed -e "/^update-ref/d" <todo.raw >todo 2174 ) && 2175 2176 # Add a break to the beginning of the todo so we can resume with no 2177 # update-ref lines 2178 echo "break" >todo.new && 2179 cat todo >>todo.new && 2180 2181 ( 2182 set_replace_editor todo.new && 2183 git rebase -i --autosquash --update-refs base && 2184 2185 # Make no changes when editing so update-refs is still empty 2186 cat todo >todo.new && 2187 git rebase --edit-todo && 2188 git rebase --continue 2189 ) && 2190 2191 # Ensure refs are not deleted and their OIDs have not changed 2192 git rev-parse first second third tip no-conflict-branch >actual-oids && 2193 test_cmp expect-oids actual-oids 2194' 2195 2196test_expect_success '--update-refs: check failed ref update' ' 2197 test_when_finished "test_might_fail git rebase --abort" && 2198 git checkout -B update-refs-error no-conflict-branch && 2199 git branch -f base HEAD~4 && 2200 git branch -f first HEAD~3 && 2201 git branch -f second HEAD~2 && 2202 git branch -f third HEAD~1 && 2203 2204 cat >fake-todo <<-EOF && 2205 pick $(git rev-parse HEAD~3) 2206 break 2207 update-ref refs/heads/first 2208 2209 pick $(git rev-parse HEAD~2) 2210 update-ref refs/heads/second 2211 2212 pick $(git rev-parse HEAD~1) 2213 update-ref refs/heads/third 2214 2215 pick $(git rev-parse HEAD) 2216 update-ref refs/heads/no-conflict-branch 2217 EOF 2218 2219 ( 2220 set_replace_editor fake-todo && 2221 git rebase -i --update-refs base 2222 ) && 2223 2224 # At this point, the values of first, second, and third are 2225 # recorded in the update-refs file. We will force-update the 2226 # "second" ref, but "git branch -f" will not work because of 2227 # the lock in the update-refs file. 2228 git update-ref refs/heads/second third && 2229 2230 test_must_fail git rebase --continue 2>err && 2231 grep "update_ref failed for ref '\''refs/heads/second'\''" err && 2232 2233 q_to_tab >expect <<-\EOF && 2234 Updated the following refs with --update-refs: 2235 Qrefs/heads/first 2236 Qrefs/heads/no-conflict-branch 2237 Qrefs/heads/third 2238 Failed to update the following refs with --update-refs: 2239 Qrefs/heads/second 2240 EOF 2241 2242 # Clear "Rebasing (X/Y)" progress lines and drop leading tabs. 2243 tail -n 6 err >err.last && 2244 sed "s/Rebasing.*Successfully/Successfully/g" <err.last >err.trimmed && 2245 test_cmp expect err.trimmed 2246' 2247 2248test_expect_success 'bad labels and refs rejected when parsing todo list' ' 2249 test_when_finished "test_might_fail git rebase --abort" && 2250 cat >todo <<-\EOF && 2251 exec >execed 2252 label # 2253 label :invalid 2254 update-ref :bad 2255 update-ref topic 2256 EOF 2257 rm -f execed && 2258 ( 2259 set_replace_editor todo && 2260 test_must_fail git rebase -i HEAD 2>err 2261 ) && 2262 grep "'\''#'\'' is not a valid label" err && 2263 grep "'\'':invalid'\'' is not a valid label" err && 2264 grep "'\'':bad'\'' is not a valid refname" err && 2265 grep "update-ref requires a fully qualified refname e.g. refs/heads/topic" \ 2266 err && 2267 test_path_is_missing execed 2268' 2269 2270test_expect_success 'non-merge commands reject merge commits' ' 2271 test_when_finished "test_might_fail git rebase --abort" && 2272 git checkout E && 2273 git merge I && 2274 oid=$(git rev-parse HEAD) && 2275 cat >todo <<-EOF && 2276 pick $oid 2277 reword $oid 2278 edit $oid 2279 fixup $oid 2280 squash $oid 2281 drop $oid # acceptable, no advice 2282 EOF 2283 ( 2284 set_replace_editor todo && 2285 test_must_fail git rebase -i HEAD 2>actual 2286 ) && 2287 cat >expect <<-EOF && 2288 error: ${SQ}pick${SQ} does not accept merge commits 2289 hint: ${SQ}pick${SQ} does not take a merge commit. If you wanted to 2290 hint: replay the merge, use ${SQ}merge -C${SQ} on the commit. 2291 hint: Disable this message with "git config set advice.rebaseTodoError false" 2292 error: invalid line 1: pick $oid 2293 error: ${SQ}reword${SQ} does not accept merge commits 2294 hint: ${SQ}reword${SQ} does not take a merge commit. If you wanted to 2295 hint: replay the merge and reword the commit message, use 2296 hint: ${SQ}merge -c${SQ} on the commit 2297 hint: Disable this message with "git config set advice.rebaseTodoError false" 2298 error: invalid line 2: reword $oid 2299 error: ${SQ}edit${SQ} does not accept merge commits 2300 hint: ${SQ}edit${SQ} does not take a merge commit. If you wanted to 2301 hint: replay the merge, use ${SQ}merge -C${SQ} on the commit, and then 2302 hint: ${SQ}break${SQ} to give the control back to you so that you can 2303 hint: do ${SQ}git commit --amend && git rebase --continue${SQ}. 2304 hint: Disable this message with "git config set advice.rebaseTodoError false" 2305 error: invalid line 3: edit $oid 2306 error: cannot squash merge commit into another commit 2307 error: invalid line 4: fixup $oid 2308 error: cannot squash merge commit into another commit 2309 error: invalid line 5: squash $oid 2310 You can fix this with ${SQ}git rebase --edit-todo${SQ} and then run ${SQ}git rebase --continue${SQ}. 2311 Or you can abort the rebase with ${SQ}git rebase --abort${SQ}. 2312 EOF 2313 test_cmp expect actual 2314' 2315 2316# This must be the last test in this file 2317test_expect_success '$EDITOR and friends are unchanged' ' 2318 test_editor_unchanged 2319' 2320 2321test_done