1#!/bin/sh
2
3test_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
14test_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
20pristine_detach () {
21 git checkout -f "$1^0" &&
22 git read-tree -u --reset HEAD &&
23 git clean -d -f -f -q -x
24}
25
26test_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
38test_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
48test_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
63test_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
77test_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
83test_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
89test_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
95test_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
102test_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
110test_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
120test_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
129test_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
138test_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
155test_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
166test_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
175test_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
198test_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
214test_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
233test_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
271test_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
277test_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
284test_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
291test_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
299test_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
311test_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
318test_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
325test_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
344test_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
350test_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
357test_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 &&
363picked
364
365Signed-off-by: C O Mitter <committer@example.com>
366
367Conflicts:
368 foo
369EOF
370
371 git show -s --pretty=format:%B > actual &&
372 test_cmp expected actual
373'
374
375test_done