]>
Commit | Line | Data |
---|---|---|
35d2fffd JH |
1 | #!/bin/sh |
2 | ||
3 | test_description='test aborting in-progress merges | |
4 | ||
5 | Set up repo with conflicting and non-conflicting branches: | |
6 | ||
7 | There are three files foo/bar/baz, and the following graph illustrates the | |
8 | content of these files in each commit: | |
9 | ||
10 | # foo/bar/baz --- foo/bar/bazz <-- master | |
11 | # \ | |
12 | # --- foo/barf/bazf <-- conflict_branch | |
13 | # \ | |
14 | # --- foo/bart/baz <-- clean_branch | |
15 | ||
16 | Next, test git merge --abort with the following variables: | |
17 | - before/after successful merge (should fail when not in merge context) | |
18 | - with/without conflicts | |
19 | - clean/dirty index before merge | |
20 | - clean/dirty worktree before merge | |
21 | - dirty index before merge matches contents on remote branch | |
22 | - changed/unchanged worktree after merge | |
23 | - changed/unchanged index after merge | |
24 | ' | |
25 | . ./test-lib.sh | |
26 | ||
27 | test_expect_success 'setup' ' | |
28 | # Create the above repo | |
29 | echo foo > foo && | |
30 | echo bar > bar && | |
31 | echo baz > baz && | |
32 | git add foo bar baz && | |
33 | git commit -m initial && | |
34 | echo bazz > baz && | |
35 | git commit -a -m "second" && | |
36 | git checkout -b conflict_branch HEAD^ && | |
37 | echo barf > bar && | |
38 | echo bazf > baz && | |
39 | git commit -a -m "conflict" && | |
40 | git checkout -b clean_branch HEAD^ && | |
41 | echo bart > bar && | |
42 | git commit -a -m "clean" && | |
43 | git checkout master | |
44 | ' | |
45 | ||
46 | pre_merge_head="$(git rev-parse HEAD)" | |
47 | ||
48 | test_expect_success 'fails without MERGE_HEAD (unstarted merge)' ' | |
c9ea118e JH |
49 | test_must_fail git merge --abort 2>output && |
50 | test_i18ngrep MERGE_HEAD output | |
bacec478 ÆAB |
51 | ' |
52 | ||
53 | test_expect_success 'fails without MERGE_HEAD (unstarted merge): .git/MERGE_HEAD sanity' ' | |
35d2fffd JH |
54 | test ! -f .git/MERGE_HEAD && |
55 | test "$pre_merge_head" = "$(git rev-parse HEAD)" | |
56 | ' | |
57 | ||
58 | test_expect_success 'fails without MERGE_HEAD (completed merge)' ' | |
59 | git merge clean_branch && | |
60 | test ! -f .git/MERGE_HEAD && | |
61 | # Merge successfully completed | |
62 | post_merge_head="$(git rev-parse HEAD)" && | |
c9ea118e JH |
63 | test_must_fail git merge --abort 2>output && |
64 | test_i18ngrep MERGE_HEAD output | |
bacec478 ÆAB |
65 | ' |
66 | ||
67 | test_expect_success 'fails without MERGE_HEAD (completed merge): .git/MERGE_HEAD sanity' ' | |
35d2fffd JH |
68 | test ! -f .git/MERGE_HEAD && |
69 | test "$post_merge_head" = "$(git rev-parse HEAD)" | |
70 | ' | |
71 | ||
72 | test_expect_success 'Forget previous merge' ' | |
73 | git reset --hard "$pre_merge_head" | |
74 | ' | |
75 | ||
76 | test_expect_success 'Abort after --no-commit' ' | |
77 | # Redo merge, but stop before creating merge commit | |
78 | git merge --no-commit clean_branch && | |
79 | test -f .git/MERGE_HEAD && | |
80 | # Abort non-conflicting merge | |
81 | git merge --abort && | |
82 | test ! -f .git/MERGE_HEAD && | |
83 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
84 | test -z "$(git diff)" && | |
85 | test -z "$(git diff --staged)" | |
86 | ' | |
87 | ||
88 | test_expect_success 'Abort after conflicts' ' | |
89 | # Create conflicting merge | |
90 | test_must_fail git merge conflict_branch && | |
91 | test -f .git/MERGE_HEAD && | |
92 | # Abort conflicting merge | |
93 | git merge --abort && | |
94 | test ! -f .git/MERGE_HEAD && | |
95 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
96 | test -z "$(git diff)" && | |
97 | test -z "$(git diff --staged)" | |
98 | ' | |
99 | ||
100 | test_expect_success 'Clean merge with dirty index fails' ' | |
101 | echo xyzzy >> foo && | |
102 | git add foo && | |
103 | git diff --staged > expect && | |
104 | test_must_fail git merge clean_branch && | |
105 | test ! -f .git/MERGE_HEAD && | |
106 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
107 | test -z "$(git diff)" && | |
108 | git diff --staged > actual && | |
109 | test_cmp expect actual | |
110 | ' | |
111 | ||
112 | test_expect_success 'Conflicting merge with dirty index fails' ' | |
113 | test_must_fail git merge conflict_branch && | |
114 | test ! -f .git/MERGE_HEAD && | |
115 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
116 | test -z "$(git diff)" && | |
117 | git diff --staged > actual && | |
118 | test_cmp expect actual | |
119 | ' | |
120 | ||
121 | test_expect_success 'Reset index (but preserve worktree changes)' ' | |
122 | git reset "$pre_merge_head" && | |
123 | git diff > actual && | |
124 | test_cmp expect actual | |
125 | ' | |
126 | ||
127 | test_expect_success 'Abort clean merge with non-conflicting dirty worktree' ' | |
128 | git merge --no-commit clean_branch && | |
129 | test -f .git/MERGE_HEAD && | |
130 | # Abort merge | |
131 | git merge --abort && | |
132 | test ! -f .git/MERGE_HEAD && | |
133 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
134 | test -z "$(git diff --staged)" && | |
135 | git diff > actual && | |
136 | test_cmp expect actual | |
137 | ' | |
138 | ||
139 | test_expect_success 'Abort conflicting merge with non-conflicting dirty worktree' ' | |
140 | test_must_fail git merge conflict_branch && | |
141 | test -f .git/MERGE_HEAD && | |
142 | # Abort merge | |
143 | git merge --abort && | |
144 | test ! -f .git/MERGE_HEAD && | |
145 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
146 | test -z "$(git diff --staged)" && | |
147 | git diff > actual && | |
148 | test_cmp expect actual | |
149 | ' | |
150 | ||
151 | test_expect_success 'Reset worktree changes' ' | |
152 | git reset --hard "$pre_merge_head" | |
153 | ' | |
154 | ||
155 | test_expect_success 'Fail clean merge with conflicting dirty worktree' ' | |
156 | echo xyzzy >> bar && | |
157 | git diff > expect && | |
158 | test_must_fail git merge --no-commit clean_branch && | |
159 | test ! -f .git/MERGE_HEAD && | |
160 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
161 | test -z "$(git diff --staged)" && | |
162 | git diff > actual && | |
163 | test_cmp expect actual | |
164 | ' | |
165 | ||
166 | test_expect_success 'Fail conflicting merge with conflicting dirty worktree' ' | |
167 | test_must_fail git merge conflict_branch && | |
168 | test ! -f .git/MERGE_HEAD && | |
169 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
170 | test -z "$(git diff --staged)" && | |
171 | git diff > actual && | |
172 | test_cmp expect actual | |
173 | ' | |
174 | ||
175 | test_expect_success 'Reset worktree changes' ' | |
176 | git reset --hard "$pre_merge_head" | |
177 | ' | |
178 | ||
179 | test_expect_success 'Fail clean merge with matching dirty worktree' ' | |
180 | echo bart > bar && | |
181 | git diff > expect && | |
182 | test_must_fail git merge --no-commit clean_branch && | |
183 | test ! -f .git/MERGE_HEAD && | |
184 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
185 | test -z "$(git diff --staged)" && | |
186 | git diff > actual && | |
187 | test_cmp expect actual | |
188 | ' | |
189 | ||
190 | test_expect_success 'Abort clean merge with matching dirty index' ' | |
191 | git add bar && | |
192 | git diff --staged > expect && | |
193 | git merge --no-commit clean_branch && | |
194 | test -f .git/MERGE_HEAD && | |
195 | ### When aborting the merge, git will discard all staged changes, | |
196 | ### including those that were staged pre-merge. In other words, | |
197 | ### --abort will LOSE any staged changes (the staged changes that | |
198 | ### are lost must match the merge result, or the merge would not | |
199 | ### have been allowed to start). Change expectations accordingly: | |
200 | rm expect && | |
201 | touch expect && | |
202 | # Abort merge | |
203 | git merge --abort && | |
204 | test ! -f .git/MERGE_HEAD && | |
205 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
206 | git diff --staged > actual && | |
207 | test_cmp expect actual && | |
208 | test -z "$(git diff)" | |
209 | ' | |
210 | ||
211 | test_expect_success 'Reset worktree changes' ' | |
212 | git reset --hard "$pre_merge_head" | |
213 | ' | |
214 | ||
215 | test_expect_success 'Fail conflicting merge with matching dirty worktree' ' | |
216 | echo barf > bar && | |
217 | git diff > expect && | |
218 | test_must_fail git merge conflict_branch && | |
219 | test ! -f .git/MERGE_HEAD && | |
220 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
221 | test -z "$(git diff --staged)" && | |
222 | git diff > actual && | |
223 | test_cmp expect actual | |
224 | ' | |
225 | ||
226 | test_expect_success 'Abort conflicting merge with matching dirty index' ' | |
227 | git add bar && | |
228 | git diff --staged > expect && | |
229 | test_must_fail git merge conflict_branch && | |
230 | test -f .git/MERGE_HEAD && | |
231 | ### When aborting the merge, git will discard all staged changes, | |
232 | ### including those that were staged pre-merge. In other words, | |
233 | ### --abort will LOSE any staged changes (the staged changes that | |
234 | ### are lost must match the merge result, or the merge would not | |
235 | ### have been allowed to start). Change expectations accordingly: | |
236 | rm expect && | |
237 | touch expect && | |
238 | # Abort merge | |
239 | git merge --abort && | |
240 | test ! -f .git/MERGE_HEAD && | |
241 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
242 | git diff --staged > actual && | |
243 | test_cmp expect actual && | |
244 | test -z "$(git diff)" | |
245 | ' | |
246 | ||
247 | test_expect_success 'Reset worktree changes' ' | |
248 | git reset --hard "$pre_merge_head" | |
249 | ' | |
250 | ||
251 | test_expect_success 'Abort merge with pre- and post-merge worktree changes' ' | |
252 | # Pre-merge worktree changes | |
253 | echo xyzzy > foo && | |
254 | echo barf > bar && | |
255 | git add bar && | |
256 | git diff > expect && | |
257 | git diff --staged > expect-staged && | |
258 | # Perform merge | |
259 | test_must_fail git merge conflict_branch && | |
260 | test -f .git/MERGE_HEAD && | |
261 | # Post-merge worktree changes | |
262 | echo yzxxz > foo && | |
263 | echo blech > baz && | |
264 | ### When aborting the merge, git will discard staged changes (bar) | |
265 | ### and unmerged changes (baz). Other changes that are neither | |
266 | ### staged nor marked as unmerged (foo), will be preserved. For | |
267 | ### these changed, git cannot tell pre-merge changes apart from | |
268 | ### post-merge changes, so the post-merge changes will be | |
269 | ### preserved. Change expectations accordingly: | |
270 | git diff -- foo > expect && | |
271 | rm expect-staged && | |
272 | touch expect-staged && | |
273 | # Abort merge | |
274 | git merge --abort && | |
275 | test ! -f .git/MERGE_HEAD && | |
276 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
277 | git diff > actual && | |
278 | test_cmp expect actual && | |
279 | git diff --staged > actual-staged && | |
280 | test_cmp expect-staged actual-staged | |
281 | ' | |
282 | ||
283 | test_expect_success 'Reset worktree changes' ' | |
284 | git reset --hard "$pre_merge_head" | |
285 | ' | |
286 | ||
287 | test_expect_success 'Abort merge with pre- and post-merge index changes' ' | |
288 | # Pre-merge worktree changes | |
289 | echo xyzzy > foo && | |
290 | echo barf > bar && | |
291 | git add bar && | |
292 | git diff > expect && | |
293 | git diff --staged > expect-staged && | |
294 | # Perform merge | |
295 | test_must_fail git merge conflict_branch && | |
296 | test -f .git/MERGE_HEAD && | |
297 | # Post-merge worktree changes | |
298 | echo yzxxz > foo && | |
299 | echo blech > baz && | |
300 | git add foo bar && | |
301 | ### When aborting the merge, git will discard all staged changes | |
302 | ### (foo, bar and baz), and no changes will be preserved. Whether | |
303 | ### the changes were staged pre- or post-merge does not matter | |
304 | ### (except for not preventing starting the merge). | |
305 | ### Change expectations accordingly: | |
306 | rm expect expect-staged && | |
307 | touch expect && | |
308 | touch expect-staged && | |
309 | # Abort merge | |
310 | git merge --abort && | |
311 | test ! -f .git/MERGE_HEAD && | |
312 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
313 | git diff > actual && | |
314 | test_cmp expect actual && | |
315 | git diff --staged > actual-staged && | |
316 | test_cmp expect-staged actual-staged | |
317 | ' | |
318 | ||
319 | test_done |