3 # Copyright (c) 2005 Junio C Hamano
6 test_description
='Two way merge with read-tree --emu23 $H $M
8 This test tries two-way merge (aka fast forward with carry forward).
10 There is the head (called H) and another commit (called M), which is
11 simply ahead of H. The index and the work tree contains a state that
12 is derived from H, but may also have local changes. This test checks
13 all the combinations described in the two-tree merge "carry forward"
14 rules, found in <Documentation/git-rev-tree.txt>.
16 In the test, these paths are used:
17 bozbar - in H, stays in M, modified from bozbar to gnusto
18 frotz - not in H added in M
19 nitfol - in H, stays in M unmodified
20 rezrov - in H, deleted in M
21 yomin - not in H nor M
26 git-read-tree
--emu23 "$1" "$2" &&
27 git-ls-files
--stage &&
28 git-merge-index ..
/..
/git-merge-one-file.sh
-a &&
32 _x40
='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
33 _x40
="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
36 -e '/^--- /d; /^+++ /d; /^@@ /d;' \
37 -e 's/^\([-+][0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /p' \
39 diff -u expected current
43 clean_if_empty
=`git-diff-files "$1"`
44 case "$clean_if_empty" in
45 '') echo "$1: clean" ;;
46 ?
*) echo "$1: dirty" ;;
48 case "$2,$clean_if_empty" in
58 git-ls-files
--stage |
sed -e "s/ $_x40 / X /" >current_stages
59 diff -u expected_stages current_stages
62 cat >bozbar-old
<<\EOF
63 This is a sample
file used
in two-way fast forward merge
64 tests. Its second line ends with a magic word bozbar
65 which will be modified by the merged
head to gnusto.
66 It has some extra lines so that external tools can
67 successfully merge independent changes made to later
68 lines
(such as this one
), avoiding line conflicts.
71 sed -e 's/bozbar/gnusto (earlier bozbar)/' bozbar-old
>bozbar-new
76 echo nitfol >nitfol &&
77 cat bozbar-old >bozbar &&
78 echo rezrov >rezrov &&
80 git-update-index --add nitfol bozbar rezrov &&
81 treeH=`git-write-tree` &&
85 cat bozbar-new >bozbar &&
86 git-update-index --add frotz bozbar --force-remove rezrov &&
87 git-ls-files --stage >M.out &&
88 treeM=`git-write-tree` &&
91 git-diff-tree $treeH $treeM'
93 # "read-tree -m H I+H M" but I is empty so this is "read-tree -m H H M".
95 # bozbar [O && A && B && O==A && O!=B (#14) ==> B] take M by read-tree
96 # frotz [!O && !A && B (#2) ==> B] take M by read-tree
97 # nitfol [O && A && B && O==A && O==B (#15) ==> B] take M by read-tree
98 # rezrov [O && A && !B && O==A (#10) ==> no merge] removed by script
100 # Earlier one did not have #2ALT so taking M was done by the script,
101 # which also updated the work tree and making frotz clean. With #2ALT,
102 # this is resolved by read-tree itself and the path is left dirty
103 # because we are not testing "read-tree -u --emu23".
104 test_expect_success \
105 '1, 2, 3 - no carry forward' \
107 read_tree_twoway $treeH $treeM &&
108 git-ls-files --stage >1-3.out &&
109 diff -u M.out 1-3.out &&
110 check_cache_at bozbar dirty &&
111 check_cache_at frotz dirty && # same as pure 2-way again.
112 check_cache_at nitfol dirty'
114 echo '+100644 X 0 yomin' >expected
116 test_expect_success \
117 '4 - carry forward local addition.' \
119 git-read-tree $treeH &&
120 git-checkout-index -u -f -q -a &&
121 git-update-index --add yomin &&
122 read_tree_twoway $treeH $treeM &&
123 git-ls-files --stage >4.out || return 1
124 diff -u M.out 4.out >4diff.out
125 compare_change 4diff.out expected &&
126 check_cache_at yomin clean'
128 # "read-tree -m H I+H M" where !H && !M; so (I+H) not being up-to-date
129 # should not matter. Thanks to #3ALT, this is now possible.
130 test_expect_success \
131 '5 - carry forward local addition.' \
133 git-read-tree $treeH &&
134 git-checkout-index -u -f -q -a &&
136 git-update-index --add yomin &&
137 echo yomin yomin >yomin &&
138 read_tree_twoway $treeH $treeM &&
139 git-ls-files --stage >5.out || return 1
140 diff -u M.out 5.out >5diff.out
141 compare_change 5diff.out expected &&
142 check_cache_at yomin dirty'
144 # "read-tree -m H I+H M" where !H && M && (I+H) == M, so this should
145 # succeed (even the entry is clean), now thanks to #5ALT.
146 test_expect_success \
147 '6 - local addition already has the same.' \
149 git-read-tree $treeH &&
150 git-checkout-index -u -f -q -a &&
151 git-update-index --add frotz &&
152 read_tree_twoway $treeH $treeM &&
153 git-ls-files --stage >6.out &&
154 diff -u M.out 6.out &&
155 check_cache_at frotz clean'
157 # Exactly the same pattern as above but with dirty cache. This also
158 # should succeed, now thanks to #5ALT.
159 test_expect_success \
160 '7 - local addition already has the same.' \
162 git-read-tree $treeH &&
163 git-checkout-index -u -f -q -a &&
165 git-update-index --add frotz &&
166 echo frotz frotz >frotz &&
167 read_tree_twoway $treeH $treeM &&
168 git-ls-files --stage >7.out &&
169 diff -u M.out 7.out &&
170 check_cache_at frotz dirty'
172 test_expect_success \
173 '8 - conflicting addition.' \
175 git-read-tree $treeH &&
176 git-checkout-index -u -f -q -a &&
177 echo frotz frotz >frotz &&
178 git-update-index --add frotz &&
179 if read_tree_twoway $treeH $treeM; then false; else :; fi'
181 test_expect_success \
182 '9 - conflicting addition.' \
184 git-read-tree $treeH &&
185 git-checkout-index -u -f -q -a &&
186 echo frotz frotz >frotz &&
187 git-update-index --add frotz &&
189 if read_tree_twoway $treeH $treeM; then false; else :; fi'
191 test_expect_success \
192 '10 - path removed.' \
194 git-read-tree $treeH &&
195 git-checkout-index -u -f -q -a &&
196 echo rezrov >rezrov &&
197 git-update-index --add rezrov &&
198 read_tree_twoway $treeH $treeM &&
199 git-ls-files --stage >10.out &&
200 diff -u M.out 10.out'
202 test_expect_success \
203 '11 - dirty path removed.' \
205 git-read-tree $treeH &&
206 git-checkout-index -u -f -q -a &&
207 echo rezrov >rezrov &&
208 git-update-index --add rezrov &&
209 echo rezrov rezrov >rezrov &&
210 if read_tree_twoway $treeH $treeM; then false; else :; fi'
212 test_expect_success \
213 '12 - unmatching local changes being removed.' \
215 git-read-tree $treeH &&
216 git-checkout-index -u -f -q -a &&
217 echo rezrov rezrov >rezrov &&
218 git-update-index --add rezrov &&
219 if read_tree_twoway $treeH $treeM; then false; else :; fi'
221 test_expect_success \
222 '13 - unmatching local changes being removed.' \
224 git-read-tree $treeH &&
225 git-checkout-index -u -f -q -a &&
226 echo rezrov rezrov >rezrov &&
227 git-update-index --add rezrov &&
228 echo rezrov >rezrov &&
229 if read_tree_twoway $treeH $treeM; then false; else :; fi'
236 test_expect_success \
237 '14 - unchanged in two heads.' \
239 git-read-tree $treeH &&
240 git-checkout-index -u -f -q -a &&
241 echo nitfol nitfol >nitfol &&
242 git-update-index --add nitfol &&
243 read_tree_twoway $treeH $treeM &&
244 git-ls-files --stage >14.out || return 1
245 diff -u M.out 14.out >14diff.out
246 compare_change 14diff.out expected &&
247 check_cache_at nitfol clean'
249 test_expect_success \
250 '15 - unchanged in two heads.' \
252 git-read-tree $treeH &&
253 git-checkout-index -u -f -q -a &&
254 echo nitfol nitfol >nitfol &&
255 git-update-index --add nitfol &&
256 echo nitfol nitfol nitfol >nitfol &&
257 read_tree_twoway $treeH $treeM &&
258 git-ls-files --stage >15.out || return 1
259 diff -u M.out 15.out >15diff.out
260 compare_change 15diff.out expected &&
261 check_cache_at nitfol dirty'
263 # This is different from straight 2-way merge in that it leaves
264 # three stages of bozbar in the index file without failing, so
265 # the user can run git-diff-stages to examine the situation.
266 # With #2ALT, frotz is resolved internally.
267 test_expect_success \
268 '16 - conflicting local change.' \
270 git-read-tree $treeH &&
271 git-checkout-index -u -f -q -a &&
272 echo bozbar bozbar >bozbar &&
273 git-update-index --add bozbar &&
274 git-read-tree --emu23 $treeH $treeM &&
285 test_expect_success \
286 '17 - conflicting local change.' \
288 git-read-tree $treeH &&
289 git-checkout-index -u -f -q -a &&
290 echo bozbar bozbar >bozbar &&
291 git-update-index --add bozbar &&
292 echo bozbar bozbar bozbar >bozbar &&
293 if read_tree_twoway $treeH $treeM; then false; else :; fi'
295 test_expect_success \
296 '18 - local change already having a good result.' \
298 git-read-tree $treeH &&
299 git-checkout-index -u -f -q -a &&
300 cat bozbar-new >bozbar &&
301 git-update-index --add bozbar &&
302 read_tree_twoway $treeH $treeM &&
303 git-ls-files --stage >18.out &&
304 diff -u M.out 18.out &&
305 check_cache_at bozbar clean'
307 test_expect_success \
308 '19 - local change already having a good result, further modified.' \
310 git-read-tree $treeH &&
311 git-checkout-index -u -f -q -a &&
312 cat bozbar-new >bozbar &&
313 git-update-index --add bozbar &&
314 echo gnusto gnusto >bozbar &&
315 read_tree_twoway $treeH $treeM &&
316 git-ls-files --stage >19.out &&
317 diff -u M.out 19.out &&
318 check_cache_at bozbar dirty'
320 test_expect_success \
321 '20 - no local change, use new tree.' \
323 git-read-tree $treeH &&
324 git-checkout-index -u -f -q -a &&
325 cat bozbar-old >bozbar &&
326 git-update-index --add bozbar &&
327 read_tree_twoway $treeH $treeM &&
328 git-ls-files --stage >20.out &&
329 diff -u M.out 20.out &&
330 check_cache_at bozbar dirty'
332 test_expect_success \
333 '21 - no local change, dirty cache.' \
335 git-read-tree $treeH &&
336 git-checkout-index -u -f -q -a &&
337 cat bozbar-old >bozbar &&
338 git-update-index --add bozbar &&
339 echo gnusto gnusto >bozbar &&
340 if read_tree_twoway $treeH $treeM; then false; else :; fi'
342 echo '-100644 X 0 bozbar
343 +100644 X 0 bozbar' >expected
345 # This fails with straight two-way fast forward, but emu23
347 test_expect_success \
348 '22 - local change cache updated.' \
350 git-read-tree $treeH &&
351 git-checkout-index -u -f -q -a &&
352 sed -e "s/such as/SUCH AS/" bozbar-old >bozbar &&
353 git-update-index --add bozbar &&
354 read_tree_twoway $treeH $treeM &&
355 git-ls-files --stage >22.out || return 1
356 diff -u M.out 22.out >22diff.out
357 compare_change 22diff.out &&
358 check_cache_at bozbar clean'
360 # Also make sure we did not break DF vs DF/DF case.
361 test_expect_success \
362 'DF vs DF/DF case setup.' \
365 git-update-index --add DF &&
366 treeDF=`git-write-tree` &&
367 echo treeDF $treeDF &&
368 git-ls-tree $treeDF &&
369 git-ls-files --stage >DF.out
374 git-update-index --add --remove DF DF/DF &&
375 treeDFDF=`git-write-tree` &&
376 echo treeDFDF $treeDFDF &&
377 git-ls-tree $treeDFDF &&
378 git-ls-files --stage >DFDF.out'
380 test_expect_success \
381 'DF vs DF/DF case test (#1)' \
385 git-update-index --add DF &&
386 read_tree_twoway $treeDF $treeDFDF &&
387 git-ls-files --stage >DFDFcheck.out &&
388 diff -u DFDF.out DFDFcheck.out &&
389 check_cache_at DF/DF clean && # different from pure 2-way
392 # The other way around
393 test_expect_success \
394 'DF vs DF/DF case test (#2)' \
399 git-update-index --add DF/DF &&
400 read_tree_twoway $treeDFDF $treeDF &&
401 git-ls-files --stage >DFDFcheck.out &&
402 diff -u DF.out DFDFcheck.out &&
403 check_cache_at DF clean && # different from pure 2-way
406 # Emu23 can grok I having more than H. Make sure we did not
407 # botch the conflict tests (fixed).
408 test_expect_success \
409 'DF vs DF/DF case test (#3).' \
414 git-update-index --add DF/DF &&
415 # This should fail because I and H have a conflict
417 if git-read-tree --emu23 $treeDF $treeDFDF