1#!/bin/sh 2# 3# Copyright (c) 2005 Junio C Hamano 4# 5 6test_description='Three way merge with read-tree -m 7 8This test tries three-way merge with read-tree -m 9 10There is one ancestor (called O for Original) and two branches A 11and B derived from it. We want to do a 3-way merge between A and 12B, using O as the common ancestor. 13 14 merge A O B 15 16Decisions are made by comparing contents of O, A and B pathname 17by pathname. The result is determined by the following guiding 18principle: 19 20 - If only A does something to it and B does not touch it, take 21 whatever A does. 22 23 - If only B does something to it and A does not touch it, take 24 whatever B does. 25 26 - If both A and B does something but in the same way, take 27 whatever they do. 28 29 - If A and B does something but different things, we need a 30 3-way merge: 31 32 - We cannot do anything about the following cases: 33 34 * O does not have it. A and B both must be adding to the 35 same path independently. 36 37 * A deletes it. B must be modifying. 38 39 - Otherwise, A and B are modifying. Run 3-way merge. 40 41First, the case matrix. 42 43 - Vertical axis is for A'\''s actions. 44 - Horizontal axis is for B'\''s actions. 45 46.----------------------------------------------------------------. 47| A B | No Action | Delete | Modify | Add | 48|------------+------------+------------+------------+------------| 49| No Action | | | | | 50| | select O | delete | select B | select B | 51| | | | | | 52|------------+------------+------------+------------+------------| 53| Delete | | | ********** | can | 54| | delete | delete | merge | not | 55| | | | | happen | 56|------------+------------+------------+------------+------------| 57| Modify | | ********** | ?????????? | can | 58| | select A | merge | select A=B | not | 59| | | | merge | happen | 60|------------+------------+------------+------------+------------| 61| Add | | can | can | ?????????? | 62| | select A | not | not | select A=B | 63| | | happen | happen | merge | 64.----------------------------------------------------------------. 65 66In addition: 67 68 SS: a special case of MM, where A and B makes the same modification. 69 LL: a special case of AA, where A and B creates the same file. 70 TT: a special case of MM, where A and B makes mergeable changes. 71 DF: a special case, where A makes a directory and B makes a file. 72 73' 74. ./test-lib.sh 75. "$TEST_DIRECTORY"/lib-read-tree.sh 76. "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh 77 78################################################################ 79# Trivial "majority when 3 stages exist" merge plus #2ALT, #3ALT 80# and #5ALT trivial merges. 81 82cat>expected <<\EOF 83100644 X 2 AA 84100644 X 3 AA 85100644 X 0 AN 86100644 X 1 DD 87100644 X 3 DF 88100644 X 2 DF/DF 89100644 X 1 DM 90100644 X 3 DM 91100644 X 1 DN 92100644 X 3 DN 93100644 X 0 LL 94100644 X 1 MD 95100644 X 2 MD 96100644 X 1 MM 97100644 X 2 MM 98100644 X 3 MM 99100644 X 0 MN 100100644 X 0 NA 101100644 X 1 ND 102100644 X 2 ND 103100644 X 0 NM 104100644 X 0 NN 105100644 X 0 SS 106100644 X 1 TT 107100644 X 2 TT 108100644 X 3 TT 109100644 X 2 Z/AA 110100644 X 3 Z/AA 111100644 X 0 Z/AN 112100644 X 1 Z/DD 113100644 X 1 Z/DM 114100644 X 3 Z/DM 115100644 X 1 Z/DN 116100644 X 3 Z/DN 117100644 X 1 Z/MD 118100644 X 2 Z/MD 119100644 X 1 Z/MM 120100644 X 2 Z/MM 121100644 X 3 Z/MM 122100644 X 0 Z/MN 123100644 X 0 Z/NA 124100644 X 1 Z/ND 125100644 X 2 Z/ND 126100644 X 0 Z/NM 127100644 X 0 Z/NN 128EOF 129 130check_result () { 131 git ls-files --stage|sed-e's/ '"$_x40"' / X /'>current && 132 test_cmp expected current 133} 134 135# This is done on an empty work directory, which is the normal 136# merge person behaviour. 137test_expect_success \ 138'3-way merge with git read-tree -m, empty cache' \ 139"rm -fr [NDMALTS][NDMALTSF] Z && 140 rm .git/index && 141 read_tree_must_succeed -m$tree_O$tree_A$tree_B&& 142 check_result" 143 144# This starts out with the first head, which is the normal 145# patch submitter behaviour. 146test_expect_success \ 147'3-way merge with git read-tree -m, match H' \ 148"rm -fr [NDMALTS][NDMALTSF] Z && 149 rm .git/index && 150 read_tree_must_succeed$tree_A&& 151 git checkout-index -f -u -a && 152 read_tree_must_succeed -m$tree_O$tree_A$tree_B&& 153 check_result" 154 155: <<\END_OF_CASE_TABLE 156 157We have so far tested only empty index and clean-and-matching-A index 158casewhich are trivial. Make sure index requirements are also 159checked. 160 161"git read-tree -m O A B" 162 163 O A B result index requirements 164------------------------------------------------------------------- 1651 missing missing missing - must not exist. 166------------------------------------------------------------------ 1672 missing missing exists take B* must match B,if exists. 168------------------------------------------------------------------ 1693 missing exists missing take A* must match A,if exists. 170------------------------------------------------------------------ 1714 missing exists A!=B no merge must match A and be 172 up-to-date,if exists. 173------------------------------------------------------------------ 1745 missing exists A==B take A must match A,if exists. 175------------------------------------------------------------------ 1766 exists missing missing remove must not exist. 177------------------------------------------------------------------ 1787 exists missing O!=B no merge must not exist. 179------------------------------------------------------------------ 1808 exists missing O==B remove must not exist. 181------------------------------------------------------------------ 1829 exists O!=A missing no merge must match A and be 183 up-to-date,if exists. 184------------------------------------------------------------------ 18510 exists O==A missing no merge must match A 186------------------------------------------------------------------ 18711 exists O!=A O!=B no merge must match A and be 188 A!=B up-to-date,if exists. 189------------------------------------------------------------------ 19012 exists O!=A O!=B take A must match A,if exists. 191 A==B 192------------------------------------------------------------------ 19313 exists O!=A O==B take A must match A,if exists. 194------------------------------------------------------------------ 19514 exists O==A O!=B take B if exists, must either (1) 196 match A and be up-to-date, 197 or (2) match B. 198------------------------------------------------------------------ 19915 exists O==A O==B take B must match A if exists. 200------------------------------------------------------------------ 20116 exists O==A O==B barf must match A if exists. 202*multi*in one in another 203------------------------------------------------------------------- 204 205Note: we need to be careful in case2 and 3. The tree A may contain 206DF (file) when tree B require DF to be a directory by having DF/DF 207(file). 208 209END_OF_CASE_TABLE 210 211test_expect_success '1 - must not have an entry not in A.'" 212 rm -f .git/index XX && 213 echo XX >XX && 214 git update-index --add XX && 215 read_tree_must_fail -m$tree_O$tree_A$tree_B 216" 217 218test_expect_success \ 219'2 - must match B in !O && !A && B case.' \ 220"rm -f .git/index NA && 221 cp .orig-B/NA NA && 222 git update-index --add NA && 223 read_tree_must_succeed -m$tree_O$tree_A$tree_B" 224 225test_expect_success \ 226'2 - matching B alone is OK in !O && !A && B case.' \ 227"rm -f .git/index NA && 228 cp .orig-B/NA NA && 229 git update-index --add NA && 230 echo extra >>NA && 231 read_tree_must_succeed -m$tree_O$tree_A$tree_B" 232 233test_expect_success \ 234'3 - must match A in !O && A && !B case.' \ 235"rm -f .git/index AN && 236 cp .orig-A/AN AN && 237 git update-index --add AN && 238 read_tree_must_succeed -m$tree_O$tree_A$tree_B&& 239 check_result" 240 241test_expect_success \ 242'3 - matching A alone is OK in !O && A && !B case.' \ 243"rm -f .git/index AN && 244 cp .orig-A/AN AN && 245 git update-index --add AN && 246 echo extra >>AN && 247 read_tree_must_succeed -m$tree_O$tree_A$tree_B" 248 249test_expect_success \ 250'3 (fail) - must match A in !O && A && !B case.'" 251 rm -f .git/index AN && 252 cp .orig-A/AN AN && 253 echo extra >>AN && 254 git update-index --add AN && 255 read_tree_must_fail -m$tree_O$tree_A$tree_B 256" 257 258test_expect_success \ 259'4 - must match and be up-to-date in !O && A && B && A!=B case.' \ 260"rm -f .git/index AA && 261 cp .orig-A/AA AA && 262 git update-index --add AA && 263 read_tree_must_succeed -m$tree_O$tree_A$tree_B&& 264 check_result" 265 266test_expect_success \ 267'4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.'" 268 rm -f .git/index AA && 269 cp .orig-A/AA AA && 270 git update-index --add AA && 271 echo extra >>AA && 272 read_tree_must_fail -m$tree_O$tree_A$tree_B 273" 274 275test_expect_success \ 276'4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.'" 277 rm -f .git/index AA && 278 cp .orig-A/AA AA && 279 echo extra >>AA && 280 git update-index --add AA && 281 read_tree_must_fail -m$tree_O$tree_A$tree_B 282" 283 284test_expect_success \ 285'5 - must match in !O && A && B && A==B case.' \ 286"rm -f .git/index LL && 287 cp .orig-A/LL LL && 288 git update-index --add LL && 289 read_tree_must_succeed -m$tree_O$tree_A$tree_B&& 290 check_result" 291 292test_expect_success \ 293'5 - must match in !O && A && B && A==B case.' \ 294"rm -f .git/index LL && 295 cp .orig-A/LL LL && 296 git update-index --add LL && 297 echo extra >>LL && 298 read_tree_must_succeed -m$tree_O$tree_A$tree_B&& 299 check_result" 300 301test_expect_success \ 302'5 (fail) - must match A in !O && A && B && A==B case.'" 303 rm -f .git/index LL && 304 cp .orig-A/LL LL && 305 echo extra >>LL && 306 git update-index --add LL && 307 read_tree_must_fail -m$tree_O$tree_A$tree_B 308" 309 310test_expect_success \ 311'6 - must not exist in O && !A && !B case'" 312 rm -f .git/index DD && 313 echo DD >DD && 314 git update-index --add DD && 315 read_tree_must_fail -m$tree_O$tree_A$tree_B 316" 317 318test_expect_success \ 319'7 - must not exist in O && !A && B && O!=B case'" 320 rm -f .git/index DM && 321 cp .orig-B/DM DM && 322 git update-index --add DM && 323 read_tree_must_fail -m$tree_O$tree_A$tree_B 324" 325 326test_expect_success \ 327'8 - must not exist in O && !A && B && O==B case'" 328 rm -f .git/index DN && 329 cp .orig-B/DN DN && 330 git update-index --add DN && 331 read_tree_must_fail -m$tree_O$tree_A$tree_B 332" 333 334test_expect_success \ 335'9 - must match and be up-to-date in O && A && !B && O!=A case' \ 336"rm -f .git/index MD && 337 cp .orig-A/MD MD && 338 git update-index --add MD && 339 read_tree_must_succeed -m$tree_O$tree_A$tree_B&& 340 check_result" 341 342test_expect_success \ 343'9 (fail) - must match and be up-to-date in O && A && !B && O!=A case'" 344 rm -f .git/index MD && 345 cp .orig-A/MD MD && 346 git update-index --add MD && 347 echo extra >>MD && 348 read_tree_must_fail -m$tree_O$tree_A$tree_B 349" 350 351test_expect_success \ 352'9 (fail) - must match and be up-to-date in O && A && !B && O!=A case'" 353 rm -f .git/index MD && 354 cp .orig-A/MD MD && 355 echo extra >>MD && 356 git update-index --add MD && 357 read_tree_must_fail -m$tree_O$tree_A$tree_B 358" 359 360test_expect_success \ 361'10 - must match and be up-to-date in O && A && !B && O==A case' \ 362"rm -f .git/index ND && 363 cp .orig-A/ND ND && 364 git update-index --add ND && 365 read_tree_must_succeed -m$tree_O$tree_A$tree_B&& 366 check_result" 367 368test_expect_success \ 369'10 (fail) - must match and be up-to-date in O && A && !B && O==A case'" 370 rm -f .git/index ND && 371 cp .orig-A/ND ND && 372 git update-index --add ND && 373 echo extra >>ND && 374 read_tree_must_fail -m$tree_O$tree_A$tree_B 375" 376 377test_expect_success \ 378'10 (fail) - must match and be up-to-date in O && A && !B && O==A case'" 379 rm -f .git/index ND && 380 cp .orig-A/ND ND && 381 echo extra >>ND && 382 git update-index --add ND && 383 read_tree_must_fail -m$tree_O$tree_A$tree_B 384" 385 386test_expect_success \ 387'11 - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' \ 388"rm -f .git/index MM && 389 cp .orig-A/MM MM && 390 git update-index --add MM && 391 read_tree_must_succeed -m$tree_O$tree_A$tree_B&& 392 check_result" 393 394test_expect_success \ 395'11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case'" 396 rm -f .git/index MM && 397 cp .orig-A/MM MM && 398 git update-index --add MM && 399 echo extra >>MM && 400 read_tree_must_fail -m$tree_O$tree_A$tree_B 401" 402 403test_expect_success \ 404'11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case'" 405 rm -f .git/index MM && 406 cp .orig-A/MM MM && 407 echo extra >>MM && 408 git update-index --add MM && 409 read_tree_must_fail -m$tree_O$tree_A$tree_B 410" 411 412test_expect_success \ 413'12 - must match A in O && A && B && O!=A && A==B case' \ 414"rm -f .git/index SS && 415 cp .orig-A/SS SS && 416 git update-index --add SS && 417 read_tree_must_succeed -m$tree_O$tree_A$tree_B&& 418 check_result" 419 420test_expect_success \ 421'12 - must match A in O && A && B && O!=A && A==B case' \ 422"rm -f .git/index SS && 423 cp .orig-A/SS SS && 424 git update-index --add SS && 425 echo extra >>SS && 426 read_tree_must_succeed -m$tree_O$tree_A$tree_B&& 427 check_result" 428 429test_expect_success \ 430'12 (fail) - must match A in O && A && B && O!=A && A==B case'" 431 rm -f .git/index SS && 432 cp .orig-A/SS SS && 433 echo extra >>SS && 434 git update-index --add SS && 435 read_tree_must_fail -m$tree_O$tree_A$tree_B 436" 437 438test_expect_success \ 439'13 - must match A in O && A && B && O!=A && O==B case' \ 440"rm -f .git/index MN && 441 cp .orig-A/MN MN && 442 git update-index --add MN && 443 read_tree_must_succeed -m$tree_O$tree_A$tree_B&& 444 check_result" 445 446test_expect_success \ 447'13 - must match A in O && A && B && O!=A && O==B case' \ 448"rm -f .git/index MN && 449 cp .orig-A/MN MN && 450 git update-index --add MN && 451 echo extra >>MN && 452 read_tree_must_succeed -m$tree_O$tree_A$tree_B&& 453 check_result" 454 455test_expect_success \ 456'14 - must match and be up-to-date in O && A && B && O==A && O!=B case' \ 457"rm -f .git/index NM && 458 cp .orig-A/NM NM && 459 git update-index --add NM && 460 read_tree_must_succeed -m$tree_O$tree_A$tree_B&& 461 check_result" 462 463test_expect_success \ 464'14 - may match B in O && A && B && O==A && O!=B case' \ 465"rm -f .git/index NM && 466 cp .orig-B/NM NM && 467 git update-index --add NM && 468 echo extra >>NM && 469 read_tree_must_succeed -m$tree_O$tree_A$tree_B&& 470 check_result" 471 472test_expect_success \ 473'14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case'" 474 rm -f .git/index NM && 475 cp .orig-A/NM NM && 476 git update-index --add NM && 477 echo extra >>NM && 478 read_tree_must_fail -m$tree_O$tree_A$tree_B 479" 480 481test_expect_success \ 482'14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case'" 483 rm -f .git/index NM && 484 cp .orig-A/NM NM && 485 echo extra >>NM && 486 git update-index --add NM && 487 read_tree_must_fail -m$tree_O$tree_A$tree_B 488" 489 490test_expect_success \ 491'15 - must match A in O && A && B && O==A && O==B case' \ 492"rm -f .git/index NN && 493 cp .orig-A/NN NN && 494 git update-index --add NN && 495 read_tree_must_succeed -m$tree_O$tree_A$tree_B&& 496 check_result" 497 498test_expect_success \ 499'15 - must match A in O && A && B && O==A && O==B case' \ 500"rm -f .git/index NN && 501 cp .orig-A/NN NN && 502 git update-index --add NN && 503 echo extra >>NN && 504 read_tree_must_succeed -m$tree_O$tree_A$tree_B&& 505 check_result" 506 507test_expect_success \ 508'15 (fail) - must match A in O && A && B && O==A && O==B case'" 509 rm -f .git/index NN && 510 cp .orig-A/NN NN && 511 echo extra >>NN && 512 git update-index --add NN && 513 read_tree_must_fail -m$tree_O$tree_A$tree_B 514" 515 516# #16 517test_expect_success \ 518'16 - A matches in one and B matches in another.' \ 519'rm -f .git/index F16 && 520 echo F16 >F16 && 521 git update-index --add F16 && 522 tree0=$(git write-tree)&& 523 echo E16 >F16 && 524 git update-index F16 && 525 tree1=$(git write-tree)&& 526 read_tree_must_succeed -m$tree0$tree1$tree1$tree0&& 527 git ls-files --stage' 528 529test_done