]>
Commit | Line | Data |
---|---|---|
8f6aed71 JS |
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 | . ./test-lib.sh | |
20 | . "$TEST_DIRECTORY"/lib-rebase.sh | |
21 | ||
22 | test_cmp_graph () { | |
23 | cat >expect && | |
24 | git log --graph --boundary --format=%s "$@" >output && | |
25 | sed "s/ *$//" <output >output.trimmed && | |
26 | test_cmp expect output.trimmed | |
27 | } | |
28 | ||
29 | test_expect_success 'setup' ' | |
30 | write_script replace-editor.sh <<-\EOF && | |
31 | mv "$1" "$(git rev-parse --git-path ORIGINAL-TODO)" | |
32 | cp script-from-scratch "$1" | |
33 | EOF | |
34 | ||
35 | test_commit A && | |
36 | git checkout -b first && | |
37 | test_commit B && | |
38 | git checkout master && | |
39 | test_commit C && | |
40 | test_commit D && | |
41 | git merge --no-commit B && | |
42 | test_tick && | |
43 | git commit -m E && | |
44 | git tag -m E E && | |
45 | git checkout -b second C && | |
46 | test_commit F && | |
47 | test_commit G && | |
48 | git checkout master && | |
49 | git merge --no-commit G && | |
50 | test_tick && | |
51 | git commit -m H && | |
52 | git tag -m H H | |
53 | ' | |
54 | ||
55 | test_expect_success 'create completely different structure' ' | |
56 | cat >script-from-scratch <<-\EOF && | |
57 | label onto | |
58 | ||
59 | # onebranch | |
60 | pick G | |
61 | pick D | |
62 | label onebranch | |
63 | ||
64 | # second | |
65 | reset onto | |
66 | pick B | |
67 | label second | |
68 | ||
69 | reset onto | |
70 | merge -C H second | |
71 | merge onebranch # Merge the topic branch '\''onebranch'\'' | |
72 | EOF | |
73 | test_config sequence.editor \""$PWD"/replace-editor.sh\" && | |
74 | test_tick && | |
75 | git rebase -i -r A && | |
76 | test_cmp_graph <<-\EOF | |
77 | * Merge the topic branch '\''onebranch'\'' | |
78 | |\ | |
79 | | * D | |
80 | | * G | |
81 | * | H | |
82 | |\ \ | |
83 | | |/ | |
84 | |/| | |
85 | | * B | |
86 | |/ | |
87 | * A | |
88 | EOF | |
89 | ' | |
90 | ||
91 | test_expect_success 'generate correct todo list' ' | |
92 | cat >expect <<-\EOF && | |
93 | label onto | |
94 | ||
95 | reset onto | |
96 | pick d9df450 B | |
97 | label E | |
98 | ||
99 | reset onto | |
100 | pick 5dee784 C | |
101 | label branch-point | |
102 | pick ca2c861 F | |
103 | pick 088b00a G | |
104 | label H | |
105 | ||
106 | reset branch-point # C | |
107 | pick 12bd07b D | |
108 | merge -C 2051b56 E # E | |
109 | merge -C 233d48a H # H | |
110 | ||
111 | EOF | |
112 | ||
113 | grep -v "^#" <.git/ORIGINAL-TODO >output && | |
114 | test_cmp expect output | |
115 | ' | |
116 | ||
117 | test_expect_success '`reset` refuses to overwrite untracked files' ' | |
118 | git checkout -b refuse-to-reset && | |
119 | test_commit dont-overwrite-untracked && | |
120 | git checkout @{-1} && | |
121 | : >dont-overwrite-untracked.t && | |
122 | echo "reset refs/tags/dont-overwrite-untracked" >script-from-scratch && | |
123 | test_config sequence.editor \""$PWD"/replace-editor.sh\" && | |
124 | test_must_fail git rebase -r HEAD && | |
125 | git rebase --abort | |
126 | ' | |
127 | ||
128 | test_expect_success 'failed `merge` writes patch (may be rescheduled, too)' ' | |
129 | test_when_finished "test_might_fail git rebase --abort" && | |
130 | git checkout -b conflicting-merge A && | |
131 | ||
132 | : fail because of conflicting untracked file && | |
133 | >G.t && | |
134 | echo "merge -C H G" >script-from-scratch && | |
135 | test_config sequence.editor \""$PWD"/replace-editor.sh\" && | |
136 | test_tick && | |
137 | test_must_fail git rebase -ir HEAD && | |
138 | grep "^merge -C .* G$" .git/rebase-merge/done && | |
139 | grep "^merge -C .* G$" .git/rebase-merge/git-rebase-todo && | |
140 | test_path_is_file .git/rebase-merge/patch && | |
141 | ||
142 | : fail because of merge conflict && | |
143 | rm G.t .git/rebase-merge/patch && | |
144 | git reset --hard && | |
145 | test_commit conflicting-G G.t not-G conflicting-G && | |
146 | test_must_fail git rebase --continue && | |
147 | ! grep "^merge -C .* G$" .git/rebase-merge/git-rebase-todo && | |
148 | test_path_is_file .git/rebase-merge/patch | |
149 | ' | |
150 | ||
151 | test_expect_success 'with a branch tip that was cherry-picked already' ' | |
152 | git checkout -b already-upstream master && | |
153 | base="$(git rev-parse --verify HEAD)" && | |
154 | ||
155 | test_commit A1 && | |
156 | test_commit A2 && | |
157 | git reset --hard $base && | |
158 | test_commit B1 && | |
159 | test_tick && | |
160 | git merge -m "Merge branch A" A2 && | |
161 | ||
162 | git checkout -b upstream-with-a2 $base && | |
163 | test_tick && | |
164 | git cherry-pick A2 && | |
165 | ||
166 | git checkout already-upstream && | |
167 | test_tick && | |
168 | git rebase -i -r upstream-with-a2 && | |
169 | test_cmp_graph upstream-with-a2.. <<-\EOF | |
170 | * Merge branch A | |
171 | |\ | |
172 | | * A1 | |
173 | * | B1 | |
174 | |/ | |
175 | o A2 | |
176 | EOF | |
177 | ' | |
178 | ||
7543f6f4 JS |
179 | test_expect_success 'do not rebase cousins unless asked for' ' |
180 | git checkout -b cousins master && | |
181 | before="$(git rev-parse --verify HEAD)" && | |
182 | test_tick && | |
183 | git rebase -r HEAD^ && | |
184 | test_cmp_rev HEAD $before && | |
185 | test_tick && | |
186 | git rebase --rebase-merges=rebase-cousins HEAD^ && | |
187 | test_cmp_graph HEAD^.. <<-\EOF | |
188 | * Merge the topic branch '\''onebranch'\'' | |
189 | |\ | |
190 | | * D | |
191 | | * G | |
192 | |/ | |
193 | o H | |
194 | EOF | |
195 | ' | |
196 | ||
a9be29c9 JS |
197 | test_expect_success 'refs/rewritten/* is worktree-local' ' |
198 | git worktree add wt && | |
199 | cat >wt/script-from-scratch <<-\EOF && | |
200 | label xyz | |
201 | exec GIT_DIR=../.git git rev-parse --verify refs/rewritten/xyz >a || : | |
202 | exec git rev-parse --verify refs/rewritten/xyz >b | |
203 | EOF | |
204 | ||
205 | test_config -C wt sequence.editor \""$PWD"/replace-editor.sh\" && | |
206 | git -C wt rebase -i HEAD && | |
207 | test_must_be_empty wt/a && | |
208 | test_cmp_rev HEAD "$(cat wt/b)" | |
209 | ' | |
210 | ||
537e7d61 JS |
211 | test_expect_success 'post-rewrite hook and fixups work for merges' ' |
212 | git checkout -b post-rewrite && | |
213 | test_commit same1 && | |
214 | git reset --hard HEAD^ && | |
215 | test_commit same2 && | |
216 | git merge -m "to fix up" same1 && | |
217 | echo same old same old >same2.t && | |
218 | test_tick && | |
219 | git commit --fixup HEAD same2.t && | |
220 | fixup="$(git rev-parse HEAD)" && | |
221 | ||
222 | mkdir -p .git/hooks && | |
223 | test_when_finished "rm .git/hooks/post-rewrite" && | |
224 | echo "cat >actual" | write_script .git/hooks/post-rewrite && | |
225 | ||
226 | test_tick && | |
227 | git rebase -i --autosquash -r HEAD^^^ && | |
228 | printf "%s %s\n%s %s\n%s %s\n%s %s\n" >expect $(git rev-parse \ | |
229 | $fixup^^2 HEAD^2 \ | |
230 | $fixup^^ HEAD^ \ | |
231 | $fixup^ HEAD \ | |
232 | $fixup HEAD) && | |
233 | test_cmp expect actual | |
234 | ' | |
235 | ||
7ccdf65b JS |
236 | test_expect_success 'refuse to merge ancestors of HEAD' ' |
237 | echo "merge HEAD^" >script-from-scratch && | |
238 | test_config -C wt sequence.editor \""$PWD"/replace-editor.sh\" && | |
239 | before="$(git rev-parse HEAD)" && | |
240 | git rebase -i HEAD && | |
241 | test_cmp_rev HEAD $before | |
242 | ' | |
243 | ||
ebddf393 JS |
244 | test_expect_success 'root commits' ' |
245 | git checkout --orphan unrelated && | |
246 | (GIT_AUTHOR_NAME="Parsnip" GIT_AUTHOR_EMAIL="root@example.com" \ | |
247 | test_commit second-root) && | |
248 | test_commit third-root && | |
249 | cat >script-from-scratch <<-\EOF && | |
250 | pick third-root | |
251 | label first-branch | |
252 | reset [new root] | |
253 | pick second-root | |
254 | merge first-branch # Merge the 3rd root | |
255 | EOF | |
256 | test_config sequence.editor \""$PWD"/replace-editor.sh\" && | |
257 | test_tick && | |
258 | git rebase -i --force --root -r && | |
259 | test "Parsnip" = "$(git show -s --format=%an HEAD^)" && | |
260 | test $(git rev-parse second-root^0) != $(git rev-parse HEAD^) && | |
261 | test $(git rev-parse second-root:second-root.t) = \ | |
262 | $(git rev-parse HEAD^:second-root.t) && | |
263 | test_cmp_graph HEAD <<-\EOF && | |
264 | * Merge the 3rd root | |
265 | |\ | |
266 | | * third-root | |
267 | * second-root | |
268 | EOF | |
269 | ||
270 | : fast forward if possible && | |
271 | before="$(git rev-parse --verify HEAD)" && | |
272 | test_might_fail git config --unset sequence.editor && | |
273 | test_tick && | |
274 | git rebase -i --root -r && | |
275 | test_cmp_rev HEAD $before | |
276 | ' | |
277 | ||
8f6aed71 | 278 | test_done |