summaryrefslogtreecommitdiff
path: root/t/t5520-pull.sh
blob: 37535d63a9cc0c8d611747bd3235995d0b98a115 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
#!/bin/sh
 
test_description='pulling into void'
 
. ./test-lib.sh
 
modify () {
	sed -e "$1" "$2" >"$2.x" &&
	mv "$2.x" "$2"
}
 
test_pull_autostash () {
	expect_parent_num="$1" &&
	shift &&
	git reset --hard before-rebase &&
	echo dirty >new_file &&
	git add new_file &&
	git pull "$@" . copy &&
	test_cmp_rev HEAD^"$expect_parent_num" copy &&
	echo dirty >expect &&
	test_cmp expect new_file &&
	echo "modified again" >expect &&
	test_cmp expect file
}
 
test_pull_autostash_fail () {
	git reset --hard before-rebase &&
	echo dirty >new_file &&
	git add new_file &&
	test_must_fail git pull "$@" . copy 2>err &&
	test_i18ngrep "\(uncommitted changes.\)\|\(overwritten by merge:\)" err
}
 
test_expect_success setup '
	echo file >file &&
	git add file &&
	git commit -a -m original
'
 
test_expect_success 'pulling into void' '
	git init cloned &&
	(
		cd cloned &&
		git pull ..
	) &&
	test_path_is_file file &&
	test_path_is_file cloned/file &&
	test_cmp file cloned/file
'
 
test_expect_success 'pulling into void using master:master' '
	git init cloned-uho &&
	(
		cd cloned-uho &&
		git pull .. master:master
	) &&
	test_path_is_file file &&
	test_path_is_file cloned-uho/file &&
	test_cmp file cloned-uho/file
'
 
test_expect_success 'pulling into void does not overwrite untracked files' '
	git init cloned-untracked &&
	(
		cd cloned-untracked &&
		echo untracked >file &&
		test_must_fail git pull .. master &&
		echo untracked >expect &&
		test_cmp expect file
	)
'
 
test_expect_success 'pulling into void does not overwrite staged files' '
	git init cloned-staged-colliding &&
	(
		cd cloned-staged-colliding &&
		echo "alternate content" >file &&
		git add file &&
		test_must_fail git pull .. master &&
		echo "alternate content" >expect &&
		test_cmp expect file &&
		git cat-file blob :file >file.index &&
		test_cmp expect file.index
	)
'
 
test_expect_success 'pulling into void does not remove new staged files' '
	git init cloned-staged-new &&
	(
		cd cloned-staged-new &&
		echo "new tracked file" >newfile &&
		git add newfile &&
		git pull .. master &&
		echo "new tracked file" >expect &&
		test_cmp expect newfile &&
		git cat-file blob :newfile >newfile.index &&
		test_cmp expect newfile.index
	)
'
 
test_expect_success 'pulling into void must not create an octopus' '
	git init cloned-octopus &&
	(
		cd cloned-octopus &&
		test_must_fail git pull .. master master &&
		test_path_is_missing file
	)
'
 
test_expect_success 'test . as a remote' '
	git branch copy master &&
	git config branch.copy.remote . &&
	git config branch.copy.merge refs/heads/master &&
	echo updated >file &&
	git commit -a -m updated &&
	git checkout copy &&
	echo file >expect &&
	test_cmp expect file &&
	git pull &&
	echo updated >expect &&
	test_cmp expect file &&
	git reflog -1 >reflog.actual &&
	sed "s/^[0-9a-f][0-9a-f]*/OBJID/" reflog.actual >reflog.fuzzy &&
	echo "OBJID HEAD@{0}: pull: Fast-forward" >reflog.expected &&
	test_cmp reflog.expected reflog.fuzzy
'
 
