1#!/bin/sh
2
3test_description='git merge
4
5Testing pull.* configuration parsing and other things.'
6
7. ./test-lib.sh
8
9test_expect_success 'setup' '
10	echo c0 >c0.c &&
11	git add c0.c &&
12	git commit -m c0 &&
13	git tag c0 &&
14	echo c1 >c1.c &&
15	git add c1.c &&
16	git commit -m c1 &&
17	git tag c1 &&
18	git reset --hard c0 &&
19	echo c2 >c2.c &&
20	git add c2.c &&
21	git commit -m c2 &&
22	git tag c2 &&
23	git reset --hard c0 &&
24	echo c3 >c3.c &&
25	git add c3.c &&
26	git commit -m c3 &&
27	git tag c3
28'
29
30test_expect_success 'pull.rebase not set, ff possible' '
31	git reset --hard c0 &&
32	git pull . c1 2>err &&
33	test_i18ngrep ! "You have divergent branches" err
34'
35
36test_expect_success 'pull.rebase not set and pull.ff=true' '
37	git reset --hard c0 &&
38	test_config pull.ff true &&
39	git pull . c1 2>err &&
40	test_i18ngrep ! "You have divergent branches" err
41'
42
43test_expect_success 'pull.rebase not set and pull.ff=false' '
44	git reset --hard c0 &&
45	test_config pull.ff false &&
46	git pull . c1 2>err &&
47	test_i18ngrep ! "You have divergent branches" err
48'
49
50test_expect_success 'pull.rebase not set and pull.ff=only' '
51	git reset --hard c0 &&
52	test_config pull.ff only &&
53	git pull . c1 2>err &&
54	test_i18ngrep ! "You have divergent branches" err
55'
56
57test_expect_success 'pull.rebase not set and --rebase given' '
58	git reset --hard c0 &&
59	git pull --rebase . c1 2>err &&
60	test_i18ngrep ! "You have divergent branches" err
61'
62
63test_expect_success 'pull.rebase not set and --no-rebase given' '
64	git reset --hard c0 &&
65	git pull --no-rebase . c1 2>err &&
66	test_i18ngrep ! "You have divergent branches" err
67'
68
69test_expect_success 'pull.rebase not set and --ff given' '
70	git reset --hard c0 &&
71	git pull --ff . c1 2>err &&
72	test_i18ngrep ! "You have divergent branches" err
73'
74
75test_expect_success 'pull.rebase not set and --no-ff given' '
76	git reset --hard c0 &&
77	git pull --no-ff . c1 2>err &&
78	test_i18ngrep ! "You have divergent branches" err
79'
80
81test_expect_success 'pull.rebase not set and --ff-only given' '
82	git reset --hard c0 &&
83	git pull --ff-only . c1 2>err &&
84	test_i18ngrep ! "You have divergent branches" err
85'
86
87test_expect_success 'pull.rebase not set (not-fast-forward)' '
88	git reset --hard c2 &&
89	test_must_fail git -c color.advice=always pull . c1 2>err &&
90	test_decode_color <err >decoded &&
91	test_i18ngrep "<YELLOW>hint: " decoded &&
92	test_i18ngrep "You have divergent branches" decoded
93'
94
95test_expect_success 'pull.rebase not set and pull.ff=true (not-fast-forward)' '
96	git reset --hard c2 &&
97	test_config pull.ff true &&
98	git pull . c1 2>err &&
99	test_i18ngrep ! "You have divergent branches" err
100'
101
102test_expect_success 'pull.rebase not set and pull.ff=false (not-fast-forward)' '
103	git reset --hard c2 &&
104	test_config pull.ff false &&
105	git pull . c1 2>err &&
106	test_i18ngrep ! "You have divergent branches" err
107'
108
109test_expect_success 'pull.rebase not set and pull.ff=only (not-fast-forward)' '
110	git reset --hard c2 &&
111	test_config pull.ff only &&
112	test_must_fail git pull . c1 2>err &&
113	test_i18ngrep ! "You have divergent branches" err
114'
115
116test_expect_success 'pull.rebase not set and --rebase given (not-fast-forward)' '
117	git reset --hard c2 &&
118	git pull --rebase . c1 2>err &&
119	test_i18ngrep ! "You have divergent branches" err
120'
121
122test_expect_success 'pull.rebase not set and --no-rebase given (not-fast-forward)' '
123	git reset --hard c2 &&
124	git pull --no-rebase . c1 2>err &&
125	test_i18ngrep ! "You have divergent branches" err
126'
127
128test_expect_success 'pull.rebase not set and --ff given (not-fast-forward)' '
129	git reset --hard c2 &&
130	git pull --ff . c1 2>err &&
131	test_i18ngrep ! "You have divergent branches" err
132'
133
134test_expect_success 'pull.rebase not set and --no-ff given (not-fast-forward)' '
135	git reset --hard c2 &&
136	git pull --no-ff . c1 2>err &&
137	test_i18ngrep ! "You have divergent branches" err
138'
139
140test_expect_success 'pull.rebase not set and --ff-only given (not-fast-forward)' '
141	git reset --hard c2 &&
142	test_must_fail git pull --ff-only . c1 2>err &&
143	test_i18ngrep ! "You have divergent branches" err
144'
145
146test_does_rebase () {
147	git reset --hard c2 &&
148	git "$@" . c1 &&
149	# Check that we actually did a rebase
150	git rev-list --count HEAD >actual &&
151	git rev-list --merges --count HEAD >>actual &&
152	test_write_lines 3 0 >expect &&
153	test_cmp expect actual &&
154	rm actual expect
155}
156
157# Prefers merge over fast-forward
158test_does_merge_when_ff_possible () {
159	git reset --hard c0 &&
160	git "$@" . c1 &&
161	# Check that we actually did a merge
162	git rev-list --count HEAD >actual &&
163	git rev-list --merges --count HEAD >>actual &&
164	test_write_lines 3 1 >expect &&
165	test_cmp expect actual &&
166	rm actual expect
167}
168
169# Prefers fast-forward over merge or rebase
170test_does_fast_forward () {
171	git reset --hard c0 &&
172	git "$@" . c1 &&
173
174	# Check that we did not get any merges
175	git rev-list --count HEAD >actual &&
176	git rev-list --merges --count HEAD >>actual &&
177	test_write_lines 2 0 >expect &&
178	test_cmp expect actual &&
179
180	# Check that we ended up at c1
181	git rev-parse HEAD >actual &&
182	git rev-parse c1^{commit} >expect &&
183	test_cmp actual expect &&
184
185	# Remove temporary files
186	rm actual expect
187}
188
189# Doesn't fail when fast-forward not possible; does a merge
190test_falls_back_to_full_merge () {
191	git reset --hard c2 &&
192	git "$@" . c1 &&
193	# Check that we actually did a merge
194	git rev-list --count HEAD >actual &&
195	git rev-list --merges --count HEAD >>actual &&
196	test_write_lines 4 1 >expect &&
197	test_cmp expect actual &&
198	rm actual expect
199}
200
201# Attempts fast forward, which is impossible, and bails
202test_attempts_fast_forward () {
203	git reset --hard c2 &&
204	test_must_fail git "$@" . c1 2>err &&
205	test_i18ngrep "Not possible to fast-forward, aborting" err
206}
207
208#
209# Group 1: Interaction of --ff-only with --[no-]rebase
210# (And related interaction of pull.ff=only with pull.rebase)
211#
212test_expect_success '--ff-only overrides --rebase' '
213	test_attempts_fast_forward pull --rebase --ff-only
214'
215
216test_expect_success '--ff-only overrides --rebase even if first' '
217	test_attempts_fast_forward pull --ff-only --rebase
218'
219
220test_expect_success '--ff-only overrides --no-rebase' '
221	test_attempts_fast_forward pull --ff-only --no-rebase
222'
223
224test_expect_success 'pull.ff=only overrides pull.rebase=true' '
225	test_attempts_fast_forward -c pull.ff=only -c pull.rebase=true pull
226'
227
228test_expect_success 'pull.ff=only overrides pull.rebase=false' '
229	test_attempts_fast_forward -c pull.ff=only -c pull.rebase=false pull
230'
231
232# Group 2: --rebase=[!false] overrides --no-ff and --ff
233# (And related interaction of pull.rebase=!false and pull.ff=!only)
234test_expect_success '--rebase overrides --no-ff' '
235	test_does_rebase pull --rebase --no-ff
236'
237
238test_expect_success '--rebase overrides --ff' '
239	test_does_rebase pull --rebase --ff
240'
241
242test_expect_success '--rebase fast-forwards when possible' '
243	test_does_fast_forward pull --rebase --ff
244'
245
246test_expect_success 'pull.rebase=true overrides pull.ff=false' '
247	test_does_rebase -c pull.rebase=true -c pull.ff=false pull
248'
249
250test_expect_success 'pull.rebase=true overrides pull.ff=true' '
251	test_does_rebase -c pull.rebase=true -c pull.ff=true pull
252'
253
254# Group 3: command line flags take precedence over config
255test_expect_success '--ff-only takes precedence over pull.rebase=true' '
256	test_attempts_fast_forward -c pull.rebase=true pull --ff-only
257'
258
259test_expect_success '--ff-only takes precedence over pull.rebase=false' '
260	test_attempts_fast_forward -c pull.rebase=false pull --ff-only
261'
262
263test_expect_success '--no-rebase takes precedence over pull.ff=only' '
264	test_falls_back_to_full_merge -c pull.ff=only pull --no-rebase
265'
266
267test_expect_success '--rebase takes precedence over pull.ff=only' '
268	test_does_rebase -c pull.ff=only pull --rebase
269'
270
271test_expect_success '--rebase overrides pull.ff=true' '
272	test_does_rebase -c pull.ff=true pull --rebase
273'
274
275test_expect_success '--rebase overrides pull.ff=false' '
276	test_does_rebase -c pull.ff=false pull --rebase
277'
278
279test_expect_success '--rebase overrides pull.ff unset' '
280	test_does_rebase pull --rebase
281'
282
283# Group 4: --no-rebase heeds pull.ff=!only or explict --ff or --no-ff
284
285test_expect_success '--no-rebase works with --no-ff' '
286	test_does_merge_when_ff_possible pull --no-rebase --no-ff
287'
288
289test_expect_success '--no-rebase works with --ff' '
290	test_does_fast_forward pull --no-rebase --ff
291'
292
293test_expect_success '--no-rebase does ff if pull.ff unset' '
294	test_does_fast_forward pull --no-rebase
295'
296
297test_expect_success '--no-rebase heeds pull.ff=true' '
298	test_does_fast_forward -c pull.ff=true pull --no-rebase
299'
300
301test_expect_success '--no-rebase heeds pull.ff=false' '
302	test_does_merge_when_ff_possible -c pull.ff=false pull --no-rebase
303'
304
305# Group 5: pull.rebase=!false in combination with --no-ff or --ff
306test_expect_success 'pull.rebase=true and --no-ff' '
307	test_does_rebase -c pull.rebase=true pull --no-ff
308'
309
310test_expect_success 'pull.rebase=true and --ff' '
311	test_does_rebase -c pull.rebase=true pull --ff
312'
313
314test_expect_success 'pull.rebase=false and --no-ff' '
315	test_does_merge_when_ff_possible -c pull.rebase=false pull --no-ff
316'
317
318test_expect_success 'pull.rebase=false and --ff, ff possible' '
319	test_does_fast_forward -c pull.rebase=false pull --ff
320'
321
322test_expect_success 'pull.rebase=false and --ff, ff not possible' '
323	test_falls_back_to_full_merge -c pull.rebase=false pull --ff
324'
325
326# End of groupings for conflicting merge vs. rebase flags/options
327
328test_expect_success 'Multiple heads warns about inability to fast forward' '
329	git reset --hard c1 &&
330	test_must_fail git pull . c2 c3 2>err &&
331	test_i18ngrep "You have divergent branches" err
332'
333
334test_expect_success 'Multiple can never be fast forwarded' '
335	git reset --hard c0 &&
336	test_must_fail git -c pull.ff=only pull . c1 c2 c3 2>err &&
337	test_i18ngrep ! "You have divergent branches" err &&
338	# In addition to calling out "cannot fast-forward", we very much
339	# want the "multiple branches" piece to be called out to users.
340	test_i18ngrep "Cannot fast-forward to multiple branches" err
341'
342
343test_expect_success 'Cannot rebase with multiple heads' '
344	git reset --hard c0 &&
345	test_must_fail git -c pull.rebase=true pull . c1 c2 c3 2>err &&
346	test_i18ngrep ! "You have divergent branches" err &&
347	test_i18ngrep "Cannot rebase onto multiple branches." err
348'
349
350test_expect_success 'merge c1 with c2' '
351	git reset --hard c1 &&
352	test -f c0.c &&
353	test -f c1.c &&
354	test ! -f c2.c &&
355	test ! -f c3.c &&
356	git merge c2 &&
357	test -f c1.c &&
358	test -f c2.c
359'
360
361test_expect_success 'fast-forward pull succeeds with "true" in pull.ff' '
362	git reset --hard c0 &&
363	test_config pull.ff true &&
364	git pull . c1 &&
365	test "$(git rev-parse HEAD)" = "$(git rev-parse c1)"
366'
367
368test_expect_success 'pull.ff=true overrides merge.ff=false' '
369	git reset --hard c0 &&
370	test_config merge.ff false &&
371	test_config pull.ff true &&
372	git pull . c1 &&
373	test "$(git rev-parse HEAD)" = "$(git rev-parse c1)"
374'
375
376test_expect_success 'fast-forward pull creates merge with "false" in pull.ff' '
377	git reset --hard c0 &&
378	test_config pull.ff false &&
379	git pull . c1 &&
380	test "$(git rev-parse HEAD^1)" = "$(git rev-parse c0)" &&
381	test "$(git rev-parse HEAD^2)" = "$(git rev-parse c1)"
382'
383
384test_expect_success 'pull prevents non-fast-forward with "only" in pull.ff' '
385	git reset --hard c1 &&
386	test_config pull.ff only &&
387	test_must_fail git pull . c3
388'
389
390test_expect_success 'already-up-to-date pull succeeds with unspecified pull.ff' '
391	git reset --hard c1 &&
392	git pull . c0 &&
393	test "$(git rev-parse HEAD)" = "$(git rev-parse c1)"
394'
395
396test_expect_success 'already-up-to-date pull succeeds with "only" in pull.ff' '
397	git reset --hard c1 &&
398	test_config pull.ff only &&
399	git pull . c0 &&
400	test "$(git rev-parse HEAD)" = "$(git rev-parse c1)"
401'
402
403test_expect_success 'already-up-to-date pull/rebase succeeds with "only" in pull.ff' '
404	git reset --hard c1 &&
405	test_config pull.ff only &&
406	git -c pull.rebase=true pull . c0 &&
407	test "$(git rev-parse HEAD)" = "$(git rev-parse c1)"
408'
409
410test_expect_success 'merge c1 with c2 (ours in pull.twohead)' '
411	git reset --hard c1 &&
412	git config pull.twohead ours &&
413	git merge c2 &&
414	test -f c1.c &&
415	! test -f c2.c
416'
417
418test_expect_success 'merge c1 with c2 and c3 (recursive in pull.octopus)' '
419	git reset --hard c1 &&
420	git config pull.octopus "recursive" &&
421	test_must_fail git merge c2 c3 &&
422	test "$(git rev-parse c1)" = "$(git rev-parse HEAD)"
423'
424
425test_expect_success 'merge c1 with c2 and c3 (recursive and octopus in pull.octopus)' '
426	git reset --hard c1 &&
427	git config pull.octopus "recursive octopus" &&
428	git merge c2 c3 &&
429	test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" &&
430	test "$(git rev-parse c1)" = "$(git rev-parse HEAD^1)" &&
431	test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" &&
432	test "$(git rev-parse c3)" = "$(git rev-parse HEAD^3)" &&
433	git diff --exit-code &&
434	test -f c0.c &&
435	test -f c1.c &&
436	test -f c2.c &&
437	test -f c3.c
438'
439
440conflict_count()
441{
442	{
443		git diff-files --name-only
444		git ls-files --unmerged
445	} | wc -l
446}
447
448# c4 - c5
449#    \ c6
450#
451# There are two conflicts here:
452#
453# 1) Because foo.c is renamed to bar.c, recursive will handle this,
454# resolve won't.
455#
456# 2) One in conflict.c and that will always fail.
457
458test_expect_success 'setup conflicted merge' '
459	git reset --hard c0 &&
460	echo A >conflict.c &&
461	git add conflict.c &&
462	echo contents >foo.c &&
463	git add foo.c &&
464	git commit -m c4 &&
465	git tag c4 &&
466	echo B >conflict.c &&
467	git add conflict.c &&
468	git mv foo.c bar.c &&
469	git commit -m c5 &&
470	git tag c5 &&
471	git reset --hard c4 &&
472	echo C >conflict.c &&
473	git add conflict.c &&
474	echo secondline >> foo.c &&
475	git add foo.c &&
476	git commit -m c6 &&
477	git tag c6
478'
479
480# First do the merge with resolve and recursive then verify that
481# recursive is chosen.
482
483test_expect_success 'merge picks up the best result' '
484	git config --unset-all pull.twohead &&
485	git reset --hard c5 &&
486	test_must_fail git merge -s resolve c6 &&
487	resolve_count=$(conflict_count) &&
488	git reset --hard c5 &&
489	test_must_fail git merge -s recursive c6 &&
490	recursive_count=$(conflict_count) &&
491	git reset --hard c5 &&
492	test_must_fail git merge -s recursive -s resolve c6 &&
493	auto_count=$(conflict_count) &&
494	test $auto_count = $recursive_count &&
495	test $auto_count != $resolve_count
496'
497
498test_expect_success 'merge picks up the best result (from config)' '
499	git config pull.twohead "recursive resolve" &&
500	git reset --hard c5 &&
501	test_must_fail git merge -s resolve c6 &&
502	resolve_count=$(conflict_count) &&
503	git reset --hard c5 &&
504	test_must_fail git merge -s recursive c6 &&
505	recursive_count=$(conflict_count) &&
506	git reset --hard c5 &&
507	test_must_fail git merge c6 &&
508	auto_count=$(conflict_count) &&
509	test $auto_count = $recursive_count &&
510	test $auto_count != $resolve_count
511'
512
513test_expect_success 'merge errors out on invalid strategy' '
514	git config pull.twohead "foobar" &&
515	git reset --hard c5 &&
516	test_must_fail git merge c6
517'
518
519test_expect_success 'merge errors out on invalid strategy' '
520	git config --unset-all pull.twohead &&
521	git reset --hard c5 &&
522	test_must_fail git merge -s "resolve recursive" c6
523'
524
525test_done
526