]> git.ipfire.org Git - thirdparty/git.git/blob - t/t3430-rebase-merges.sh
t3430: add conflicting commit
[thirdparty/git.git] / t / t3430-rebase-merges.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2018 Johannes E. Schindelin
4 #
5
6 test_description='git rebase -i --rebase-merges
7
8 This test runs git rebase "interactively", retaining the branch structure by
9 recreating merge commits.
10
11 Initial setup:
12
13 -- B -- (first)
14 / \
15 A - C - D - E - H (master)
16 \ \ /
17 \ F - G (second)
18 \
19 Conflicting-G
20 '
21 . ./test-lib.sh
22 . "$TEST_DIRECTORY"/lib-rebase.sh
23
24 test_cmp_graph () {
25 cat >expect &&
26 git log --graph --boundary --format=%s "$@" >output &&
27 sed "s/ *$//" <output >output.trimmed &&
28 test_cmp expect output.trimmed
29 }
30
31 test_expect_success 'setup' '
32 write_script replace-editor.sh <<-\EOF &&
33 mv "$1" "$(git rev-parse --git-path ORIGINAL-TODO)"
34 cp script-from-scratch "$1"
35 EOF
36
37 test_commit A &&
38 git checkout -b first &&
39 test_commit B &&
40 git checkout master &&
41 test_commit C &&
42 test_commit D &&
43 git merge --no-commit B &&
44 test_tick &&
45 git commit -m E &&
46 git tag -m E E &&
47 git checkout -b second C &&
48 test_commit F &&
49 test_commit G &&
50 git checkout master &&
51 git merge --no-commit G &&
52 test_tick &&
53 git commit -m H &&
54 git tag -m H H &&
55 git checkout A &&
56 test_commit conflicting-G G.t
57 '
58
59 test_expect_success 'create completely different structure' '
60 cat >script-from-scratch <<-\EOF &&
61 label onto
62
63 # onebranch
64 pick G
65 pick D
66 label onebranch
67
68 # second
69 reset onto
70 pick B
71 label second
72
73 reset onto
74 merge -C H second
75 merge onebranch # Merge the topic branch '\''onebranch'\''
76 EOF
77 test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
78 test_tick &&
79 git rebase -i -r A master &&
80 test_cmp_graph <<-\EOF
81 * Merge the topic branch '\''onebranch'\''
82 |\
83 | * D
84 | * G
85 * | H
86 |\ \
87 | |/
88 |/|
89 | * B
90 |/
91 * A
92 EOF
93 '
94
95 test_expect_success 'generate correct todo list' '
96 cat >expect <<-\EOF &&
97 label onto
98
99 reset onto
100 pick d9df450 B
101 label E
102
103 reset onto
104 pick 5dee784 C
105 label branch-point
106 pick ca2c861 F
107 pick 088b00a G
108 label H
109
110 reset branch-point # C
111 pick 12bd07b D
112 merge -C 2051b56 E # E
113 merge -C 233d48a H # H
114
115 EOF
116
117 grep -v "^#" <.git/ORIGINAL-TODO >output &&
118 test_cmp expect output
119 '
120
121 test_expect_success '`reset` refuses to overwrite untracked files' '
122 git checkout -b refuse-to-reset &&
123 test_commit dont-overwrite-untracked &&
124 git checkout @{-1} &&
125 : >dont-overwrite-untracked.t &&
126 echo "reset refs/tags/dont-overwrite-untracked" >script-from-scratch &&
127 test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
128 test_must_fail git rebase -r HEAD &&
129 git rebase --abort
130 '
131
132 test_expect_success 'failed `merge` writes patch (may be rescheduled, too)' '
133 test_when_finished "test_might_fail git rebase --abort" &&
134 git checkout -b conflicting-merge A &&
135
136 : fail because of conflicting untracked file &&
137 >G.t &&
138 echo "merge -C H G" >script-from-scratch &&
139 test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
140 test_tick &&
141 test_must_fail git rebase -ir HEAD &&
142 grep "^merge -C .* G$" .git/rebase-merge/done &&
143 grep "^merge -C .* G$" .git/rebase-merge/git-rebase-todo &&
144 test_path_is_file .git/rebase-merge/patch &&
145
146 : fail because of merge conflict &&
147 rm G.t .git/rebase-merge/patch &&
148 git reset --hard conflicting-G &&
149 test_must_fail git rebase --continue &&
150 ! grep "^merge -C .* G$" .git/rebase-merge/git-rebase-todo &&
151 test_path_is_file .git/rebase-merge/patch
152 '
153
154 test_expect_success 'with a branch tip that was cherry-picked already' '
155 git checkout -b already-upstream master &&
156 base="$(git rev-parse --verify HEAD)" &&
157
158 test_commit A1 &&
159 test_commit A2 &&
160 git reset --hard $base &&
161 test_commit B1 &&
162 test_tick &&
163 git merge -m "Merge branch A" A2 &&
164
165 git checkout -b upstream-with-a2 $base &&
166 test_tick &&
167 git cherry-pick A2 &&
168
169 git checkout already-upstream &&
170 test_tick &&
171 git rebase -i -r upstream-with-a2 &&
172 test_cmp_graph upstream-with-a2.. <<-\EOF
173 * Merge branch A
174 |\
175 | * A1
176 * | B1
177 |/
178 o A2
179 EOF
180 '
181
182 test_expect_success 'do not rebase cousins unless asked for' '
183 git checkout -b cousins master &&
184 before="$(git rev-parse --verify HEAD)" &&
185 test_tick &&
186 git rebase -r HEAD^ &&
187 test_cmp_rev HEAD $before &&
188 test_tick &&
189 git rebase --rebase-merges=rebase-cousins HEAD^ &&
190 test_cmp_graph HEAD^.. <<-\EOF
191 * Merge the topic branch '\''onebranch'\''
192 |\
193 | * D
194 | * G
195 |/
196 o H
197 EOF
198 '
199
200 test_expect_success 'refs/rewritten/* is worktree-local' '
201 git worktree add wt &&
202 cat >wt/script-from-scratch <<-\EOF &&
203 label xyz
204 exec GIT_DIR=../.git git rev-parse --verify refs/rewritten/xyz >a || :
205 exec git rev-parse --verify refs/rewritten/xyz >b
206 EOF
207
208 test_config -C wt sequence.editor \""$PWD"/replace-editor.sh\" &&
209 git -C wt rebase -i HEAD &&
210 test_must_be_empty wt/a &&
211 test_cmp_rev HEAD "$(cat wt/b)"
212 '
213
214 test_expect_success 'post-rewrite hook and fixups work for merges' '
215 git checkout -b post-rewrite &&
216 test_commit same1 &&
217 git reset --hard HEAD^ &&
218 test_commit same2 &&
219 git merge -m "to fix up" same1 &&
220 echo same old same old >same2.t &&
221 test_tick &&
222 git commit --fixup HEAD same2.t &&
223 fixup="$(git rev-parse HEAD)" &&
224
225 mkdir -p .git/hooks &&
226 test_when_finished "rm .git/hooks/post-rewrite" &&
227 echo "cat >actual" | write_script .git/hooks/post-rewrite &&
228
229 test_tick &&
230 git rebase -i --autosquash -r HEAD^^^ &&
231 printf "%s %s\n%s %s\n%s %s\n%s %s\n" >expect $(git rev-parse \
232 $fixup^^2 HEAD^2 \
233 $fixup^^ HEAD^ \
234 $fixup^ HEAD \
235 $fixup HEAD) &&
236 test_cmp expect actual
237 '
238
239 test_expect_success 'refuse to merge ancestors of HEAD' '
240 echo "merge HEAD^" >script-from-scratch &&
241 test_config -C wt sequence.editor \""$PWD"/replace-editor.sh\" &&
242 before="$(git rev-parse HEAD)" &&
243 git rebase -i HEAD &&
244 test_cmp_rev HEAD $before
245 '
246
247 test_expect_success 'root commits' '
248 git checkout --orphan unrelated &&
249 (GIT_AUTHOR_NAME="Parsnip" GIT_AUTHOR_EMAIL="root@example.com" \
250 test_commit second-root) &&
251 test_commit third-root &&
252 cat >script-from-scratch <<-\EOF &&
253 pick third-root
254 label first-branch
255 reset [new root]
256 pick second-root
257 merge first-branch # Merge the 3rd root
258 EOF
259 test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
260 test_tick &&
261 git rebase -i --force --root -r &&
262 test "Parsnip" = "$(git show -s --format=%an HEAD^)" &&
263 test $(git rev-parse second-root^0) != $(git rev-parse HEAD^) &&
264 test $(git rev-parse second-root:second-root.t) = \
265 $(git rev-parse HEAD^:second-root.t) &&
266 test_cmp_graph HEAD <<-\EOF &&
267 * Merge the 3rd root
268 |\
269 | * third-root
270 * second-root
271 EOF
272
273 : fast forward if possible &&
274 before="$(git rev-parse --verify HEAD)" &&
275 test_might_fail git config --unset sequence.editor &&
276 test_tick &&
277 git rebase -i --root -r &&
278 test_cmp_rev HEAD $before
279 '
280
281 test_expect_success 'a "merge" into a root commit is a fast-forward' '
282 head=$(git rev-parse HEAD) &&
283 cat >script-from-scratch <<-EOF &&
284 reset [new root]
285 merge $head
286 EOF
287 test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
288 test_tick &&
289 git rebase -i -r HEAD^ &&
290 test_cmp_rev HEAD $head
291 '
292
293 test_expect_success 'A root commit can be a cousin, treat it that way' '
294 git checkout --orphan khnum &&
295 test_commit yama &&
296 git checkout -b asherah master &&
297 test_commit shamkat &&
298 git merge --allow-unrelated-histories khnum &&
299 test_tick &&
300 git rebase -f -r HEAD^ &&
301 ! test_cmp_rev HEAD^2 khnum &&
302 test_cmp_graph HEAD^.. <<-\EOF &&
303 * Merge branch '\''khnum'\'' into asherah
304 |\
305 | * yama
306 o shamkat
307 EOF
308 test_tick &&
309 git rebase --rebase-merges=rebase-cousins HEAD^ &&
310 test_cmp_graph HEAD^.. <<-\EOF
311 * Merge branch '\''khnum'\'' into asherah
312 |\
313 | * yama
314 |/
315 o shamkat
316 EOF
317 '
318
319 test_expect_success 'labels that are object IDs are rewritten' '
320 git checkout -b third B &&
321 test_commit I &&
322 third=$(git rev-parse HEAD) &&
323 git checkout -b labels master &&
324 git merge --no-commit third &&
325 test_tick &&
326 git commit -m "Merge commit '\''$third'\'' into labels" &&
327 echo noop >script-from-scratch &&
328 test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
329 test_tick &&
330 git rebase -i -r A &&
331 grep "^label $third-" .git/ORIGINAL-TODO &&
332 ! grep "^label $third$" .git/ORIGINAL-TODO
333 '
334
335 test_done