test_expect_success 'the default remote . should not break explicit pull' '
	git checkout -b second master^ &&
	echo modified >file &&
	git commit -a -m modified &&
	git checkout copy &&
	git reset --hard HEAD^ &&
	echo file >expect &&
	test_cmp expect file &&
	git pull . second &&
	echo modified >expect &&
	test_cmp expect file &&
	git reflog -1 >reflog.actual &&
	sed "s/^[0-9a-f][0-9a-f]*/OBJID/" reflog.actual >reflog.fuzzy &&
	echo "OBJID HEAD@{0}: pull . second: Fast-forward" >reflog.expected &&
	test_cmp reflog.expected reflog.fuzzy
'
 
test_expect_success 'fail if wildcard spec does not match any refs' '
	git checkout -b test copy^ &&
	test_when_finished "git checkout -f copy && git branch -D test" &&
	echo file >expect &&
	test_cmp expect file &&
	test_must_fail git pull . "refs/nonexisting1/*:refs/nonexisting2/*" 2>err &&
	test_i18ngrep "no candidates for merging" err &&
	test_cmp expect file
'
 
test_expect_success 'fail if no branches specified with non-default remote' '
	git remote add test_remote . &&
	test_when_finished "git remote remove test_remote" &&
	git checkout -b test copy^ &&
	test_when_finished "git checkout -f copy && git branch -D test" &&
	echo file >expect &&
	test_cmp expect file &&
	test_config branch.test.remote origin &&
	test_must_fail git pull test_remote 2>err &&
	test_i18ngrep "specify a branch on the command line" err &&
	test_cmp expect file
'
 
test_expect_success 'fail if not on a branch' '
	git remote add origin . &&
	test_when_finished "git remote remove origin" &&
	git checkout HEAD^ &&
	test_when_finished "git checkout -f copy" &&
	echo file >expect &&
	test_cmp expect file &&
	test_must_fail git pull 2>err &&
	test_i18ngrep "not currently on a branch" err &&
	test_cmp expect file
'
 
test_expect_success 'fail if no configuration for current branch' '
	git remote add test_remote . &&
	test_when_finished "git remote remove test_remote" &&
	git checkout -b test copy^ &&
	test_when_finished "git checkout -f copy && git branch -D test" &&
	test_config branch.test.remote test_remote &&
	echo file >expect &&
	test_cmp expect file &&
	test_must_fail git pull 2>err &&
	test_i18ngrep "no tracking information" err &&
	test_cmp expect file
'
 
test_expect_success 'pull --all: fail if no configuration for current branch' '
	git remote add test_remote . &&
	test_when_finished "git remote remove test_remote" &&
	git checkout -b test copy^ &&
	test_when_finished "git checkout -f copy && git branch -D test" &&
	test_config branch.test.remote test_remote &&
	echo file >expect &&
	test_cmp expect file &&
	test_must_fail git pull --all 2>err &&
	test_i18ngrep "There is no tracking information" err &&
	test_cmp expect file
'
 
test_expect_success 'fail if upstream branch does not exist' '
	git checkout -b test copy^ &&
	test_when_finished "git checkout -f copy && git branch -D test" &&
	test_config branch.test.remote . &&
	test_config branch.test.merge refs/heads/nonexisting &&
	echo file >expect &&
	test_cmp expect file &&
	test_must_fail git pull 2>err &&
	test_i18ngrep "no such ref was fetched" err &&
	test_cmp expect file
'
 
test_expect_success 'fail if the index has unresolved entries' '
	git checkout -b third second^ &&
	test_when_finished "git checkout -f copy && git branch -D third" &&
	echo file >expect &&
	test_cmp expect file &&
	test_commit modified2 file &&
	git ls-files -u >unmerged &&
	test_must_be_empty unmerged &&
	test_must_fail git pull . second &&
	git ls-files -u >unmerged &&
	test_file_not_empty unmerged &&
	cp file expected &&
	test_must_fail git pull . second 2>err &&
	test_i18ngrep "Pulling is not possible because you have unmerged files." err &&
	test_cmp expected file &&
	git add file &&
	git ls-files -u >unmerged &&
	test_must_be_empty unmerged &&
	test_must_fail git pull . second 2>err &&
	test_i18ngrep "You have not concluded your merge" err &&
	test_cmp expected file
'
 
