t / t3903-stash.shon commit Merge branch 'jx/do-not-crash-receive-pack-wo-head' (0baebca)
   1#!/bin/sh
   2#
   3# Copyright (c) 2007 Johannes E Schindelin
   4#
   5
   6test_description='Test git stash'
   7
   8. ./test-lib.sh
   9
  10test_expect_success 'stash some dirty working directory' '
  11        echo 1 > file &&
  12        git add file &&
  13        echo unrelated >other-file &&
  14        git add other-file &&
  15        test_tick &&
  16        git commit -m initial &&
  17        echo 2 > file &&
  18        git add file &&
  19        echo 3 > file &&
  20        test_tick &&
  21        git stash &&
  22        git diff-files --quiet &&
  23        git diff-index --cached --quiet HEAD
  24'
  25
  26cat > expect << EOF
  27diff --git a/file b/file
  28index 0cfbf08..00750ed 100644
  29--- a/file
  30+++ b/file
  31@@ -1 +1 @@
  32-2
  33+3
  34EOF
  35
  36test_expect_success 'parents of stash' '
  37        test $(git rev-parse stash^) = $(git rev-parse HEAD) &&
  38        git diff stash^2..stash > output &&
  39        test_cmp output expect
  40'
  41
  42test_expect_success 'applying bogus stash does nothing' '
  43        test_must_fail git stash apply stash@{1} &&
  44        echo 1 >expect &&
  45        test_cmp expect file
  46'
  47
  48test_expect_success 'apply does not need clean working directory' '
  49        echo 4 >other-file &&
  50        git stash apply &&
  51        echo 3 >expect &&
  52        test_cmp expect file
  53'
  54
  55test_expect_success 'apply does not clobber working directory changes' '
  56        git reset --hard &&
  57        echo 4 >file &&
  58        test_must_fail git stash apply &&
  59        echo 4 >expect &&
  60        test_cmp expect file
  61'
  62
  63test_expect_success 'apply stashed changes' '
  64        git reset --hard &&
  65        echo 5 >other-file &&
  66        git add other-file &&
  67        test_tick &&
  68        git commit -m other-file &&
  69        git stash apply &&
  70        test 3 = $(cat file) &&
  71        test 1 = $(git show :file) &&
  72        test 1 = $(git show HEAD:file)
  73'
  74
  75test_expect_success 'apply stashed changes (including index)' '
  76        git reset --hard HEAD^ &&
  77        echo 6 > other-file &&
  78        git add other-file &&
  79        test_tick &&
  80        git commit -m other-file &&
  81        git stash apply --index &&
  82        test 3 = $(cat file) &&
  83        test 2 = $(git show :file) &&
  84        test 1 = $(git show HEAD:file)
  85'
  86
  87test_expect_success 'unstashing in a subdirectory' '
  88        git reset --hard HEAD &&
  89        mkdir subdir &&
  90        (
  91                cd subdir &&
  92                git stash apply
  93        )
  94'
  95
  96test_expect_success 'stash drop complains of extra options' '
  97        test_must_fail git stash drop --foo
  98'
  99
 100test_expect_success 'drop top stash' '
 101        git reset --hard &&
 102        git stash list > stashlist1 &&
 103        echo 7 > file &&
 104        git stash &&
 105        git stash drop &&
 106        git stash list > stashlist2 &&
 107        test_cmp stashlist1 stashlist2 &&
 108        git stash apply &&
 109        test 3 = $(cat file) &&
 110        test 1 = $(git show :file) &&
 111        test 1 = $(git show HEAD:file)
 112'
 113
 114test_expect_success 'drop middle stash' '
 115        git reset --hard &&
 116        echo 8 > file &&
 117        git stash &&
 118        echo 9 > file &&
 119        git stash &&
 120        git stash drop stash@{1} &&
 121        test 2 = $(git stash list | wc -l) &&
 122        git stash apply &&
 123        test 9 = $(cat file) &&
 124        test 1 = $(git show :file) &&
 125        test 1 = $(git show HEAD:file) &&
 126        git reset --hard &&
 127        git stash drop &&
 128        git stash apply &&
 129        test 3 = $(cat file) &&
 130        test 1 = $(git show :file) &&
 131        test 1 = $(git show HEAD:file)
 132'
 133
 134test_expect_success 'stash pop' '
 135        git reset --hard &&
 136        git stash pop &&
 137        test 3 = $(cat file) &&
 138        test 1 = $(git show :file) &&
 139        test 1 = $(git show HEAD:file) &&
 140        test 0 = $(git stash list | wc -l)
 141'
 142
 143cat > expect << EOF
 144diff --git a/file2 b/file2
 145new file mode 100644
 146index 0000000..1fe912c
 147--- /dev/null
 148+++ b/file2
 149@@ -0,0 +1 @@
 150+bar2
 151EOF
 152
 153cat > expect1 << EOF
 154diff --git a/file b/file
 155index 257cc56..5716ca5 100644
 156--- a/file
 157+++ b/file
 158@@ -1 +1 @@
 159-foo
 160+bar
 161EOF
 162
 163cat > expect2 << EOF
 164diff --git a/file b/file
 165index 7601807..5716ca5 100644
 166--- a/file
 167+++ b/file
 168@@ -1 +1 @@
 169-baz
 170+bar
 171diff --git a/file2 b/file2
 172new file mode 100644
 173index 0000000..1fe912c
 174--- /dev/null
 175+++ b/file2
 176@@ -0,0 +1 @@
 177+bar2
 178EOF
 179
 180test_expect_success 'stash branch' '
 181        echo foo > file &&
 182        git commit file -m first &&
 183        echo bar > file &&
 184        echo bar2 > file2 &&
 185        git add file2 &&
 186        git stash &&
 187        echo baz > file &&
 188        git commit file -m second &&
 189        git stash branch stashbranch &&
 190        test refs/heads/stashbranch = $(git symbolic-ref HEAD) &&
 191        test $(git rev-parse HEAD) = $(git rev-parse master^) &&
 192        git diff --cached > output &&
 193        test_cmp output expect &&
 194        git diff > output &&
 195        test_cmp output expect1 &&
 196        git add file &&
 197        git commit -m alternate\ second &&
 198        git diff master..stashbranch > output &&
 199        test_cmp output expect2 &&
 200        test 0 = $(git stash list | wc -l)
 201'
 202
 203test_expect_success 'apply -q is quiet' '
 204        echo foo > file &&
 205        git stash &&
 206        git stash apply -q > output.out 2>&1 &&
 207        test_must_be_empty output.out
 208'
 209
 210test_expect_success 'save -q is quiet' '
 211        git stash save --quiet > output.out 2>&1 &&
 212        test_must_be_empty output.out
 213'
 214
 215test_expect_success 'pop -q is quiet' '
 216        git stash pop -q > output.out 2>&1 &&
 217        test_must_be_empty output.out
 218'
 219
 220test_expect_success 'pop -q --index works and is quiet' '
 221        echo foo > file &&
 222        git add file &&
 223        git stash save --quiet &&
 224        git stash pop -q --index > output.out 2>&1 &&
 225        test foo = "$(git show :file)" &&
 226        test_must_be_empty output.out
 227'
 228
 229test_expect_success 'drop -q is quiet' '
 230        git stash &&
 231        git stash drop -q > output.out 2>&1 &&
 232        test_must_be_empty output.out
 233'
 234
 235test_expect_success 'stash -k' '
 236        echo bar3 > file &&
 237        echo bar4 > file2 &&
 238        git add file2 &&
 239        git stash -k &&
 240        test bar,bar4 = $(cat file),$(cat file2)
 241'
 242
 243test_expect_success 'stash --no-keep-index' '
 244        echo bar33 > file &&
 245        echo bar44 > file2 &&
 246        git add file2 &&
 247        git stash --no-keep-index &&
 248        test bar,bar2 = $(cat file),$(cat file2)
 249'
 250
 251test_expect_success 'stash --invalid-option' '
 252        echo bar5 > file &&
 253        echo bar6 > file2 &&
 254        git add file2 &&
 255        test_must_fail git stash --invalid-option &&
 256        test_must_fail git stash save --invalid-option &&
 257        test bar5,bar6 = $(cat file),$(cat file2) &&
 258        git stash -- -message-starting-with-dash &&
 259        test bar,bar2 = $(cat file),$(cat file2)
 260'
 261
 262test_expect_success 'stash an added file' '
 263        git reset --hard &&
 264        echo new >file3 &&
 265        git add file3 &&
 266        git stash save "added file" &&
 267        ! test -r file3 &&
 268        git stash apply &&
 269        test new = "$(cat file3)"
 270'
 271
 272test_expect_success 'stash rm then recreate' '
 273        git reset --hard &&
 274        git rm file &&
 275        echo bar7 >file &&
 276        git stash save "rm then recreate" &&
 277        test bar = "$(cat file)" &&
 278        git stash apply &&
 279        test bar7 = "$(cat file)"
 280'
 281
 282test_expect_success 'stash rm and ignore' '
 283        git reset --hard &&
 284        git rm file &&
 285        echo file >.gitignore &&
 286        git stash save "rm and ignore" &&
 287        test bar = "$(cat file)" &&
 288        test file = "$(cat .gitignore)" &&
 289        git stash apply &&
 290        ! test -r file &&
 291        test file = "$(cat .gitignore)"
 292'
 293
 294test_expect_success 'stash rm and ignore (stage .gitignore)' '
 295        git reset --hard &&
 296        git rm file &&
 297        echo file >.gitignore &&
 298        git add .gitignore &&
 299        git stash save "rm and ignore (stage .gitignore)" &&
 300        test bar = "$(cat file)" &&
 301        ! test -r .gitignore &&
 302        git stash apply &&
 303        ! test -r file &&
 304        test file = "$(cat .gitignore)"
 305'
 306
 307test_expect_success SYMLINKS 'stash file to symlink' '
 308        git reset --hard &&
 309        rm file &&
 310        ln -s file2 file &&
 311        git stash save "file to symlink" &&
 312        test -f file &&
 313        test bar = "$(cat file)" &&
 314        git stash apply &&
 315        case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac
 316'
 317
 318test_expect_success SYMLINKS 'stash file to symlink (stage rm)' '
 319        git reset --hard &&
 320        git rm file &&
 321        ln -s file2 file &&
 322        git stash save "file to symlink (stage rm)" &&
 323        test -f file &&
 324        test bar = "$(cat file)" &&
 325        git stash apply &&
 326        case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac
 327'
 328
 329test_expect_success SYMLINKS 'stash file to symlink (full stage)' '
 330        git reset --hard &&
 331        rm file &&
 332        ln -s file2 file &&
 333        git add file &&
 334        git stash save "file to symlink (full stage)" &&
 335        test -f file &&
 336        test bar = "$(cat file)" &&
 337        git stash apply &&
 338        case "$(ls -l file)" in *" file -> file2") :;; *) false;; esac
 339'
 340
 341# This test creates a commit with a symlink used for the following tests
 342
 343test_expect_success 'stash symlink to file' '
 344        git reset --hard &&
 345        test_ln_s_add file filelink &&
 346        git commit -m "Add symlink" &&
 347        rm filelink &&
 348        cp file filelink &&
 349        git stash save "symlink to file"
 350'
 351
 352test_expect_success SYMLINKS 'this must have re-created the symlink' '
 353        test -h filelink &&
 354        case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac
 355'
 356
 357test_expect_success 'unstash must re-create the file' '
 358        git stash apply &&
 359        ! test -h filelink &&
 360        test bar = "$(cat file)"
 361'
 362
 363test_expect_success 'stash symlink to file (stage rm)' '
 364        git reset --hard &&
 365        git rm filelink &&
 366        cp file filelink &&
 367        git stash save "symlink to file (stage rm)"
 368'
 369
 370test_expect_success SYMLINKS 'this must have re-created the symlink' '
 371        test -h filelink &&
 372        case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac
 373'
 374
 375test_expect_success 'unstash must re-create the file' '
 376        git stash apply &&
 377        ! test -h filelink &&
 378        test bar = "$(cat file)"
 379'
 380
 381test_expect_success 'stash symlink to file (full stage)' '
 382        git reset --hard &&
 383        rm filelink &&
 384        cp file filelink &&
 385        git add filelink &&
 386        git stash save "symlink to file (full stage)"
 387'
 388
 389test_expect_success SYMLINKS 'this must have re-created the symlink' '
 390        test -h filelink &&
 391        case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac
 392'
 393
 394test_expect_success 'unstash must re-create the file' '
 395        git stash apply &&
 396        ! test -h filelink &&
 397        test bar = "$(cat file)"
 398'
 399
 400test_expect_failure 'stash directory to file' '
 401        git reset --hard &&
 402        mkdir dir &&
 403        echo foo >dir/file &&
 404        git add dir/file &&
 405        git commit -m "Add file in dir" &&
 406        rm -fr dir &&
 407        echo bar >dir &&
 408        git stash save "directory to file" &&
 409        test -d dir &&
 410        test foo = "$(cat dir/file)" &&
 411        test_must_fail git stash apply &&
 412        test bar = "$(cat dir)" &&
 413        git reset --soft HEAD^
 414'
 415
 416test_expect_failure 'stash file to directory' '
 417        git reset --hard &&
 418        rm file &&
 419        mkdir file &&
 420        echo foo >file/file &&
 421        git stash save "file to directory" &&
 422        test -f file &&
 423        test bar = "$(cat file)" &&
 424        git stash apply &&
 425        test -f file/file &&
 426        test foo = "$(cat file/file)"
 427'
 428
 429test_expect_success 'stash branch - no stashes on stack, stash-like argument' '
 430        git stash clear &&
 431        test_when_finished "git reset --hard HEAD" &&
 432        git reset --hard &&
 433        echo foo >> file &&
 434        STASH_ID=$(git stash create) &&
 435        git reset --hard &&
 436        git stash branch stash-branch ${STASH_ID} &&
 437        test_when_finished "git reset --hard HEAD && git checkout master && git branch -D stash-branch" &&
 438        test $(git ls-files --modified | wc -l) -eq 1
 439'
 440
 441test_expect_success 'stash branch - stashes on stack, stash-like argument' '
 442        git stash clear &&
 443        test_when_finished "git reset --hard HEAD" &&
 444        git reset --hard &&
 445        echo foo >> file &&
 446        git stash &&
 447        test_when_finished "git stash drop" &&
 448        echo bar >> file &&
 449        STASH_ID=$(git stash create) &&
 450        git reset --hard &&
 451        git stash branch stash-branch ${STASH_ID} &&
 452        test_when_finished "git reset --hard HEAD && git checkout master && git branch -D stash-branch" &&
 453        test $(git ls-files --modified | wc -l) -eq 1
 454'
 455
 456test_expect_success 'stash show format defaults to --stat' '
 457        git stash clear &&
 458        test_when_finished "git reset --hard HEAD" &&
 459        git reset --hard &&
 460        echo foo >> file &&
 461        git stash &&
 462        test_when_finished "git stash drop" &&
 463        echo bar >> file &&
 464        STASH_ID=$(git stash create) &&
 465        git reset --hard &&
 466        cat >expected <<-EOF &&
 467         file | 1 +
 468         1 file changed, 1 insertion(+)
 469        EOF
 470        git stash show ${STASH_ID} >actual &&
 471        test_i18ncmp expected actual
 472'
 473
 474test_expect_success 'stash show - stashes on stack, stash-like argument' '
 475        git stash clear &&
 476        test_when_finished "git reset --hard HEAD" &&
 477        git reset --hard &&
 478        echo foo >> file &&
 479        git stash &&
 480        test_when_finished "git stash drop" &&
 481        echo bar >> file &&
 482        STASH_ID=$(git stash create) &&
 483        git reset --hard &&
 484        echo "1 0       file" >expected &&
 485        git stash show --numstat ${STASH_ID} >actual &&
 486        test_cmp expected actual
 487'
 488
 489test_expect_success 'stash show -p - stashes on stack, stash-like argument' '
 490        git stash clear &&
 491        test_when_finished "git reset --hard HEAD" &&
 492        git reset --hard &&
 493        echo foo >> file &&
 494        git stash &&
 495        test_when_finished "git stash drop" &&
 496        echo bar >> file &&
 497        STASH_ID=$(git stash create) &&
 498        git reset --hard &&
 499        cat >expected <<-EOF &&
 500        diff --git a/file b/file
 501        index 7601807..935fbd3 100644
 502        --- a/file
 503        +++ b/file
 504        @@ -1 +1,2 @@
 505         baz
 506        +bar
 507        EOF
 508        git stash show -p ${STASH_ID} >actual &&
 509        test_cmp expected actual
 510'
 511
 512test_expect_success 'stash show - no stashes on stack, stash-like argument' '
 513        git stash clear &&
 514        test_when_finished "git reset --hard HEAD" &&
 515        git reset --hard &&
 516        echo foo >> file &&
 517        STASH_ID=$(git stash create) &&
 518        git reset --hard &&
 519        echo "1 0       file" >expected &&
 520        git stash show --numstat ${STASH_ID} >actual &&
 521        test_cmp expected actual
 522'
 523
 524test_expect_success 'stash show -p - no stashes on stack, stash-like argument' '
 525        git stash clear &&
 526        test_when_finished "git reset --hard HEAD" &&
 527        git reset --hard &&
 528        echo foo >> file &&
 529        STASH_ID=$(git stash create) &&
 530        git reset --hard &&
 531        cat >expected <<-EOF &&
 532        diff --git a/file b/file
 533        index 7601807..71b52c4 100644
 534        --- a/file
 535        +++ b/file
 536        @@ -1 +1,2 @@
 537         baz
 538        +foo
 539        EOF
 540        git stash show -p ${STASH_ID} >actual &&
 541        test_cmp expected actual
 542'
 543
 544test_expect_success 'stash drop - fail early if specified stash is not a stash reference' '
 545        git stash clear &&
 546        test_when_finished "git reset --hard HEAD && git stash clear" &&
 547        git reset --hard &&
 548        echo foo > file &&
 549        git stash &&
 550        echo bar > file &&
 551        git stash &&
 552        test_must_fail git stash drop $(git rev-parse stash@{0}) &&
 553        git stash pop &&
 554        test bar = "$(cat file)" &&
 555        git reset --hard HEAD
 556'
 557
 558test_expect_success 'stash pop - fail early if specified stash is not a stash reference' '
 559        git stash clear &&
 560        test_when_finished "git reset --hard HEAD && git stash clear" &&
 561        git reset --hard &&
 562        echo foo > file &&
 563        git stash &&
 564        echo bar > file &&
 565        git stash &&
 566        test_must_fail git stash pop $(git rev-parse stash@{0}) &&
 567        git stash pop &&
 568        test bar = "$(cat file)" &&
 569        git reset --hard HEAD
 570'
 571
 572test_expect_success 'ref with non-existent reflog' '
 573        git stash clear &&
 574        echo bar5 > file &&
 575        echo bar6 > file2 &&
 576        git add file2 &&
 577        git stash &&
 578        test_must_fail git rev-parse --quiet --verify does-not-exist &&
 579        test_must_fail git stash drop does-not-exist &&
 580        test_must_fail git stash drop does-not-exist@{0} &&
 581        test_must_fail git stash pop does-not-exist &&
 582        test_must_fail git stash pop does-not-exist@{0} &&
 583        test_must_fail git stash apply does-not-exist &&
 584        test_must_fail git stash apply does-not-exist@{0} &&
 585        test_must_fail git stash show does-not-exist &&
 586        test_must_fail git stash show does-not-exist@{0} &&
 587        test_must_fail git stash branch tmp does-not-exist &&
 588        test_must_fail git stash branch tmp does-not-exist@{0} &&
 589        git stash drop
 590'
 591
 592test_expect_success 'invalid ref of the form stash@{n}, n >= N' '
 593        git stash clear &&
 594        test_must_fail git stash drop stash@{0} &&
 595        echo bar5 > file &&
 596        echo bar6 > file2 &&
 597        git add file2 &&
 598        git stash &&
 599        test_must_fail git stash drop stash@{1} &&
 600        test_must_fail git stash pop stash@{1} &&
 601        test_must_fail git stash apply stash@{1} &&
 602        test_must_fail git stash show stash@{1} &&
 603        test_must_fail git stash branch tmp stash@{1} &&
 604        git stash drop
 605'
 606
 607test_expect_success 'stash branch should not drop the stash if the branch exists' '
 608        git stash clear &&
 609        echo foo >file &&
 610        git add file &&
 611        git commit -m initial &&
 612        echo bar >file &&
 613        git stash &&
 614        test_must_fail git stash branch master stash@{0} &&
 615        git rev-parse stash@{0} --
 616'
 617
 618test_expect_success 'stash apply shows status same as git status (relative to current directory)' '
 619        git stash clear &&
 620        echo 1 >subdir/subfile1 &&
 621        echo 2 >subdir/subfile2 &&
 622        git add subdir/subfile1 &&
 623        git commit -m subdir &&
 624        (
 625                cd subdir &&
 626                echo x >subfile1 &&
 627                echo x >../file &&
 628                git status >../expect &&
 629                git stash &&
 630                sane_unset GIT_MERGE_VERBOSITY &&
 631                git stash apply
 632        ) |
 633        sed -e 1,2d >actual && # drop "Saved..." and "HEAD is now..."
 634        test_i18ncmp expect actual
 635'
 636
 637cat > expect << EOF
 638diff --git a/HEAD b/HEAD
 639new file mode 100644
 640index 0000000..fe0cbee
 641--- /dev/null
 642+++ b/HEAD
 643@@ -0,0 +1 @@
 644+file-not-a-ref
 645EOF
 646
 647test_expect_success 'stash where working directory contains "HEAD" file' '
 648        git stash clear &&
 649        git reset --hard &&
 650        echo file-not-a-ref > HEAD &&
 651        git add HEAD &&
 652        test_tick &&
 653        git stash &&
 654        git diff-files --quiet &&
 655        git diff-index --cached --quiet HEAD &&
 656        test "$(git rev-parse stash^)" = "$(git rev-parse HEAD)" &&
 657        git diff stash^..stash > output &&
 658        test_cmp output expect
 659'
 660
 661test_expect_success 'store called with invalid commit' '
 662        test_must_fail git stash store foo
 663'
 664
 665test_expect_success 'store updates stash ref and reflog' '
 666        git stash clear &&
 667        git reset --hard &&
 668        echo quux >bazzy &&
 669        git add bazzy &&
 670        STASH_ID=$(git stash create) &&
 671        git reset --hard &&
 672        ! grep quux bazzy &&
 673        git stash store -m quuxery $STASH_ID &&
 674        test $(cat .git/refs/stash) = $STASH_ID &&
 675        grep $STASH_ID .git/logs/refs/stash &&
 676        git stash pop &&
 677        grep quux bazzy
 678'
 679
 680test_expect_success 'handle stash specification with spaces' '
 681        git stash clear &&
 682        echo pig >file &&
 683        git stash &&
 684        stamp=$(git log -g --format="%cd" -1 refs/stash) &&
 685        test_tick &&
 686        echo cow >file &&
 687        git stash &&
 688        git stash apply "stash@{$stamp}" &&
 689        grep pig file
 690'
 691
 692test_expect_success 'setup stash with index and worktree changes' '
 693        git stash clear &&
 694        git reset --hard &&
 695        echo index >file &&
 696        git add file &&
 697        echo working >file &&
 698        git stash
 699'
 700
 701test_expect_success 'stash list implies --first-parent -m' '
 702        cat >expect <<-EOF &&
 703        stash@{0}
 704
 705        diff --git a/file b/file
 706        index 257cc56..d26b33d 100644
 707        --- a/file
 708        +++ b/file
 709        @@ -1 +1 @@
 710        -foo
 711        +working
 712        EOF
 713        git stash list --format=%gd -p >actual &&
 714        test_cmp expect actual
 715'
 716
 717test_expect_success 'stash list --cc shows combined diff' '
 718        cat >expect <<-\EOF &&
 719        stash@{0}
 720
 721        diff --cc file
 722        index 257cc56,9015a7a..d26b33d
 723        --- a/file
 724        +++ b/file
 725        @@@ -1,1 -1,1 +1,1 @@@
 726        - foo
 727         -index
 728        ++working
 729        EOF
 730        git stash list --format=%gd -p --cc >actual &&
 731        test_cmp expect actual
 732'
 733
 734test_done