t / t3507-cherry-pick-conflict.shon commit commit/reset: try to clean up sequencer state (b07d9bf)
   1#!/bin/sh
   2
   3test_description='test cherry-pick and revert with conflicts
   4
   5  -
   6  + picked: rewrites foo to c
   7  + base: rewrites foo to b
   8  + initial: writes foo as a, unrelated as unrelated
   9
  10'
  11
  12. ./test-lib.sh
  13
  14pristine_detach () {
  15        git checkout -f "$1^0" &&
  16        git read-tree -u --reset HEAD &&
  17        git clean -d -f -f -q -x
  18}
  19
  20test_expect_success setup '
  21
  22        echo unrelated >unrelated &&
  23        git add unrelated &&
  24        test_commit initial foo a &&
  25        test_commit base foo b &&
  26        test_commit picked foo c &&
  27        test_commit --signoff picked-signed foo d &&
  28        git config advice.detachedhead false
  29
  30'
  31
  32test_expect_success 'failed cherry-pick does not advance HEAD' '
  33        pristine_detach initial &&
  34
  35        head=$(git rev-parse HEAD) &&
  36        test_must_fail git cherry-pick picked &&
  37        newhead=$(git rev-parse HEAD) &&
  38
  39        test "$head" = "$newhead"
  40'
  41
  42test_expect_success 'advice from failed cherry-pick' "
  43        pristine_detach initial &&
  44
  45        picked=\$(git rev-parse --short picked) &&
  46        cat <<-EOF >expected &&
  47        error: could not apply \$picked... picked
  48        hint: after resolving the conflicts, mark the corrected paths
  49        hint: with 'git add <paths>' or 'git rm <paths>'
  50        hint: and commit the result with 'git commit'
  51        EOF
  52        test_must_fail git cherry-pick picked 2>actual &&
  53
  54        test_i18ncmp expected actual
  55"
  56
  57test_expect_success 'advice from failed cherry-pick --no-commit' "
  58        pristine_detach initial &&
  59
  60        picked=\$(git rev-parse --short picked) &&
  61        cat <<-EOF >expected &&
  62        error: could not apply \$picked... picked
  63        hint: after resolving the conflicts, mark the corrected paths
  64        hint: with 'git add <paths>' or 'git rm <paths>'
  65        EOF
  66        test_must_fail git cherry-pick --no-commit picked 2>actual &&
  67
  68        test_i18ncmp expected actual
  69"
  70
  71test_expect_success 'failed cherry-pick sets CHERRY_PICK_HEAD' '
  72        pristine_detach initial &&
  73        test_must_fail git cherry-pick picked &&
  74        test_cmp_rev picked CHERRY_PICK_HEAD
  75'
  76
  77test_expect_success 'successful cherry-pick does not set CHERRY_PICK_HEAD' '
  78        pristine_detach initial &&
  79        git cherry-pick base &&
  80        test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
  81'
  82
  83test_expect_success 'cherry-pick --no-commit does not set CHERRY_PICK_HEAD' '
  84        pristine_detach initial &&
  85        git cherry-pick --no-commit base &&
  86        test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
  87'
  88
  89test_expect_success 'cherry-pick w/dirty tree does not set CHERRY_PICK_HEAD' '
  90        pristine_detach initial &&
  91        echo foo > foo &&
  92        test_must_fail git cherry-pick base &&
  93        test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
  94'
  95
  96test_expect_success \
  97        'cherry-pick --strategy=resolve w/dirty tree does not set CHERRY_PICK_HEAD' '
  98        pristine_detach initial &&
  99        echo foo > foo &&
 100        test_must_fail git cherry-pick --strategy=resolve base &&
 101        test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
 102'
 103
 104test_expect_success 'GIT_CHERRY_PICK_HELP suppresses CHERRY_PICK_HEAD' '
 105        pristine_detach initial &&
 106        (
 107                GIT_CHERRY_PICK_HELP="and then do something else" &&
 108                export GIT_CHERRY_PICK_HELP &&
 109                test_must_fail git cherry-pick picked
 110        ) &&
 111        test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
 112'
 113
 114test_expect_success 'git reset clears CHERRY_PICK_HEAD' '
 115        pristine_detach initial &&
 116
 117        test_must_fail git cherry-pick picked &&
 118        git reset &&
 119
 120        test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
 121'
 122
 123test_expect_success 'failed commit does not clear CHERRY_PICK_HEAD' '
 124        pristine_detach initial &&
 125
 126        test_must_fail git cherry-pick picked &&
 127        test_must_fail git commit &&
 128
 129        test_cmp_rev picked CHERRY_PICK_HEAD
 130'
 131
 132test_expect_success 'cancelled commit does not clear CHERRY_PICK_HEAD' '
 133        pristine_detach initial &&
 134
 135        test_must_fail git cherry-pick picked &&
 136        echo resolved >foo &&
 137        git add foo &&
 138        git update-index --refresh -q &&
 139        test_must_fail git diff-index --exit-code HEAD &&
 140        (
 141                GIT_EDITOR=false &&
 142                export GIT_EDITOR &&
 143                test_must_fail git commit
 144        ) &&
 145
 146        test_cmp_rev picked CHERRY_PICK_HEAD
 147'
 148
 149test_expect_success 'successful commit clears CHERRY_PICK_HEAD' '
 150        pristine_detach initial &&
 151
 152        test_must_fail git cherry-pick picked &&
 153        echo resolved >foo &&
 154        git add foo &&
 155        git commit &&
 156
 157        test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
 158'
 159test_expect_success 'successful final commit clears cherry-pick state' '
 160        pristine_detach initial &&
 161
 162        test_must_fail git cherry-pick base picked-signed &&
 163        echo resolved >foo &&
 164        test_path_is_file .git/sequencer/todo &&
 165        git commit -a &&
 166        test_must_fail test_path_exists .git/sequencer
 167'
 168
 169test_expect_success 'reset after final pick clears cherry-pick state' '
 170        pristine_detach initial &&
 171
 172        test_must_fail git cherry-pick base picked-signed &&
 173        echo resolved >foo &&
 174        test_path_is_file .git/sequencer/todo &&
 175        git reset &&
 176        test_must_fail test_path_exists .git/sequencer
 177'
 178
 179test_expect_success 'failed cherry-pick produces dirty index' '
 180        pristine_detach initial &&
 181
 182        test_must_fail git cherry-pick picked &&
 183
 184        test_must_fail git update-index --refresh -q &&
 185        test_must_fail git diff-index --exit-code HEAD
 186'
 187
 188test_expect_success 'failed cherry-pick registers participants in index' '
 189        pristine_detach initial &&
 190        {
 191                git checkout base -- foo &&
 192                git ls-files --stage foo &&
 193                git checkout initial -- foo &&
 194                git ls-files --stage foo &&
 195                git checkout picked -- foo &&
 196                git ls-files --stage foo
 197        } > stages &&
 198        sed "
 199                1 s/ 0  / 1     /
 200                2 s/ 0  / 2     /
 201                3 s/ 0  / 3     /
 202        " < stages > expected &&
 203        git read-tree -u --reset HEAD &&
 204
 205        test_must_fail git cherry-pick picked &&
 206        git ls-files --stage --unmerged > actual &&
 207
 208        test_cmp expected actual
 209'
 210
 211test_expect_success 'failed cherry-pick describes conflict in work tree' '
 212        pristine_detach initial &&
 213        cat <<-EOF > expected &&
 214        <<<<<<< HEAD
 215        a
 216        =======
 217        c
 218        >>>>>>> objid picked
 219        EOF
 220
 221        test_must_fail git cherry-pick picked &&
 222
 223        sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
 224        test_cmp expected actual
 225'
 226
 227test_expect_success 'diff3 -m style' '
 228        pristine_detach initial &&
 229        git config merge.conflictstyle diff3 &&
 230        cat <<-EOF > expected &&
 231        <<<<<<< HEAD
 232        a
 233        ||||||| parent of objid picked
 234        b
 235        =======
 236        c
 237        >>>>>>> objid picked
 238        EOF
 239
 240        test_must_fail git cherry-pick picked &&
 241
 242        sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
 243        test_cmp expected actual
 244'
 245
 246test_expect_success 'revert also handles conflicts sanely' '
 247        git config --unset merge.conflictstyle &&
 248        pristine_detach initial &&
 249        cat <<-EOF > expected &&
 250        <<<<<<< HEAD
 251        a
 252        =======
 253        b
 254        >>>>>>> parent of objid picked
 255        EOF
 256        {
 257                git checkout picked -- foo &&
 258                git ls-files --stage foo &&
 259                git checkout initial -- foo &&
 260                git ls-files --stage foo &&
 261                git checkout base -- foo &&
 262                git ls-files --stage foo
 263        } > stages &&
 264        sed "
 265                1 s/ 0  / 1     /
 266                2 s/ 0  / 2     /
 267                3 s/ 0  / 3     /
 268        " < stages > expected-stages &&
 269        git read-tree -u --reset HEAD &&
 270
 271        head=$(git rev-parse HEAD) &&
 272        test_must_fail git revert picked &&
 273        newhead=$(git rev-parse HEAD) &&
 274        git ls-files --stage --unmerged > actual-stages &&
 275
 276        test "$head" = "$newhead" &&
 277        test_must_fail git update-index --refresh -q &&
 278        test_must_fail git diff-index --exit-code HEAD &&
 279        test_cmp expected-stages actual-stages &&
 280        sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
 281        test_cmp expected actual
 282'
 283
 284test_expect_success 'failed revert sets REVERT_HEAD' '
 285        pristine_detach initial &&
 286        test_must_fail git revert picked &&
 287        test_cmp_rev picked REVERT_HEAD
 288'
 289
 290test_expect_success 'successful revert does not set REVERT_HEAD' '
 291        pristine_detach base &&
 292        git revert base &&
 293        test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
 294        test_must_fail git rev-parse --verify REVERT_HEAD
 295'
 296
 297test_expect_success 'revert --no-commit sets REVERT_HEAD' '
 298        pristine_detach base &&
 299        git revert --no-commit base &&
 300        test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
 301        test_cmp_rev base REVERT_HEAD
 302'
 303
 304test_expect_success 'revert w/dirty tree does not set REVERT_HEAD' '
 305        pristine_detach base &&
 306        echo foo > foo &&
 307        test_must_fail git revert base &&
 308        test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
 309        test_must_fail git rev-parse --verify REVERT_HEAD
 310'
 311
 312test_expect_success 'GIT_CHERRY_PICK_HELP does not suppress REVERT_HEAD' '
 313        pristine_detach initial &&
 314        (
 315                GIT_CHERRY_PICK_HELP="and then do something else" &&
 316                GIT_REVERT_HELP="and then do something else, again" &&
 317                export GIT_CHERRY_PICK_HELP GIT_REVERT_HELP &&
 318                test_must_fail git revert picked
 319        ) &&
 320        test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
 321        test_cmp_rev picked REVERT_HEAD
 322'
 323
 324test_expect_success 'git reset clears REVERT_HEAD' '
 325        pristine_detach initial &&
 326        test_must_fail git revert picked &&
 327        git reset &&
 328        test_must_fail git rev-parse --verify REVERT_HEAD
 329'
 330
 331test_expect_success 'failed commit does not clear REVERT_HEAD' '
 332        pristine_detach initial &&
 333        test_must_fail git revert picked &&
 334        test_must_fail git commit &&
 335        test_cmp_rev picked REVERT_HEAD
 336'
 337
 338test_expect_success 'successful final commit clears revert state' '
 339       pristine_detach picked-signed &&
 340
 341       test_must_fail git revert picked-signed base &&
 342       echo resolved >foo &&
 343       test_path_is_file .git/sequencer/todo &&
 344       git commit -a &&
 345       test_must_fail test_path_exists .git/sequencer
 346'
 347
 348test_expect_success 'reset after final pick clears revert state' '
 349       pristine_detach picked-signed &&
 350
 351       test_must_fail git revert picked-signed base &&
 352       echo resolved >foo &&
 353       test_path_is_file .git/sequencer/todo &&
 354       git reset &&
 355       test_must_fail test_path_exists .git/sequencer
 356'
 357
 358test_expect_success 'revert conflict, diff3 -m style' '
 359        pristine_detach initial &&
 360        git config merge.conflictstyle diff3 &&
 361        cat <<-EOF > expected &&
 362        <<<<<<< HEAD
 363        a
 364        ||||||| objid picked
 365        c
 366        =======
 367        b
 368        >>>>>>> parent of objid picked
 369        EOF
 370
 371        test_must_fail git revert picked &&
 372
 373        sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
 374        test_cmp expected actual
 375'
 376
 377test_expect_success 'failed cherry-pick does not forget -s' '
 378        pristine_detach initial &&
 379        test_must_fail git cherry-pick -s picked &&
 380        test_i18ngrep -e "Signed-off-by" .git/MERGE_MSG
 381'
 382
 383test_expect_success 'commit after failed cherry-pick does not add duplicated -s' '
 384        pristine_detach initial &&
 385        test_must_fail git cherry-pick -s picked-signed &&
 386        git commit -a -s &&
 387        test $(git show -s |grep -c "Signed-off-by") = 1
 388'
 389
 390test_expect_success 'commit after failed cherry-pick adds -s at the right place' '
 391        pristine_detach initial &&
 392        test_must_fail git cherry-pick picked &&
 393
 394        git commit -a -s &&
 395
 396        # Do S-o-b and Conflicts appear in the right order?
 397        cat <<-\EOF >expect &&
 398        Signed-off-by: C O Mitter <committer@example.com>
 399        # Conflicts:
 400        EOF
 401        grep -e "^# Conflicts:" -e '^Signed-off-by' <.git/COMMIT_EDITMSG >actual &&
 402        test_cmp expect actual &&
 403
 404        cat <<-\EOF >expected &&
 405        picked
 406
 407        Signed-off-by: C O Mitter <committer@example.com>
 408        EOF
 409
 410        git show -s --pretty=format:%B >actual &&
 411        test_cmp expected actual
 412'
 413
 414test_expect_success 'commit --amend -s places the sign-off at the right place' '
 415        pristine_detach initial &&
 416        test_must_fail git cherry-pick picked &&
 417
 418        # emulate old-style conflicts block
 419        mv .git/MERGE_MSG .git/MERGE_MSG+ &&
 420        sed -e "/^# Conflicts:/,\$s/^# *//" <.git/MERGE_MSG+ >.git/MERGE_MSG &&
 421
 422        git commit -a &&
 423        git commit --amend -s &&
 424
 425        # Do S-o-b and Conflicts appear in the right order?
 426        cat <<-\EOF >expect &&
 427        Signed-off-by: C O Mitter <committer@example.com>
 428        Conflicts:
 429        EOF
 430        grep -e "^Conflicts:" -e '^Signed-off-by' <.git/COMMIT_EDITMSG >actual &&
 431        test_cmp expect actual
 432'
 433
 434test_expect_success 'cherry-pick preserves sparse-checkout' '
 435        pristine_detach initial &&
 436        test_config core.sparseCheckout true &&
 437        test_when_finished "
 438                echo \"/*\" >.git/info/sparse-checkout
 439                git read-tree --reset -u HEAD
 440                rm .git/info/sparse-checkout" &&
 441        echo /unrelated >.git/info/sparse-checkout &&
 442        git read-tree --reset -u HEAD &&
 443        test_must_fail git cherry-pick -Xours picked>actual &&
 444        test_i18ngrep ! "Changes not staged for commit:" actual
 445'
 446
 447test_done