test_expect_success 'fast-forwards working tree if branch head is updated' '
	git checkout -b third second^ &&
	test_when_finished "git checkout -f copy && git branch -D third" &&
	echo file >expect &&
	test_cmp expect file &&
	git pull . second:third 2>err &&
	test_i18ngrep "fetch updated the current branch head" err &&
	echo modified >expect &&
	test_cmp expect file &&
	test_cmp_rev third second
'
 
test_expect_success 'fast-forward fails with conflicting work tree' '
	git checkout -b third second^ &&
	test_when_finished "git checkout -f copy && git branch -D third" &&
	echo file >expect &&
	test_cmp expect file &&
	echo conflict >file &&
	test_must_fail git pull . second:third 2>err &&
	test_i18ngrep "Cannot fast-forward your working tree" err &&
	echo conflict >expect &&
	test_cmp expect file &&
	test_cmp_rev third second
'
 
test_expect_success '--rebase' '
	git branch to-rebase &&
	echo modified again >file &&
	git commit -m file file &&
	git checkout to-rebase &&
	echo new >file2 &&
	git add file2 &&
	git commit -m "new file" &&
	git tag before-rebase &&
	git pull --rebase . copy &&
	test_cmp_rev HEAD^ copy &&
	echo new >expect &&
	git show HEAD:file2 >actual &&
	test_cmp expect actual
'
 
test_expect_success '--rebase (merge) fast forward' '
	git reset --hard before-rebase &&
	git checkout -b ff &&
	echo another modification >file &&
	git commit -m third file &&
 
	git checkout to-rebase &&
	git -c rebase.backend=merge pull --rebase . ff &&
	test_cmp_rev HEAD ff &&
 
	# The above only validates the result.  Did we actually bypass rebase?
	git reflog -1 >reflog.actual &&
	sed "s/^[0-9a-f][0-9a-f]*/OBJID/" reflog.actual >reflog.fuzzy &&
	echo "OBJID HEAD@{0}: pull --rebase . ff: Fast-forward" >reflog.expected &&
	test_cmp reflog.expected reflog.fuzzy
'
 
test_expect_success '--rebase (am) fast forward' '
	git reset --hard before-rebase &&
 
	git -c rebase.backend=apply pull --rebase . ff &&
	test_cmp_rev HEAD ff &&
 
	# The above only validates the result.  Did we actually bypass rebase?
	git reflog -1 >reflog.actual &&
	sed "s/^[0-9a-f][0-9a-f]*/OBJID/" reflog.actual >reflog.fuzzy &&
	echo "OBJID HEAD@{0}: pull --rebase . ff: Fast-forward" >reflog.expected &&
	test_cmp reflog.expected reflog.fuzzy
'
 
test_expect_success '--rebase --autostash fast forward' '
	test_when_finished "
		git reset --hard
		git checkout to-rebase
		git branch -D to-rebase-ff
		git branch -D behind" &&
	git branch behind &&
	git checkout -b to-rebase-ff &&
	echo another modification >>file &&
	git add file &&
	git commit -m mod &&
 
	git checkout behind &&
	echo dirty >file &&
	git pull --rebase --autostash . to-rebase-ff &&
	test_cmp_rev HEAD to-rebase-ff
'
 
test_expect_success '--rebase with conflicts shows advice' '
	test_when_finished "git rebase --abort; git checkout -f to-rebase" &&
	git checkout -b seq &&
	test_seq 5 >seq.txt &&
	git add seq.txt &&
	test_tick &&
	git commit -m "Add seq.txt" &&
	echo 6 >>seq.txt &&
	test_tick &&
	git commit -m "Append to seq.txt" seq.txt &&
	git checkout -b with-conflicts HEAD^ &&
	echo conflicting >>seq.txt &&
	test_tick &&
	git commit -m "Create conflict" seq.txt &&
	test_must_fail git pull --rebase . seq 2>err >out &&
	test_i18ngrep "Resolve all conflicts manually" err
'
 
