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