t / t7611-merge-abort.shon commit Merge branch 'rj/xdiff-prepare-plug-leak-on-error-codepath' (aa3a2c2)
   1#!/bin/sh
   2
   3test_description='test aborting in-progress merges
   4
   5Set up repo with conflicting and non-conflicting branches:
   6
   7There are three files foo/bar/baz, and the following graph illustrates the
   8content of these files in each commit:
   9
  10# foo/bar/baz --- foo/bar/bazz     <-- master
  11#             \
  12#              --- foo/barf/bazf   <-- conflict_branch
  13#               \
  14#                --- foo/bart/baz  <-- clean_branch
  15
  16Next, test git merge --abort with the following variables:
  17- before/after successful merge (should fail when not in merge context)
  18- with/without conflicts
  19- clean/dirty index before merge
  20- clean/dirty worktree before merge
  21- dirty index before merge matches contents on remote branch
  22- changed/unchanged worktree after merge
  23- changed/unchanged index after merge
  24'
  25. ./test-lib.sh
  26
  27test_expect_success 'setup' '
  28        # Create the above repo
  29        echo foo > foo &&
  30        echo bar > bar &&
  31        echo baz > baz &&
  32        git add foo bar baz &&
  33        git commit -m initial &&
  34        echo bazz > baz &&
  35        git commit -a -m "second" &&
  36        git checkout -b conflict_branch HEAD^ &&
  37        echo barf > bar &&
  38        echo bazf > baz &&
  39        git commit -a -m "conflict" &&
  40        git checkout -b clean_branch HEAD^ &&
  41        echo bart > bar &&
  42        git commit -a -m "clean" &&
  43        git checkout master
  44'
  45
  46pre_merge_head="$(git rev-parse HEAD)"
  47
  48test_expect_success 'fails without MERGE_HEAD (unstarted merge)' '
  49        test_must_fail git merge --abort 2>output &&
  50        test_i18ngrep MERGE_HEAD output
  51'
  52
  53test_expect_success 'fails without MERGE_HEAD (unstarted merge): .git/MERGE_HEAD sanity' '
  54        test ! -f .git/MERGE_HEAD &&
  55        test "$pre_merge_head" = "$(git rev-parse HEAD)"
  56'
  57
  58test_expect_success 'fails without MERGE_HEAD (completed merge)' '
  59        git merge clean_branch &&
  60        test ! -f .git/MERGE_HEAD &&
  61        # Merge successfully completed
  62        post_merge_head="$(git rev-parse HEAD)" &&
  63        test_must_fail git merge --abort 2>output &&
  64        test_i18ngrep MERGE_HEAD output
  65'
  66
  67test_expect_success 'fails without MERGE_HEAD (completed merge): .git/MERGE_HEAD sanity' '
  68        test ! -f .git/MERGE_HEAD &&
  69        test "$post_merge_head" = "$(git rev-parse HEAD)"
  70'
  71
  72test_expect_success 'Forget previous merge' '
  73        git reset --hard "$pre_merge_head"
  74'
  75
  76test_expect_success 'Abort after --no-commit' '
  77        # Redo merge, but stop before creating merge commit
  78        git merge --no-commit clean_branch &&
  79        test -f .git/MERGE_HEAD &&
  80        # Abort non-conflicting merge
  81        git merge --abort &&
  82        test ! -f .git/MERGE_HEAD &&
  83        test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
  84        test -z "$(git diff)" &&
  85        test -z "$(git diff --staged)"
  86'
  87
  88test_expect_success 'Abort after conflicts' '
  89        # Create conflicting merge
  90        test_must_fail git merge conflict_branch &&
  91        test -f .git/MERGE_HEAD &&
  92        # Abort conflicting merge
  93        git merge --abort &&
  94        test ! -f .git/MERGE_HEAD &&
  95        test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
  96        test -z "$(git diff)" &&
  97        test -z "$(git diff --staged)"
  98'
  99
 100test_expect_success 'Clean merge with dirty index fails' '
 101        echo xyzzy >> foo &&
 102        git add foo &&
 103        git diff --staged > expect &&
 104        test_must_fail git merge clean_branch &&
 105        test ! -f .git/MERGE_HEAD &&
 106        test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 107        test -z "$(git diff)" &&
 108        git diff --staged > actual &&
 109        test_cmp expect actual
 110'
 111
 112test_expect_success 'Conflicting merge with dirty index fails' '
 113        test_must_fail git merge conflict_branch &&
 114        test ! -f .git/MERGE_HEAD &&
 115        test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 116        test -z "$(git diff)" &&
 117        git diff --staged > actual &&
 118        test_cmp expect actual
 119'
 120
 121test_expect_success 'Reset index (but preserve worktree changes)' '
 122        git reset "$pre_merge_head" &&
 123        git diff > actual &&
 124        test_cmp expect actual
 125'
 126
 127test_expect_success 'Abort clean merge with non-conflicting dirty worktree' '
 128        git merge --no-commit clean_branch &&
 129        test -f .git/MERGE_HEAD &&
 130        # Abort merge
 131        git merge --abort &&
 132        test ! -f .git/MERGE_HEAD &&
 133        test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 134        test -z "$(git diff --staged)" &&
 135        git diff > actual &&
 136        test_cmp expect actual
 137'
 138
 139test_expect_success 'Abort conflicting merge with non-conflicting dirty worktree' '
 140        test_must_fail git merge conflict_branch &&
 141        test -f .git/MERGE_HEAD &&
 142        # Abort merge
 143        git merge --abort &&
 144        test ! -f .git/MERGE_HEAD &&
 145        test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 146        test -z "$(git diff --staged)" &&
 147        git diff > actual &&
 148        test_cmp expect actual
 149'
 150
 151test_expect_success 'Reset worktree changes' '
 152        git reset --hard "$pre_merge_head"
 153'
 154
 155test_expect_success 'Fail clean merge with conflicting dirty worktree' '
 156        echo xyzzy >> bar &&
 157        git diff > expect &&
 158        test_must_fail git merge --no-commit clean_branch &&
 159        test ! -f .git/MERGE_HEAD &&
 160        test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 161        test -z "$(git diff --staged)" &&
 162        git diff > actual &&
 163        test_cmp expect actual
 164'
 165
 166test_expect_success 'Fail conflicting merge with conflicting dirty worktree' '
 167        test_must_fail git merge conflict_branch &&
 168        test ! -f .git/MERGE_HEAD &&
 169        test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 170        test -z "$(git diff --staged)" &&
 171        git diff > actual &&
 172        test_cmp expect actual
 173'
 174
 175test_expect_success 'Reset worktree changes' '
 176        git reset --hard "$pre_merge_head"
 177'
 178
 179test_expect_success 'Fail clean merge with matching dirty worktree' '
 180        echo bart > bar &&
 181        git diff > expect &&
 182        test_must_fail git merge --no-commit clean_branch &&
 183        test ! -f .git/MERGE_HEAD &&
 184        test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 185        test -z "$(git diff --staged)" &&
 186        git diff > actual &&
 187        test_cmp expect actual
 188'
 189
 190test_expect_success 'Abort clean merge with matching dirty index' '
 191        git add bar &&
 192        git diff --staged > expect &&
 193        git merge --no-commit clean_branch &&
 194        test -f .git/MERGE_HEAD &&
 195        ### When aborting the merge, git will discard all staged changes,
 196        ### including those that were staged pre-merge. In other words,
 197        ### --abort will LOSE any staged changes (the staged changes that
 198        ### are lost must match the merge result, or the merge would not
 199        ### have been allowed to start). Change expectations accordingly:
 200        rm expect &&
 201        touch expect &&
 202        # Abort merge
 203        git merge --abort &&
 204        test ! -f .git/MERGE_HEAD &&
 205        test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 206        git diff --staged > actual &&
 207        test_cmp expect actual &&
 208        test -z "$(git diff)"
 209'
 210
 211test_expect_success 'Reset worktree changes' '
 212        git reset --hard "$pre_merge_head"
 213'
 214
 215test_expect_success 'Fail conflicting merge with matching dirty worktree' '
 216        echo barf > bar &&
 217        git diff > expect &&
 218        test_must_fail git merge conflict_branch &&
 219        test ! -f .git/MERGE_HEAD &&
 220        test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 221        test -z "$(git diff --staged)" &&
 222        git diff > actual &&
 223        test_cmp expect actual
 224'
 225
 226test_expect_success 'Abort conflicting merge with matching dirty index' '
 227        git add bar &&
 228        git diff --staged > expect &&
 229        test_must_fail git merge conflict_branch &&
 230        test -f .git/MERGE_HEAD &&
 231        ### When aborting the merge, git will discard all staged changes,
 232        ### including those that were staged pre-merge. In other words,
 233        ### --abort will LOSE any staged changes (the staged changes that
 234        ### are lost must match the merge result, or the merge would not
 235        ### have been allowed to start). Change expectations accordingly:
 236        rm expect &&
 237        touch expect &&
 238        # Abort merge
 239        git merge --abort &&
 240        test ! -f .git/MERGE_HEAD &&
 241        test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 242        git diff --staged > actual &&
 243        test_cmp expect actual &&
 244        test -z "$(git diff)"
 245'
 246
 247test_expect_success 'Reset worktree changes' '
 248        git reset --hard "$pre_merge_head"
 249'
 250
 251test_expect_success 'Abort merge with pre- and post-merge worktree changes' '
 252        # Pre-merge worktree changes
 253        echo xyzzy > foo &&
 254        echo barf > bar &&
 255        git add bar &&
 256        git diff > expect &&
 257        git diff --staged > expect-staged &&
 258        # Perform merge
 259        test_must_fail git merge conflict_branch &&
 260        test -f .git/MERGE_HEAD &&
 261        # Post-merge worktree changes
 262        echo yzxxz > foo &&
 263        echo blech > baz &&
 264        ### When aborting the merge, git will discard staged changes (bar)
 265        ### and unmerged changes (baz). Other changes that are neither
 266        ### staged nor marked as unmerged (foo), will be preserved. For
 267        ### these changed, git cannot tell pre-merge changes apart from
 268        ### post-merge changes, so the post-merge changes will be
 269        ### preserved. Change expectations accordingly:
 270        git diff -- foo > expect &&
 271        rm expect-staged &&
 272        touch expect-staged &&
 273        # Abort merge
 274        git merge --abort &&
 275        test ! -f .git/MERGE_HEAD &&
 276        test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 277        git diff > actual &&
 278        test_cmp expect actual &&
 279        git diff --staged > actual-staged &&
 280        test_cmp expect-staged actual-staged
 281'
 282
 283test_expect_success 'Reset worktree changes' '
 284        git reset --hard "$pre_merge_head"
 285'
 286
 287test_expect_success 'Abort merge with pre- and post-merge index changes' '
 288        # Pre-merge worktree changes
 289        echo xyzzy > foo &&
 290        echo barf > bar &&
 291        git add bar &&
 292        git diff > expect &&
 293        git diff --staged > expect-staged &&
 294        # Perform merge
 295        test_must_fail git merge conflict_branch &&
 296        test -f .git/MERGE_HEAD &&
 297        # Post-merge worktree changes
 298        echo yzxxz > foo &&
 299        echo blech > baz &&
 300        git add foo bar &&
 301        ### When aborting the merge, git will discard all staged changes
 302        ### (foo, bar and baz), and no changes will be preserved. Whether
 303        ### the changes were staged pre- or post-merge does not matter
 304        ### (except for not preventing starting the merge).
 305        ### Change expectations accordingly:
 306        rm expect expect-staged &&
 307        touch expect &&
 308        touch expect-staged &&
 309        # Abort merge
 310        git merge --abort &&
 311        test ! -f .git/MERGE_HEAD &&
 312        test "$pre_merge_head" = "$(git rev-parse HEAD)" &&
 313        git diff > actual &&
 314        test_cmp expect actual &&
 315        git diff --staged > actual-staged &&
 316        test_cmp expect-staged actual-staged
 317'
 318
 319test_done