test_expect_success 'failed --rebase shows advice' '
	test_when_finished "git rebase --abort; git checkout -f to-rebase" &&
	git checkout -b diverging &&
	test_commit attributes .gitattributes "* text=auto" attrs &&
	sha1="$(printf "1\\r\\n" | git hash-object -w --stdin)" &&
	git update-index --cacheinfo 0644 $sha1 file &&
	git commit -m v1-with-cr &&
	# force checkout because `git reset --hard` will not leave clean `file`
	git checkout -f -b fails-to-rebase HEAD^ &&
	test_commit v2-without-cr file "2" file2-lf &&
	test_must_fail git pull --rebase . diverging 2>err >out &&
	test_i18ngrep "Resolve all conflicts manually" err
'
 
test_expect_success '--rebase fails with multiple branches' '
	git reset --hard before-rebase &&
	test_must_fail git pull --rebase . copy master 2>err &&
	test_cmp_rev HEAD before-rebase &&
	test_i18ngrep "Cannot rebase onto multiple branches" err &&
	echo modified >expect &&
	git show HEAD:file >actual &&
	test_cmp expect actual
'
 
test_expect_success 'pull --rebase succeeds with dirty working directory and rebase.autostash set' '
	test_config rebase.autostash true &&
	test_pull_autostash 1 --rebase
'
 
test_expect_success 'pull --rebase --autostash & rebase.autostash=true' '
	test_config rebase.autostash true &&
	test_pull_autostash 1 --rebase --autostash
'
 
test_expect_success 'pull --rebase --autostash & rebase.autostash=false' '
	test_config rebase.autostash false &&
	test_pull_autostash 1 --rebase --autostash
'
 
test_expect_success 'pull --rebase --autostash & rebase.autostash unset' '
	test_unconfig rebase.autostash &&
	test_pull_autostash 1 --rebase --autostash
'
 
test_expect_success 'pull --rebase --no-autostash & rebase.autostash=true' '
	test_config rebase.autostash true &&
	test_pull_autostash_fail --rebase --no-autostash
'
 
test_expect_success 'pull --rebase --no-autostash & rebase.autostash=false' '
	test_config rebase.autostash false &&
	test_pull_autostash_fail --rebase --no-autostash
'
 
test_expect_success 'pull --rebase --no-autostash & rebase.autostash unset' '
	test_unconfig rebase.autostash &&
	test_pull_autostash_fail --rebase --no-autostash
'
 
test_expect_success 'pull succeeds with dirty working directory and merge.autostash set' '
	test_config merge.autostash true &&
	test_pull_autostash 2
'
 
test_expect_success 'pull --autostash & merge.autostash=true' '
	test_config merge.autostash true &&
	test_pull_autostash 2 --autostash
'
 
test_expect_success 'pull --autostash & merge.autostash=false' '
	test_config merge.autostash false &&
	test_pull_autostash 2 --autostash
'
 
test_expect_success 'pull --autostash & merge.autostash unset' '
	test_unconfig merge.autostash &&
	test_pull_autostash 2 --autostash
'
 
test_expect_success 'pull --no-autostash & merge.autostash=true' '
	test_config merge.autostash true &&
	test_pull_autostash_fail --no-autostash
'
 
test_expect_success 'pull --no-autostash & merge.autostash=false' '
	test_config merge.autostash false &&
	test_pull_autostash_fail --no-autostash
'
 
test_expect_success 'pull --no-autostash & merge.autostash unset' '
	test_unconfig merge.autostash &&
	test_pull_autostash_fail --no-autostash
'
 
test_expect_success 'pull.rebase' '
	git reset --hard before-rebase &&
	test_config pull.rebase true &&
	git pull . copy &&
	test_cmp_rev HEAD^ copy &&
	echo new >expect &&
	git show HEAD:file2 >actual &&
	test_cmp expect actual
'
 
test_expect_success 'pull --autostash & pull.rebase=true' '
	test_config pull.rebase true &&
	test_pull_autostash 1 --autostash
'
 
test_expect_success 'pull --no-autostash & pull.rebase=true' '
	test_config pull.rebase true &&
	test_pull_autostash_fail --no-autostash
'
 
