1#!/bin/sh
2
3test_description='Merge-recursive merging renames'
4. ./test-lib.sh
5
6test_expect_success setup \
7'
8cat >A <<\EOF &&
9a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
10b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
11c cccccccccccccccccccccccccccccccccccccccccccccccc
12d dddddddddddddddddddddddddddddddddddddddddddddddd
13e eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
14f ffffffffffffffffffffffffffffffffffffffffffffffff
15g gggggggggggggggggggggggggggggggggggggggggggggggg
16h hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
17i iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
18j jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
19k kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
20l llllllllllllllllllllllllllllllllllllllllllllllll
21m mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
22n nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
23o oooooooooooooooooooooooooooooooooooooooooooooooo
24EOF
25
26cat >M <<\EOF &&
27A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
28B BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
29C CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
30D DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
31E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
32F FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
33G GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
34H HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
35I IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
36J JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
37K KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
38L LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
39M MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
40N NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
41O OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
42EOF
43
44git add A M &&
45git commit -m "initial has A and M" &&
46git branch white &&
47git branch red &&
48git branch blue &&
49git branch yellow &&
50git branch change &&
51git branch change+rename &&
52
53sed -e "/^g /s/.*/g : master changes a line/" <A >A+ &&
54mv A+ A &&
55git commit -a -m "master updates A" &&
56
57git checkout yellow &&
58rm -f M &&
59git commit -a -m "yellow removes M" &&
60
61git checkout white &&
62sed -e "/^g /s/.*/g : white changes a line/" <A >B &&
63sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N &&
64rm -f A M &&
65git update-index --add --remove A B M N &&
66git commit -m "white renames A->B, M->N" &&
67
68git checkout red &&
69sed -e "/^g /s/.*/g : red changes a line/" <A >B &&
70sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N &&
71rm -f A M &&
72git update-index --add --remove A B M N &&
73git commit -m "red renames A->B, M->N" &&
74
75git checkout blue &&
76sed -e "/^g /s/.*/g : blue changes a line/" <A >C &&
77sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N &&
78rm -f A M &&
79git update-index --add --remove A C M N &&
80git commit -m "blue renames A->C, M->N" &&
81
82git checkout change &&
83sed -e "/^g /s/.*/g : changed line/" <A >A+ &&
84mv A+ A &&
85git commit -q -a -m "changed" &&
86
87git checkout change+rename &&
88sed -e "/^g /s/.*/g : changed line/" <A >B &&
89rm A &&
90git update-index --add B &&
91git commit -q -a -m "changed and renamed" &&
92
93git checkout master'
94
95test_expect_success 'pull renaming branch into unrenaming one' \
96'
97 git show-branch
98 git pull . white && {
99 echo "BAD: should have conflicted"
100 return 1
101 }
102 git ls-files -s
103 test "$(git ls-files -u B | wc -l)" -eq 3 || {
104 echo "BAD: should have left stages for B"
105 return 1
106 }
107 test "$(git ls-files -s N | wc -l)" -eq 1 || {
108 echo "BAD: should have merged N"
109 return 1
110 }
111 sed -ne "/^g/{
112 p
113 q
114 }" B | grep master || {
115 echo "BAD: should have listed our change first"
116 return 1
117 }
118 test "$(git diff white N | wc -l)" -eq 0 || {
119 echo "BAD: should have taken colored branch"
120 return 1
121 }
122'
123
124test_expect_success 'pull renaming branch into another renaming one' \
125'
126 rm -f B
127 git reset --hard
128 git checkout red
129 git pull . white && {
130 echo "BAD: should have conflicted"
131 return 1
132 }
133 test "$(git ls-files -u B | wc -l)" -eq 3 || {
134 echo "BAD: should have left stages"
135 return 1
136 }
137 test "$(git ls-files -s N | wc -l)" -eq 1 || {
138 echo "BAD: should have merged N"
139 return 1
140 }
141 sed -ne "/^g/{
142 p
143 q
144 }" B | grep red || {
145 echo "BAD: should have listed our change first"
146 return 1
147 }
148 test "$(git diff white N | wc -l)" -eq 0 || {
149 echo "BAD: should have taken colored branch"
150 return 1
151 }
152'
153
154test_expect_success 'pull unrenaming branch into renaming one' \
155'
156 git reset --hard
157 git show-branch
158 git pull . master && {
159 echo "BAD: should have conflicted"
160 return 1
161 }
162 test "$(git ls-files -u B | wc -l)" -eq 3 || {
163 echo "BAD: should have left stages"
164 return 1
165 }
166 test "$(git ls-files -s N | wc -l)" -eq 1 || {
167 echo "BAD: should have merged N"
168 return 1
169 }
170 sed -ne "/^g/{
171 p
172 q
173 }" B | grep red || {
174 echo "BAD: should have listed our change first"
175 return 1
176 }
177 test "$(git diff white N | wc -l)" -eq 0 || {
178 echo "BAD: should have taken colored branch"
179 return 1
180 }
181'
182
183test_expect_success 'pull conflicting renames' \
184'
185 git reset --hard
186 git show-branch
187 git pull . blue && {
188 echo "BAD: should have conflicted"
189 return 1
190 }
191 test "$(git ls-files -u A | wc -l)" -eq 1 || {
192 echo "BAD: should have left a stage"
193 return 1
194 }
195 test "$(git ls-files -u B | wc -l)" -eq 1 || {
196 echo "BAD: should have left a stage"
197 return 1
198 }
199 test "$(git ls-files -u C | wc -l)" -eq 1 || {
200 echo "BAD: should have left a stage"
201 return 1
202 }
203 test "$(git ls-files -s N | wc -l)" -eq 1 || {
204 echo "BAD: should have merged N"
205 return 1
206 }
207 sed -ne "/^g/{
208 p
209 q
210 }" B | grep red || {
211 echo "BAD: should have listed our change first"
212 return 1
213 }
214 test "$(git diff white N | wc -l)" -eq 0 || {
215 echo "BAD: should have taken colored branch"
216 return 1
217 }
218'
219
220test_expect_success 'interference with untracked working tree file' '
221
222 git reset --hard
223 git show-branch
224 echo >A this file should not matter
225 git pull . white && {
226 echo "BAD: should have conflicted"
227 return 1
228 }
229 test -f A || {
230 echo "BAD: should have left A intact"
231 return 1
232 }
233'
234
235test_expect_success 'interference with untracked working tree file' '
236
237 git reset --hard
238 git checkout white
239 git show-branch
240 rm -f A
241 echo >A this file should not matter
242 git pull . red && {
243 echo "BAD: should have conflicted"
244 return 1
245 }
246 test -f A || {
247 echo "BAD: should have left A intact"
248 return 1
249 }
250'
251
252test_expect_success 'interference with untracked working tree file' '
253
254 git reset --hard
255 rm -f A M
256 git checkout -f master
257 git tag -f anchor
258 git show-branch
259 git pull . yellow || {
260 echo "BAD: should have cleanly merged"
261 return 1
262 }
263 test -f M && {
264 echo "BAD: should have removed M"
265 return 1
266 }
267 git reset --hard anchor
268'
269
270test_expect_success 'updated working tree file should prevent the merge' '
271
272 git reset --hard
273 rm -f A M
274 git checkout -f master
275 git tag -f anchor
276 git show-branch
277 echo >>M one line addition
278 cat M >M.saved
279 git pull . yellow && {
280 echo "BAD: should have complained"
281 return 1
282 }
283 test_cmp M M.saved || {
284 echo "BAD: should have left M intact"
285 return 1
286 }
287 rm -f M.saved
288'
289
290test_expect_success 'updated working tree file should prevent the merge' '
291
292 git reset --hard
293 rm -f A M
294 git checkout -f master
295 git tag -f anchor
296 git show-branch
297 echo >>M one line addition
298 cat M >M.saved
299 git update-index M
300 git pull . yellow && {
301 echo "BAD: should have complained"
302 return 1
303 }
304 test_cmp M M.saved || {
305 echo "BAD: should have left M intact"
306 return 1
307 }
308 rm -f M.saved
309'
310
311test_expect_success 'interference with untracked working tree file' '
312
313 git reset --hard
314 rm -f A M
315 git checkout -f yellow
316 git tag -f anchor
317 git show-branch
318 echo >M this file should not matter
319 git pull . master || {
320 echo "BAD: should have cleanly merged"
321 return 1
322 }
323 test -f M || {
324 echo "BAD: should have left M intact"
325 return 1
326 }
327 git ls-files -s | grep M && {
328 echo "BAD: M must be untracked in the result"
329 return 1
330 }
331 git reset --hard anchor
332'
333
334test_expect_success 'merge of identical changes in a renamed file' '
335 rm -f A M N
336 git reset --hard &&
337 git checkout change+rename &&
338 GIT_MERGE_VERBOSITY=3 git merge change | grep "^Skipped B" &&
339 git reset --hard HEAD^ &&
340 git checkout change &&
341 GIT_MERGE_VERBOSITY=3 git merge change+rename | grep "^Skipped B"
342'
343
344test_done