Merge branch 'jc/maint-rev-list-culled-boundary'
[git] / t / t6036-recursive-corner-cases.sh
1 #!/bin/sh
2
3 test_description='recursive merge corner cases'
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
17 test_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
48 test_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
85 test_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
123 test_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
169 test_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
205 test_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 test_done