test_expect_success 'branch.to-rebase.rebase' '
	git reset --hard before-rebase &&
	test_config branch.to-rebase.rebase true &&
	git pull . copy &&
	test_cmp_rev HEAD^ copy &&
	echo new >expect &&
	git show HEAD:file2 >actual &&
	test_cmp expect actual
'
 
test_expect_success 'branch.to-rebase.rebase should override pull.rebase' '
	git reset --hard before-rebase &&
	test_config pull.rebase true &&
	test_config branch.to-rebase.rebase false &&
	git pull . copy &&
	test_cmp_rev ! HEAD^ copy &&
	echo new >expect &&
	git show HEAD:file2 >actual &&
	test_cmp expect actual
'
 
test_expect_success 'pull --rebase warns on --verify-signatures' '
	git reset --hard before-rebase &&
	git pull --rebase --verify-signatures . copy 2>err &&
	test_cmp_rev HEAD^ copy &&
	echo new >expect &&
	git show HEAD:file2 >actual &&
	test_cmp expect actual &&
	test_i18ngrep "ignoring --verify-signatures for rebase" err
'
 
test_expect_success 'pull --rebase does not warn on --no-verify-signatures' '
	git reset --hard before-rebase &&
	git pull --rebase --no-verify-signatures . copy 2>err &&
	test_cmp_rev HEAD^ copy &&
	echo new >expect &&
	git show HEAD:file2 >actual &&
	test_cmp expect actual &&
	test_i18ngrep ! "verify-signatures" err
'
 
# add a feature branch, keep-merge, that is merged into master, so the
# test can try preserving the merge commit (or not) with various
# --rebase flags/pull.rebase settings.
test_expect_success 'preserve merge setup' '
	git reset --hard before-rebase &&
	git checkout -b keep-merge second^ &&
	test_commit file3 &&
	git checkout to-rebase &&
	git merge keep-merge &&
	git tag before-preserve-rebase
'
 
test_expect_success 'pull.rebase=false create a new merge commit' '
	git reset --hard before-preserve-rebase &&
	test_config pull.rebase false &&
	git pull . copy &&
	test_cmp_rev HEAD^1 before-preserve-rebase &&
	test_cmp_rev HEAD^2 copy &&
	echo file3 >expect &&
	git show HEAD:file3.t >actual &&
	test_cmp expect actual
'
 
test_expect_success 'pull.rebase=true flattens keep-merge' '
	git reset --hard before-preserve-rebase &&
	test_config pull.rebase true &&
	git pull . copy &&
	test_cmp_rev HEAD^^ copy &&
	echo file3 >expect &&
	git show HEAD:file3.t >actual &&
	test_cmp expect actual
'
 
test_expect_success 'pull.rebase=1 is treated as true and flattens keep-merge' '
	git reset --hard before-preserve-rebase &&
	test_config pull.rebase 1 &&
	git pull . copy &&
	test_cmp_rev HEAD^^ copy &&
	echo file3 >expect &&
	git show HEAD:file3.t >actual &&
	test_cmp expect actual
'
 
test_expect_success REBASE_P \
	'pull.rebase=preserve rebases and merges keep-merge' '
	git reset --hard before-preserve-rebase &&
	test_config pull.rebase preserve &&
	git pull . copy &&
	test_cmp_rev HEAD^^ copy &&
	test_cmp_rev HEAD^2 keep-merge
'
 
test_expect_success 'pull.rebase=interactive' '
	write_script "$TRASH_DIRECTORY/fake-editor" <<-\EOF &&
	echo I was here >fake.out &&
	false
	EOF
	test_set_editor "$TRASH_DIRECTORY/fake-editor" &&
	test_when_finished "test_might_fail git rebase --abort" &&
	test_must_fail git pull --rebase=interactive . copy &&
	echo "I was here" >expect &&
	test_cmp expect fake.out
'
 
