t / t6036-recursive-corner-cases.shon commit t6036: Add differently resolved modify/delete conflict in criss-cross test (fe7e9c2)
   1#!/bin/sh
   2
   3test_description='recursive merge corner cases involving criss-cross merges'
   4
   5. ./test-lib.sh
   6
   7#
   8#  L1  L2
   9#   o---o
  10#  / \ / \
  11# o   X   ?
  12#  \ / \ /
  13#   o---o
  14#  R1  R2
  15#
  16
  17test_expect_success 'setup basic criss-cross + rename with no modifications' '
  18        ten="0 1 2 3 4 5 6 7 8 9" &&
  19        for i in $ten
  20        do
  21                echo line $i in a sample file
  22        done >one &&
  23        for i in $ten
  24        do
  25                echo line $i in another sample file
  26        done >two &&
  27        git add one two &&
  28        test_tick && git commit -m initial &&
  29
  30        git branch L1 &&
  31        git checkout -b R1 &&
  32        git mv one three &&
  33        test_tick && git commit -m R1 &&
  34
  35        git checkout L1 &&
  36        git mv two three &&
  37        test_tick && git commit -m L1 &&
  38
  39        git checkout L1^0 &&
  40        test_tick && git merge -s ours R1 &&
  41        git tag L2 &&
  42
  43        git checkout R1^0 &&
  44        test_tick && git merge -s ours L1 &&
  45        git tag R2
  46'
  47
  48test_expect_success 'merge simple rename+criss-cross with no modifications' '
  49        git reset --hard &&
  50        git checkout L2^0 &&
  51
  52        test_must_fail git merge -s recursive R2^0 &&
  53
  54        test 5 = $(git ls-files -s | wc -l) &&
  55        test 3 = $(git ls-files -u | wc -l) &&
  56        test 0 = $(git ls-files -o | wc -l) &&
  57
  58        test $(git rev-parse :0:one) = $(git rev-parse L2:one) &&
  59        test $(git rev-parse :0:two) = $(git rev-parse R2:two) &&
  60        test $(git rev-parse :2:three) = $(git rev-parse L2:three) &&
  61        test $(git rev-parse :3:three) = $(git rev-parse R2:three) &&
  62
  63        cp two merged &&
  64        >empty &&
  65        test_must_fail git merge-file \
  66                -L "Temporary merge branch 2" \
  67                -L "" \
  68                -L "Temporary merge branch 1" \
  69                merged empty one &&
  70        test $(git rev-parse :1:three) = $(git hash-object merged)
  71'
  72
  73#
  74# Same as before, but modify L1 slightly:
  75#
  76#  L1m L2
  77#   o---o
  78#  / \ / \
  79# o   X   ?
  80#  \ / \ /
  81#   o---o
  82#  R1  R2
  83#
  84
  85test_expect_success 'setup criss-cross + rename merges with basic modification' '
  86        git rm -rf . &&
  87        git clean -fdqx &&
  88        rm -rf .git &&
  89        git init &&
  90
  91        ten="0 1 2 3 4 5 6 7 8 9"
  92        for i in $ten
  93        do
  94                echo line $i in a sample file
  95        done >one &&
  96        for i in $ten
  97        do
  98                echo line $i in another sample file
  99        done >two &&
 100        git add one two &&
 101        test_tick && git commit -m initial &&
 102
 103        git branch L1 &&
 104        git checkout -b R1 &&
 105        git mv one three &&
 106        echo more >>two &&
 107        git add two &&
 108        test_tick && git commit -m R1 &&
 109
 110        git checkout L1 &&
 111        git mv two three &&
 112        test_tick && git commit -m L1 &&
 113
 114        git checkout L1^0 &&
 115        test_tick && git merge -s ours R1 &&
 116        git tag L2 &&
 117
 118        git checkout R1^0 &&
 119        test_tick && git merge -s ours L1 &&
 120        git tag R2
 121'
 122
 123test_expect_success 'merge criss-cross + rename merges with basic modification' '
 124        git reset --hard &&
 125        git checkout L2^0 &&
 126
 127        test_must_fail git merge -s recursive R2^0 &&
 128
 129        test 5 = $(git ls-files -s | wc -l) &&
 130        test 3 = $(git ls-files -u | wc -l) &&
 131        test 0 = $(git ls-files -o | wc -l) &&
 132
 133        test $(git rev-parse :0:one) = $(git rev-parse L2:one) &&
 134        test $(git rev-parse :0:two) = $(git rev-parse R2:two) &&
 135        test $(git rev-parse :2:three) = $(git rev-parse L2:three) &&
 136        test $(git rev-parse :3:three) = $(git rev-parse R2:three) &&
 137
 138        head -n 10 two >merged &&
 139        cp one merge-me &&
 140        >empty &&
 141        test_must_fail git merge-file \
 142                -L "Temporary merge branch 2" \
 143                -L "" \
 144                -L "Temporary merge branch 1" \
 145                merged empty merge-me &&
 146        test $(git rev-parse :1:three) = $(git hash-object merged)
 147'
 148
 149#
 150# For the next test, we start with three commits in two lines of development
 151# which setup a rename/add conflict:
 152#   Commit A: File 'a' exists
 153#   Commit B: Rename 'a' -> 'new_a'
 154#   Commit C: Modify 'a', create different 'new_a'
 155# Later, two different people merge and resolve differently:
 156#   Commit D: Merge B & C, ignoring separately created 'new_a'
 157#   Commit E: Merge B & C making use of some piece of secondary 'new_a'
 158# Finally, someone goes to merge D & E.  Does git detect the conflict?
 159#
 160#      B   D
 161#      o---o
 162#     / \ / \
 163#  A o   X   ? F
 164#     \ / \ /
 165#      o---o
 166#      C   E
 167#
 168
 169test_expect_success 'setup differently handled merges of rename/add conflict' '
 170        git rm -rf . &&
 171        git clean -fdqx &&
 172        rm -rf .git &&
 173        git init &&
 174
 175        printf "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n" >a &&
 176        git add a &&
 177        test_tick && git commit -m A &&
 178
 179        git branch B &&
 180        git checkout -b C &&
 181        echo 10 >>a &&
 182        echo "other content" >>new_a &&
 183        git add a new_a &&
 184        test_tick && git commit -m C &&
 185
 186        git checkout B &&
 187        git mv a new_a &&
 188        test_tick && git commit -m B &&
 189
 190        git checkout B^0 &&
 191        test_must_fail git merge C &&
 192        git clean -f &&
 193        test_tick && git commit -m D &&
 194        git tag D &&
 195
 196        git checkout C^0 &&
 197        test_must_fail git merge B &&
 198        rm new_a~HEAD new_a &&
 199        printf "Incorrectly merged content" >>new_a &&
 200        git add -u &&
 201        test_tick && git commit -m E &&
 202        git tag E
 203'
 204
 205test_expect_success 'git detects differently handled merges conflict' '
 206        git reset --hard &&
 207        git checkout D^0 &&
 208
 209        git merge -s recursive E^0 && {
 210                echo "BAD: should have conflicted"
 211                test "Incorrectly merged content" = "$(cat new_a)" &&
 212                        echo "BAD: Silently accepted wrong content"
 213                return 1
 214        }
 215
 216        test 3 = $(git ls-files -s | wc -l) &&
 217        test 3 = $(git ls-files -u | wc -l) &&
 218        test 0 = $(git ls-files -o | wc -l) &&
 219
 220        test $(git rev-parse :2:new_a) = $(git rev-parse D:new_a) &&
 221        test $(git rev-parse :3:new_a) = $(git rev-parse E:new_a) &&
 222
 223        git cat-file -p B:new_a >>merged &&
 224        git cat-file -p C:new_a >>merge-me &&
 225        >empty &&
 226        test_must_fail git merge-file \
 227                -L "Temporary merge branch 2" \
 228                -L "" \
 229                -L "Temporary merge branch 1" \
 230                merged empty merge-me &&
 231        test $(git rev-parse :1:new_a) = $(git hash-object merged)
 232'
 233
 234#
 235# criss-cross + modify/delete:
 236#
 237#      B   D
 238#      o---o
 239#     / \ / \
 240#  A o   X   ? F
 241#     \ / \ /
 242#      o---o
 243#      C   E
 244#
 245#   Commit A: file with contents 'A\n'
 246#   Commit B: file with contents 'B\n'
 247#   Commit C: file not present
 248#   Commit D: file with contents 'B\n'
 249#   Commit E: file not present
 250#
 251# Merging commits D & E should result in modify/delete conflict.
 252
 253test_expect_success 'setup criss-cross + modify/delete resolved differently' '
 254        git rm -rf . &&
 255        git clean -fdqx &&
 256        rm -rf .git &&
 257        git init &&
 258
 259        echo A >file &&
 260        git add file &&
 261        test_tick &&
 262        git commit -m A &&
 263
 264        git branch B &&
 265        git checkout -b C &&
 266        git rm file &&
 267        test_tick &&
 268        git commit -m C &&
 269
 270        git checkout B &&
 271        echo B >file &&
 272        git add file &&
 273        test_tick &&
 274        git commit -m B &&
 275
 276        git checkout B^0 &&
 277        test_must_fail git merge C &&
 278        echo B >file &&
 279        git add file &&
 280        test_tick &&
 281        git commit -m D &&
 282        git tag D &&
 283
 284        git checkout C^0 &&
 285        test_must_fail git merge B &&
 286        git rm file &&
 287        test_tick &&
 288        git commit -m E &&
 289        git tag E
 290'
 291
 292test_expect_failure 'git detects conflict merging criss-cross+modify/delete' '
 293        git checkout D^0 &&
 294
 295        test_must_fail git merge -s recursive E^0 &&
 296
 297        test 2 -eq $(git ls-files -s | wc -l) &&
 298        test 2 -eq $(git ls-files -u | wc -l) &&
 299
 300        test $(git rev-parse :1:file) = $(git rev-parse master:file) &&
 301        test $(git rev-parse :2:file) = $(git rev-parse B:file)
 302'
 303
 304test_expect_failure 'git detects conflict merging criss-cross+modify/delete, reverse direction' '
 305        git reset --hard &&
 306        git checkout E^0 &&
 307
 308        test_must_fail git merge -s recursive D^0 &&
 309
 310        test 2 -eq $(git ls-files -s | wc -l) &&
 311        test 2 -eq $(git ls-files -u | wc -l) &&
 312
 313        test $(git rev-parse :1:file) = $(git rev-parse master:file) &&
 314        test $(git rev-parse :3:file) = $(git rev-parse B:file)
 315'
 316
 317test_done