Merge branch 'jc/doc-diff-blobs'
[git] / t / t3507-cherry-pick-conflict.sh
1 #!/bin/sh
2
3 test_description='test cherry-pick and revert with conflicts
4
5   -
6   + picked: rewrites foo to c
7   + base: rewrites foo to b
8   + initial: writes foo as a, unrelated as unrelated
9
10 '
11
12 . ./test-lib.sh
13
14 test_cmp_rev () {
15         git rev-parse --verify "$1" >expect.rev &&
16         git rev-parse --verify "$2" >actual.rev &&
17         test_cmp expect.rev actual.rev
18 }
19
20 pristine_detach () {
21         git checkout -f "$1^0" &&
22         git read-tree -u --reset HEAD &&
23         git clean -d -f -f -q -x
24 }
25
26 test_expect_success setup '
27
28         echo unrelated >unrelated &&
29         git add unrelated &&
30         test_commit initial foo a &&
31         test_commit base foo b &&
32         test_commit picked foo c &&
33         test_commit --signoff picked-signed foo d &&
34         git config advice.detachedhead false
35
36 '
37
38 test_expect_success 'failed cherry-pick does not advance HEAD' '
39         pristine_detach initial &&
40
41         head=$(git rev-parse HEAD) &&
42         test_must_fail git cherry-pick picked &&
43         newhead=$(git rev-parse HEAD) &&
44
45         test "$head" = "$newhead"
46 '
47
48 test_expect_success 'advice from failed cherry-pick' "
49         pristine_detach initial &&
50
51         picked=\$(git rev-parse --short picked) &&
52         cat <<-EOF >expected &&
53         error: could not apply \$picked... picked
54         hint: after resolving the conflicts, mark the corrected paths
55         hint: with 'git add <paths>' or 'git rm <paths>'
56         hint: and commit the result with 'git commit'
57         EOF
58         test_must_fail git cherry-pick picked 2>actual &&
59
60         test_i18ncmp expected actual
61 "
62
63 test_expect_success 'advice from failed cherry-pick --no-commit' "
64         pristine_detach initial &&
65
66         picked=\$(git rev-parse --short picked) &&
67         cat <<-EOF >expected &&
68         error: could not apply \$picked... picked
69         hint: after resolving the conflicts, mark the corrected paths
70         hint: with 'git add <paths>' or 'git rm <paths>'
71         EOF
72         test_must_fail git cherry-pick --no-commit picked 2>actual &&
73
74         test_i18ncmp expected actual
75 "
76
77 test_expect_success 'failed cherry-pick sets CHERRY_PICK_HEAD' '
78         pristine_detach initial &&
79         test_must_fail git cherry-pick picked &&
80         test_cmp_rev picked CHERRY_PICK_HEAD
81 '
82
83 test_expect_success 'successful cherry-pick does not set CHERRY_PICK_HEAD' '
84         pristine_detach initial &&
85         git cherry-pick base &&
86         test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
87 '
88
89 test_expect_success 'cherry-pick --no-commit does not set CHERRY_PICK_HEAD' '
90         pristine_detach initial &&
91         git cherry-pick --no-commit base &&
92         test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
93 '
94
95 test_expect_success 'cherry-pick w/dirty tree does not set CHERRY_PICK_HEAD' '
96         pristine_detach initial &&
97         echo foo > foo &&
98         test_must_fail git cherry-pick base &&
99         test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
100 '
101
102 test_expect_success \
103         'cherry-pick --strategy=resolve w/dirty tree does not set CHERRY_PICK_HEAD' '
104         pristine_detach initial &&
105         echo foo > foo &&
106         test_must_fail git cherry-pick --strategy=resolve base &&
107         test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
108 '
109
110 test_expect_success 'GIT_CHERRY_PICK_HELP suppresses CHERRY_PICK_HEAD' '
111         pristine_detach initial &&
112         (
113                 GIT_CHERRY_PICK_HELP="and then do something else" &&
114                 export GIT_CHERRY_PICK_HELP &&
115                 test_must_fail git cherry-pick picked
116         ) &&
117         test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
118 '
119
120 test_expect_success 'git reset clears CHERRY_PICK_HEAD' '
121         pristine_detach initial &&
122
123         test_must_fail git cherry-pick picked &&
124         git reset &&
125
126         test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
127 '
128
129 test_expect_success 'failed commit does not clear CHERRY_PICK_HEAD' '
130         pristine_detach initial &&
131
132         test_must_fail git cherry-pick picked &&
133         test_must_fail git commit &&
134
135         test_cmp_rev picked CHERRY_PICK_HEAD
136 '
137
138 test_expect_success 'cancelled commit does not clear CHERRY_PICK_HEAD' '
139         pristine_detach initial &&
140
141         test_must_fail git cherry-pick picked &&
142         echo resolved >foo &&
143         git add foo &&
144         git update-index --refresh -q &&
145         test_must_fail git diff-index --exit-code HEAD &&
146         (
147                 GIT_EDITOR=false &&
148                 export GIT_EDITOR &&
149                 test_must_fail git commit
150         ) &&
151
152         test_cmp_rev picked CHERRY_PICK_HEAD
153 '
154
155 test_expect_success 'successful commit clears CHERRY_PICK_HEAD' '
156         pristine_detach initial &&
157
158         test_must_fail git cherry-pick picked &&
159         echo resolved >foo &&
160         git add foo &&
161         git commit &&
162
163         test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
164 '
165
166 test_expect_success 'failed cherry-pick produces dirty index' '
167         pristine_detach initial &&
168
169         test_must_fail git cherry-pick picked &&
170
171         test_must_fail git update-index --refresh -q &&
172         test_must_fail git diff-index --exit-code HEAD
173 '
174
175 test_expect_success 'failed cherry-pick registers participants in index' '
176         pristine_detach initial &&
177         {
178                 git checkout base -- foo &&
179                 git ls-files --stage foo &&
180                 git checkout initial -- foo &&
181                 git ls-files --stage foo &&
182                 git checkout picked -- foo &&
183                 git ls-files --stage foo
184         } > stages &&
185         sed "
186                 1 s/ 0  / 1     /
187                 2 s/ 0  / 2     /
188                 3 s/ 0  / 3     /
189         " < stages > expected &&
190         git read-tree -u --reset HEAD &&
191
192         test_must_fail git cherry-pick picked &&
193         git ls-files --stage --unmerged > actual &&
194
195         test_cmp expected actual
196 '
197
198 test_expect_success 'failed cherry-pick describes conflict in work tree' '
199         pristine_detach initial &&
200         cat <<-EOF > expected &&
201         <<<<<<< HEAD
202         a
203         =======
204         c
205         >>>>>>> objid picked
206         EOF
207
208         test_must_fail git cherry-pick picked &&
209
210         sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
211         test_cmp expected actual
212 '
213
214 test_expect_success 'diff3 -m style' '
215         pristine_detach initial &&
216         git config merge.conflictstyle diff3 &&
217         cat <<-EOF > expected &&
218         <<<<<<< HEAD
219         a
220         ||||||| parent of objid picked
221         b
222         =======
223         c
224         >>>>>>> objid picked
225         EOF
226
227         test_must_fail git cherry-pick picked &&
228
229         sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
230         test_cmp expected actual
231 '
232
233 test_expect_success 'revert also handles conflicts sanely' '
234         git config --unset merge.conflictstyle &&
235         pristine_detach initial &&
236         cat <<-EOF > expected &&
237         <<<<<<< HEAD
238         a
239         =======
240         b
241         >>>>>>> parent of objid picked
242         EOF
243         {
244                 git checkout picked -- foo &&
245                 git ls-files --stage foo &&
246                 git checkout initial -- foo &&
247                 git ls-files --stage foo &&
248                 git checkout base -- foo &&
249                 git ls-files --stage foo
250         } > stages &&
251         sed "
252                 1 s/ 0  / 1     /
253                 2 s/ 0  / 2     /
254                 3 s/ 0  / 3     /
255         " < stages > expected-stages &&
256         git read-tree -u --reset HEAD &&
257
258         head=$(git rev-parse HEAD) &&
259         test_must_fail git revert picked &&
260         newhead=$(git rev-parse HEAD) &&
261         git ls-files --stage --unmerged > actual-stages &&
262
263         test "$head" = "$newhead" &&
264         test_must_fail git update-index --refresh -q &&
265         test_must_fail git diff-index --exit-code HEAD &&
266         test_cmp expected-stages actual-stages &&
267         sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
268         test_cmp expected actual
269 '
270
271 test_expect_success 'failed revert sets REVERT_HEAD' '
272         pristine_detach initial &&
273         test_must_fail git revert picked &&
274         test_cmp_rev picked REVERT_HEAD
275 '
276
277 test_expect_success 'successful revert does not set REVERT_HEAD' '
278         pristine_detach base &&
279         git revert base &&
280         test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
281         test_must_fail git rev-parse --verify REVERT_HEAD
282 '
283
284 test_expect_success 'revert --no-commit sets REVERT_HEAD' '
285         pristine_detach base &&
286         git revert --no-commit base &&
287         test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
288         test_cmp_rev base REVERT_HEAD
289 '
290
291 test_expect_success 'revert w/dirty tree does not set REVERT_HEAD' '
292         pristine_detach base &&
293         echo foo > foo &&
294         test_must_fail git revert base &&
295         test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
296         test_must_fail git rev-parse --verify REVERT_HEAD
297 '
298
299 test_expect_success 'GIT_CHERRY_PICK_HELP does not suppress REVERT_HEAD' '
300         pristine_detach initial &&
301         (
302                 GIT_CHERRY_PICK_HELP="and then do something else" &&
303                 GIT_REVERT_HELP="and then do something else, again" &&
304                 export GIT_CHERRY_PICK_HELP GIT_REVERT_HELP &&
305                 test_must_fail git revert picked
306         ) &&
307         test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
308         test_cmp_rev picked REVERT_HEAD
309 '
310
311 test_expect_success 'git reset clears REVERT_HEAD' '
312         pristine_detach initial &&
313         test_must_fail git revert picked &&
314         git reset &&
315         test_must_fail git rev-parse --verify REVERT_HEAD
316 '
317
318 test_expect_success 'failed commit does not clear REVERT_HEAD' '
319         pristine_detach initial &&
320         test_must_fail git revert picked &&
321         test_must_fail git commit &&
322         test_cmp_rev picked REVERT_HEAD
323 '
324
325 test_expect_success 'revert conflict, diff3 -m style' '
326         pristine_detach initial &&
327         git config merge.conflictstyle diff3 &&
328         cat <<-EOF > expected &&
329         <<<<<<< HEAD
330         a
331         ||||||| objid picked
332         c
333         =======
334         b
335         >>>>>>> parent of objid picked
336         EOF
337
338         test_must_fail git revert picked &&
339
340         sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
341         test_cmp expected actual
342 '
343
344 test_expect_success 'failed cherry-pick does not forget -s' '
345         pristine_detach initial &&
346         test_must_fail git cherry-pick -s picked &&
347         test_i18ngrep -e "Signed-off-by" .git/MERGE_MSG
348 '
349
350 test_expect_success 'commit after failed cherry-pick does not add duplicated -s' '
351         pristine_detach initial &&
352         test_must_fail git cherry-pick -s picked-signed &&
353         git commit -a -s &&
354         test $(git show -s |grep -c "Signed-off-by") = 1
355 '
356
357 test_expect_success 'commit after failed cherry-pick adds -s at the right place' '
358         pristine_detach initial &&
359         test_must_fail git cherry-pick picked &&
360         git commit -a -s &&
361         pwd &&
362         cat <<EOF > expected &&
363 picked
364
365 Signed-off-by: C O Mitter <committer@example.com>
366
367 Conflicts:
368         foo
369 EOF
370
371         git show -s --pretty=format:%B > actual &&
372         test_cmp expected actual
373 '
374
375 test_done