test_expect_success 'pull --rebase=i' '
	write_script "$TRASH_DIRECTORY/fake-editor" <<-\EOF &&
	echo I was here, too >fake.out &&
	false
	EOF
	test_set_editor "$TRASH_DIRECTORY/fake-editor" &&
	test_when_finished "test_might_fail git rebase --abort" &&
	test_must_fail git pull --rebase=i . copy &&
	echo "I was here, too" >expect &&
	test_cmp expect fake.out
'
 
test_expect_success 'pull.rebase=invalid fails' '
	git reset --hard before-preserve-rebase &&
	test_config pull.rebase invalid &&
	test_must_fail git pull . copy
'
 
test_expect_success '--rebase=false create a new merge commit' '
	git reset --hard before-preserve-rebase &&
	test_config pull.rebase true &&
	git pull --rebase=false . copy &&
	test_cmp_rev HEAD^1 before-preserve-rebase &&
	test_cmp_rev HEAD^2 copy &&
	echo file3 >expect &&
	git show HEAD:file3.t >actual &&
	test_cmp expect actual
'
 
test_expect_success '--rebase=true rebases and flattens keep-merge' '
	git reset --hard before-preserve-rebase &&
	test_config pull.rebase preserve &&
	git pull --rebase=true . copy &&
	test_cmp_rev HEAD^^ copy &&
	echo file3 >expect &&
	git show HEAD:file3.t >actual &&
	test_cmp expect actual
'
 
test_expect_success REBASE_P \
	'--rebase=preserve rebases and merges keep-merge' '
	git reset --hard before-preserve-rebase &&
	test_config pull.rebase true &&
	git pull --rebase=preserve . copy &&
	test_cmp_rev HEAD^^ copy &&
	test_cmp_rev HEAD^2 keep-merge
'
 
test_expect_success '--rebase=invalid fails' '
	git reset --hard before-preserve-rebase &&
	test_must_fail git pull --rebase=invalid . copy
'
 
test_expect_success '--rebase overrides pull.rebase=preserve and flattens keep-merge' '
	git reset --hard before-preserve-rebase &&
	test_config pull.rebase preserve &&
	git pull --rebase . copy &&
	test_cmp_rev HEAD^^ copy &&
	echo file3 >expect &&
	git show HEAD:file3.t >actual &&
	test_cmp expect actual
'
 
test_expect_success '--rebase with rebased upstream' '
	git remote add -f me . &&
	git checkout copy &&
	git tag copy-orig &&
	git reset --hard HEAD^ &&
	echo conflicting modification >file &&
	git commit -m conflict file &&
	git checkout to-rebase &&
	echo file >file2 &&
	git commit -m to-rebase file2 &&
	git tag to-rebase-orig &&
	git pull --rebase me copy &&
	echo "conflicting modification" >expect &&
	test_cmp expect file &&
	echo file >expect &&
	test_cmp expect file2
'
 
test_expect_success '--rebase -f with rebased upstream' '
	test_when_finished "test_might_fail git rebase --abort" &&
	git reset --hard to-rebase-orig &&
	git pull --rebase -f me copy &&
	echo "conflicting modification" >expect &&
	test_cmp expect file &&
	echo file >expect &&
	test_cmp expect file2
'
 
test_expect_success '--rebase with rebased default upstream' '
	git update-ref refs/remotes/me/copy copy-orig &&
	git checkout --track -b to-rebase2 me/copy &&
	git reset --hard to-rebase-orig &&
	git pull --rebase &&
	echo "conflicting modification" >expect &&
	test_cmp expect file &&
	echo file >expect &&
	test_cmp expect file2
'
 
test_expect_success 'rebased upstream + fetch + pull --rebase' '
 
	git update-ref refs/remotes/me/copy copy-orig &&
	git reset --hard to-rebase-orig &&
	git checkout --track -b to-rebase3 me/copy &&
	git reset --hard to-rebase-orig &&
	git fetch &&
	git pull --rebase &&
	echo "conflicting modification" >expect &&
	test_cmp expect file &&
	echo file >expect &&
	test_cmp expect file2
 
'
 
