t / t6042-merge-rename-corner-cases.shon commit t6042: Add a testcase where undetected rename causes silent file deletion (a0551f2)
   1#!/bin/sh
   2
   3test_description="recursive merge corner cases w/ renames but not criss-crosses"
   4# t6036 has corner cases that involve both criss-cross merges and renames
   5
   6. ./test-lib.sh
   7
   8test_expect_success 'setup rename/delete + untracked file' '
   9        echo "A pretty inscription" >ring &&
  10        git add ring &&
  11        test_tick &&
  12        git commit -m beginning &&
  13
  14        git branch people &&
  15        git checkout -b rename-the-ring &&
  16        git mv ring one-ring-to-rule-them-all &&
  17        test_tick &&
  18        git commit -m fullname &&
  19
  20        git checkout people &&
  21        git rm ring &&
  22        echo gollum >owner &&
  23        git add owner &&
  24        test_tick &&
  25        git commit -m track-people-instead-of-objects &&
  26        echo "Myyy PRECIOUSSS" >ring
  27'
  28
  29test_expect_failure "Does git preserve Gollum's precious artifact?" '
  30        test_must_fail git merge -s recursive rename-the-ring &&
  31
  32        # Make sure git did not delete an untracked file
  33        test -f ring
  34'
  35
  36# Testcase setup for rename/modify/add-source:
  37#   Commit A: new file: a
  38#   Commit B: modify a slightly
  39#   Commit C: rename a->b, add completely different a
  40#
  41# We should be able to merge B & C cleanly
  42
  43test_expect_success 'setup rename/modify/add-source conflict' '
  44        git rm -rf . &&
  45        git clean -fdqx &&
  46        rm -rf .git &&
  47        git init &&
  48
  49        printf "1\n2\n3\n4\n5\n6\n7\n" >a &&
  50        git add a &&
  51        git commit -m A &&
  52        git tag A &&
  53
  54        git checkout -b B A &&
  55        echo 8 >>a &&
  56        git add a &&
  57        git commit -m B &&
  58
  59        git checkout -b C A &&
  60        git mv a b &&
  61        echo something completely different >a &&
  62        git add a &&
  63        git commit -m C
  64'
  65
  66test_expect_failure 'rename/modify/add-source conflict resolvable' '
  67        git checkout B^0 &&
  68
  69        git merge -s recursive C^0 &&
  70
  71        test $(git rev-parse B:a) = $(git rev-parse b) &&
  72        test $(git rev-parse C:a) = $(git rev-parse a)
  73'
  74
  75test_expect_success 'setup resolvable conflict missed if rename missed' '
  76        git rm -rf . &&
  77        git clean -fdqx &&
  78        rm -rf .git &&
  79        git init &&
  80
  81        printf "1\n2\n3\n4\n5\n" >a &&
  82        echo foo >b &&
  83        git add a b &&
  84        git commit -m A &&
  85        git tag A &&
  86
  87        git checkout -b B A &&
  88        git mv a c &&
  89        echo "Completely different content" >a &&
  90        git add a &&
  91        git commit -m B &&
  92
  93        git checkout -b C A &&
  94        echo 6 >>a &&
  95        git add a &&
  96        git commit -m C
  97'
  98
  99test_expect_failure 'conflict caused if rename not detected' '
 100        git checkout -q C^0 &&
 101        git merge -s recursive B^0 &&
 102
 103        test 3 -eq $(git ls-files -s | wc -l) &&
 104        test 0 -eq $(git ls-files -u | wc -l) &&
 105        test 0 -eq $(git ls-files -o | wc -l) &&
 106
 107        test 6 -eq $(wc -l < c) &&
 108        test $(git rev-parse HEAD:a) = $(git rev-parse B:a) &&
 109        test $(git rev-parse HEAD:b) = $(git rev-parse A:b)
 110'
 111
 112test_expect_success 'setup conflict resolved wrong if rename missed' '
 113        git reset --hard &&
 114        git clean -f &&
 115
 116        git checkout -b D A &&
 117        echo 7 >>a &&
 118        git add a &&
 119        git mv a c &&
 120        echo "Completely different content" >a &&
 121        git add a &&
 122        git commit -m D &&
 123
 124        git checkout -b E A &&
 125        git rm a &&
 126        echo "Completely different content" >>a &&
 127        git add a &&
 128        git commit -m E
 129'
 130
 131test_expect_failure 'missed conflict if rename not detected' '
 132        git checkout -q E^0 &&
 133        test_must_fail git merge -s recursive D^0
 134'
 135
 136# Tests for undetected rename/add-source causing a file to erroneously be
 137# deleted (and for mishandled rename/rename(1to1) causing the same issue).
 138#
 139# This test uses a rename/rename(1to1)+add-source conflict (1to1 means the
 140# same file is renamed on both sides to the same thing; it should trigger
 141# the 1to2 logic, which it would do if the add-source didn't cause issues
 142# for git's rename detection):
 143#   Commit A: new file: a
 144#   Commit B: rename a->b
 145#   Commit C: rename a->b, add unrelated a
 146
 147test_expect_success 'setup undetected rename/add-source causes data loss' '
 148        git rm -rf . &&
 149        git clean -fdqx &&
 150        rm -rf .git &&
 151        git init &&
 152
 153        printf "1\n2\n3\n4\n5\n" >a &&
 154        git add a &&
 155        git commit -m A &&
 156        git tag A &&
 157
 158        git checkout -b B A &&
 159        git mv a b &&
 160        git commit -m B &&
 161
 162        git checkout -b C A &&
 163        git mv a b &&
 164        echo foobar >a &&
 165        git add a &&
 166        git commit -m C
 167'
 168
 169test_expect_failure 'detect rename/add-source and preserve all data' '
 170        git checkout B^0 &&
 171
 172        git merge -s recursive C^0 &&
 173
 174        test 2 -eq $(git ls-files -s | wc -l) &&
 175        test 2 -eq $(git ls-files -u | wc -l) &&
 176        test 0 -eq $(git ls-files -o | wc -l) &&
 177
 178        test -f a &&
 179        test -f b &&
 180
 181        test $(git rev-parse HEAD:b) = $(git rev-parse A:a) &&
 182        test $(git rev-parse HEAD:a) = $(git rev-parse C:a)
 183'
 184
 185test_expect_failure 'detect rename/add-source and preserve all data, merge other way' '
 186        git checkout C^0 &&
 187
 188        git merge -s recursive B^0 &&
 189
 190        test 2 -eq $(git ls-files -s | wc -l) &&
 191        test 2 -eq $(git ls-files -u | wc -l) &&
 192        test 0 -eq $(git ls-files -o | wc -l) &&
 193
 194        test -f a &&
 195        test -f b &&
 196
 197        test $(git rev-parse HEAD:b) = $(git rev-parse A:a) &&
 198        test $(git rev-parse HEAD:a) = $(git rev-parse C:a)
 199'
 200
 201test_done