]>
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)' ' | |
49 | test_must_fail git merge --abort 2>output && | |
50 | grep -q MERGE_HEAD output && | |
51 | test ! -f .git/MERGE_HEAD && | |
52 | test "$pre_merge_head" = "$(git rev-parse HEAD)" | |
53 | ' | |
54 | ||
55 | test_expect_success 'fails without MERGE_HEAD (completed merge)' ' | |
56 | git merge clean_branch && | |
57 | test ! -f .git/MERGE_HEAD && | |
58 | # Merge successfully completed | |
59 | post_merge_head="$(git rev-parse HEAD)" && | |
60 | test_must_fail git merge --abort 2>output && | |
61 | grep -q MERGE_HEAD output && | |
62 | test ! -f .git/MERGE_HEAD && | |
63 | test "$post_merge_head" = "$(git rev-parse HEAD)" | |
64 | ' | |
65 | ||
66 | test_expect_success 'Forget previous merge' ' | |
67 | git reset --hard "$pre_merge_head" | |
68 | ' | |
69 | ||
70 | test_expect_success 'Abort after --no-commit' ' | |
71 | # Redo merge, but stop before creating merge commit | |
72 | git merge --no-commit clean_branch && | |
73 | test -f .git/MERGE_HEAD && | |
74 | # Abort non-conflicting merge | |
75 | git merge --abort && | |
76 | test ! -f .git/MERGE_HEAD && | |
77 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
78 | test -z "$(git diff)" && | |
79 | test -z "$(git diff --staged)" | |
80 | ' | |
81 | ||
82 | test_expect_success 'Abort after conflicts' ' | |
83 | # Create conflicting merge | |
84 | test_must_fail git merge conflict_branch && | |
85 | test -f .git/MERGE_HEAD && | |
86 | # Abort conflicting merge | |
87 | git merge --abort && | |
88 | test ! -f .git/MERGE_HEAD && | |
89 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
90 | test -z "$(git diff)" && | |
91 | test -z "$(git diff --staged)" | |
92 | ' | |
93 | ||
94 | test_expect_success 'Clean merge with dirty index fails' ' | |
95 | echo xyzzy >> foo && | |
96 | git add foo && | |
97 | git diff --staged > expect && | |
98 | test_must_fail git merge clean_branch && | |
99 | test ! -f .git/MERGE_HEAD && | |
100 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
101 | test -z "$(git diff)" && | |
102 | git diff --staged > actual && | |
103 | test_cmp expect actual | |
104 | ' | |
105 | ||
106 | test_expect_success 'Conflicting merge with dirty index fails' ' | |
107 | test_must_fail git merge conflict_branch && | |
108 | test ! -f .git/MERGE_HEAD && | |
109 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
110 | test -z "$(git diff)" && | |
111 | git diff --staged > actual && | |
112 | test_cmp expect actual | |
113 | ' | |
114 | ||
115 | test_expect_success 'Reset index (but preserve worktree changes)' ' | |
116 | git reset "$pre_merge_head" && | |
117 | git diff > actual && | |
118 | test_cmp expect actual | |
119 | ' | |
120 | ||
121 | test_expect_success 'Abort clean merge with non-conflicting dirty worktree' ' | |
122 | git merge --no-commit clean_branch && | |
123 | test -f .git/MERGE_HEAD && | |
124 | # Abort merge | |
125 | git merge --abort && | |
126 | test ! -f .git/MERGE_HEAD && | |
127 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
128 | test -z "$(git diff --staged)" && | |
129 | git diff > actual && | |
130 | test_cmp expect actual | |
131 | ' | |
132 | ||
133 | test_expect_success 'Abort conflicting merge with non-conflicting dirty worktree' ' | |
134 | test_must_fail git merge conflict_branch && | |
135 | test -f .git/MERGE_HEAD && | |
136 | # Abort merge | |
137 | git merge --abort && | |
138 | test ! -f .git/MERGE_HEAD && | |
139 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
140 | test -z "$(git diff --staged)" && | |
141 | git diff > actual && | |
142 | test_cmp expect actual | |
143 | ' | |
144 | ||
145 | test_expect_success 'Reset worktree changes' ' | |
146 | git reset --hard "$pre_merge_head" | |
147 | ' | |
148 | ||
149 | test_expect_success 'Fail clean merge with conflicting dirty worktree' ' | |
150 | echo xyzzy >> bar && | |
151 | git diff > expect && | |
152 | test_must_fail git merge --no-commit clean_branch && | |
153 | test ! -f .git/MERGE_HEAD && | |
154 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
155 | test -z "$(git diff --staged)" && | |
156 | git diff > actual && | |
157 | test_cmp expect actual | |
158 | ' | |
159 | ||
160 | test_expect_success 'Fail conflicting merge with conflicting dirty worktree' ' | |
161 | test_must_fail git merge conflict_branch && | |
162 | test ! -f .git/MERGE_HEAD && | |
163 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
164 | test -z "$(git diff --staged)" && | |
165 | git diff > actual && | |
166 | test_cmp expect actual | |
167 | ' | |
168 | ||
169 | test_expect_success 'Reset worktree changes' ' | |
170 | git reset --hard "$pre_merge_head" | |
171 | ' | |
172 | ||
173 | test_expect_success 'Fail clean merge with matching dirty worktree' ' | |
174 | echo bart > bar && | |
175 | git diff > expect && | |
176 | test_must_fail git merge --no-commit clean_branch && | |
177 | test ! -f .git/MERGE_HEAD && | |
178 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
179 | test -z "$(git diff --staged)" && | |
180 | git diff > actual && | |
181 | test_cmp expect actual | |
182 | ' | |
183 | ||
184 | test_expect_success 'Abort clean merge with matching dirty index' ' | |
185 | git add bar && | |
186 | git diff --staged > expect && | |
187 | git merge --no-commit clean_branch && | |
188 | test -f .git/MERGE_HEAD && | |
189 | ### When aborting the merge, git will discard all staged changes, | |
190 | ### including those that were staged pre-merge. In other words, | |
191 | ### --abort will LOSE any staged changes (the staged changes that | |
192 | ### are lost must match the merge result, or the merge would not | |
193 | ### have been allowed to start). Change expectations accordingly: | |
194 | rm expect && | |
195 | touch expect && | |
196 | # Abort merge | |
197 | git merge --abort && | |
198 | test ! -f .git/MERGE_HEAD && | |
199 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
200 | git diff --staged > actual && | |
201 | test_cmp expect actual && | |
202 | test -z "$(git diff)" | |
203 | ' | |
204 | ||
205 | test_expect_success 'Reset worktree changes' ' | |
206 | git reset --hard "$pre_merge_head" | |
207 | ' | |
208 | ||
209 | test_expect_success 'Fail conflicting merge with matching dirty worktree' ' | |
210 | echo barf > bar && | |
211 | git diff > expect && | |
212 | test_must_fail git merge conflict_branch && | |
213 | test ! -f .git/MERGE_HEAD && | |
214 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
215 | test -z "$(git diff --staged)" && | |
216 | git diff > actual && | |
217 | test_cmp expect actual | |
218 | ' | |
219 | ||
220 | test_expect_success 'Abort conflicting merge with matching dirty index' ' | |
221 | git add bar && | |
222 | git diff --staged > expect && | |
223 | test_must_fail git merge conflict_branch && | |
224 | test -f .git/MERGE_HEAD && | |
225 | ### When aborting the merge, git will discard all staged changes, | |
226 | ### including those that were staged pre-merge. In other words, | |
227 | ### --abort will LOSE any staged changes (the staged changes that | |
228 | ### are lost must match the merge result, or the merge would not | |
229 | ### have been allowed to start). Change expectations accordingly: | |
230 | rm expect && | |
231 | touch expect && | |
232 | # Abort merge | |
233 | git merge --abort && | |
234 | test ! -f .git/MERGE_HEAD && | |
235 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
236 | git diff --staged > actual && | |
237 | test_cmp expect actual && | |
238 | test -z "$(git diff)" | |
239 | ' | |
240 | ||
241 | test_expect_success 'Reset worktree changes' ' | |
242 | git reset --hard "$pre_merge_head" | |
243 | ' | |
244 | ||
245 | test_expect_success 'Abort merge with pre- and post-merge worktree changes' ' | |
246 | # Pre-merge worktree changes | |
247 | echo xyzzy > foo && | |
248 | echo barf > bar && | |
249 | git add bar && | |
250 | git diff > expect && | |
251 | git diff --staged > expect-staged && | |
252 | # Perform merge | |
253 | test_must_fail git merge conflict_branch && | |
254 | test -f .git/MERGE_HEAD && | |
255 | # Post-merge worktree changes | |
256 | echo yzxxz > foo && | |
257 | echo blech > baz && | |
258 | ### When aborting the merge, git will discard staged changes (bar) | |
259 | ### and unmerged changes (baz). Other changes that are neither | |
260 | ### staged nor marked as unmerged (foo), will be preserved. For | |
261 | ### these changed, git cannot tell pre-merge changes apart from | |
262 | ### post-merge changes, so the post-merge changes will be | |
263 | ### preserved. Change expectations accordingly: | |
264 | git diff -- foo > expect && | |
265 | rm expect-staged && | |
266 | touch expect-staged && | |
267 | # Abort merge | |
268 | git merge --abort && | |
269 | test ! -f .git/MERGE_HEAD && | |
270 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
271 | git diff > actual && | |
272 | test_cmp expect actual && | |
273 | git diff --staged > actual-staged && | |
274 | test_cmp expect-staged actual-staged | |
275 | ' | |
276 | ||
277 | test_expect_success 'Reset worktree changes' ' | |
278 | git reset --hard "$pre_merge_head" | |
279 | ' | |
280 | ||
281 | test_expect_success 'Abort merge with pre- and post-merge index changes' ' | |
282 | # Pre-merge worktree changes | |
283 | echo xyzzy > foo && | |
284 | echo barf > bar && | |
285 | git add bar && | |
286 | git diff > expect && | |
287 | git diff --staged > expect-staged && | |
288 | # Perform merge | |
289 | test_must_fail git merge conflict_branch && | |
290 | test -f .git/MERGE_HEAD && | |
291 | # Post-merge worktree changes | |
292 | echo yzxxz > foo && | |
293 | echo blech > baz && | |
294 | git add foo bar && | |
295 | ### When aborting the merge, git will discard all staged changes | |
296 | ### (foo, bar and baz), and no changes will be preserved. Whether | |
297 | ### the changes were staged pre- or post-merge does not matter | |
298 | ### (except for not preventing starting the merge). | |
299 | ### Change expectations accordingly: | |
300 | rm expect expect-staged && | |
301 | touch expect && | |
302 | touch expect-staged && | |
303 | # Abort merge | |
304 | git merge --abort && | |
305 | test ! -f .git/MERGE_HEAD && | |
306 | test "$pre_merge_head" = "$(git rev-parse HEAD)" && | |
307 | git diff > actual && | |
308 | test_cmp expect actual && | |
309 | git diff --staged > actual-staged && | |
310 | test_cmp expect-staged actual-staged | |
311 | ' | |
312 | ||
313 | test_done |