test_expect_success 'pull --rebase dies early with dirty working directory' '
	git checkout to-rebase &&
	git update-ref refs/remotes/me/copy copy^ &&
	COPY="$(git rev-parse --verify me/copy)" &&
	git rebase --onto $COPY copy &&
	test_config branch.to-rebase.remote me &&
	test_config branch.to-rebase.merge refs/heads/copy &&
	test_config branch.to-rebase.rebase true &&
	echo dirty >>file &&
	git add file &&
	test_must_fail git pull &&
	test_cmp_rev "$COPY" me/copy &&
	git checkout HEAD -- file &&
	git pull &&
	test_cmp_rev ! "$COPY" me/copy
'
 
test_expect_success 'pull --rebase works on branch yet to be born' '
	git rev-parse master >expect &&
	mkdir empty_repo &&
	(
		cd empty_repo &&
		git init &&
		git pull --rebase .. master &&
		git rev-parse HEAD >../actual
	) &&
	test_cmp expect actual
'
 
test_expect_success 'pull --rebase fails on unborn branch with staged changes' '
	test_when_finished "rm -rf empty_repo2" &&
	git init empty_repo2 &&
	(
		cd empty_repo2 &&
		echo staged-file >staged-file &&
		git add staged-file &&
		echo staged-file >expect &&
		git ls-files >actual &&
		test_cmp expect actual &&
		test_must_fail git pull --rebase .. master 2>err &&
		git ls-files >actual &&
		test_cmp expect actual &&
		git show :staged-file >actual &&
		test_cmp expect actual &&
		test_i18ngrep "unborn branch with changes added to the index" err
	)
'
 
test_expect_success 'pull --rebase fails on corrupt HEAD' '
	test_when_finished "rm -rf corrupt" &&
	git init corrupt &&
	(
		cd corrupt &&
		test_commit one &&
		git rev-parse --verify HEAD >head &&
		obj=$(sed "s#^..#&/#" head) &&
		rm -f .git/objects/$obj &&
		test_must_fail git pull --rebase
	)
'
 
test_expect_success 'setup for detecting upstreamed changes' '
	mkdir src &&
	(
		cd src &&
		git init &&
		printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" > stuff &&
		git add stuff &&
		git commit -m "Initial revision"
	) &&
	git clone src dst &&
	(
		cd src &&
		modify s/5/43/ stuff &&
		git commit -a -m "5->43" &&
		modify s/6/42/ stuff &&
		git commit -a -m "Make it bigger"
	) &&
	(
		cd dst &&
		modify s/5/43/ stuff &&
		git commit -a -m "Independent discovery of 5->43"
	)
'
 
test_expect_success 'git pull --rebase detects upstreamed changes' '
	(
		cd dst &&
		git pull --rebase &&
		git ls-files -u >untracked &&
		test_must_be_empty untracked
	)
'
 
test_expect_success 'setup for avoiding reapplying old patches' '
	(
		cd dst &&
		test_might_fail git rebase --abort &&
		git reset --hard origin/master
	) &&
	git clone --bare src src-replace.git &&
	rm -rf src &&
	mv src-replace.git src &&
	(
		cd dst &&
		modify s/2/22/ stuff &&
		git commit -a -m "Change 2" &&
		modify s/3/33/ stuff &&
		git commit -a -m "Change 3" &&
		modify s/4/44/ stuff &&
		git commit -a -m "Change 4" &&
		git push &&
 
		modify s/44/55/ stuff &&
		git commit --amend -a -m "Modified Change 4"
	)
'
 
test_expect_success 'git pull --rebase does not reapply old patches' '
	(
		cd dst &&
		test_must_fail git pull --rebase &&
		cat .git/rebase-merge/done .git/rebase-merge/git-rebase-todo >work &&
		grep -v -e \# -e ^$ work >patches &&
		test_line_count = 1 patches &&
		rm -f work
	)
'
 
test_expect_success 'git pull --rebase against local branch' '
	git checkout -b copy2 to-rebase-orig &&
	git pull --rebase . to-rebase &&
	echo "conflicting modification" >expect &&
	test_cmp expect file &&
	echo file >expect &&
	test_cmp expect file2
'
 
test_done