Sync with 'maint'
[alt-git.git] / t / t3400-rebase.sh
blob09f230eefb2cbc03a6b8f85e0f5c39cfcb2467d5
1 #!/bin/sh
3 # Copyright (c) 2005 Amos Waterland
6 test_description='git rebase assorted tests
8 This test runs git rebase and checks that the author information is not lost
9 among other things.
11 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
12 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
14 TEST_PASSES_SANITIZE_LEAK=true
15 . ./test-lib.sh
17 GIT_AUTHOR_NAME=author@name
18 GIT_AUTHOR_EMAIL=bogus@email@address
19 export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL
21 test_expect_success 'prepare repository with topic branches' '
22 test_commit "Add A." A First First &&
23 git checkout -b force-3way &&
24 echo Dummy >Y &&
25 git update-index --add Y &&
26 git commit -m "Add Y." &&
27 git checkout -b filemove &&
28 git reset --soft main &&
29 mkdir D &&
30 git mv A D/A &&
31 git commit -m "Move A." &&
32 git checkout -b my-topic-branch main &&
33 test_commit "Add B." B Second Second &&
34 git checkout -f main &&
35 echo Third >>A &&
36 git update-index A &&
37 git commit -m "Modify A." &&
38 git checkout -b side my-topic-branch &&
39 echo Side >>C &&
40 git add C &&
41 git commit -m "Add C" &&
42 git checkout -f my-topic-branch &&
43 git tag topic
46 test_expect_success 'rebase on dirty worktree' '
47 echo dirty >>A &&
48 test_must_fail git rebase main
51 test_expect_success 'rebase on dirty cache' '
52 git add A &&
53 test_must_fail git rebase main
56 test_expect_success 'rebase against main' '
57 git reset --hard HEAD &&
58 git rebase main
61 test_expect_success 'rebase sets ORIG_HEAD to pre-rebase state' '
62 git checkout -b orig-head topic &&
63 pre="$(git rev-parse --verify HEAD)" &&
64 git rebase main &&
65 test_cmp_rev "$pre" ORIG_HEAD &&
66 test_cmp_rev ! "$pre" HEAD
69 test_expect_success 'rebase, with <onto> and <upstream> specified as :/quuxery' '
70 test_when_finished "git branch -D torebase" &&
71 git checkout -b torebase my-topic-branch^ &&
72 upstream=$(git rev-parse ":/Add B") &&
73 onto=$(git rev-parse ":/Add A") &&
74 git rebase --onto $onto $upstream &&
75 git reset --hard my-topic-branch^ &&
76 git rebase --onto ":/Add A" ":/Add B" &&
77 git checkout my-topic-branch
80 test_expect_success 'the rebase operation should not have destroyed author information' '
81 ! (git log | grep "Author:" | grep "<>")
84 test_expect_success 'the rebase operation should not have destroyed author information (2)' "
85 git log -1 |
86 grep 'Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>'
89 test_expect_success 'HEAD was detached during rebase' '
90 test $(git rev-parse HEAD@{1}) != $(git rev-parse my-topic-branch@{1})
93 test_expect_success 'rebase from ambiguous branch name' '
94 git checkout -b topic side &&
95 git rebase main
98 test_expect_success 'rebase off of the previous branch using "-"' '
99 git checkout main &&
100 git checkout HEAD^ &&
101 git rebase @{-1} >expect.messages &&
102 git merge-base main HEAD >expect.forkpoint &&
104 git checkout main &&
105 git checkout HEAD^ &&
106 git rebase - >actual.messages &&
107 git merge-base main HEAD >actual.forkpoint &&
109 test_cmp expect.forkpoint actual.forkpoint &&
110 # the next one is dubious---we may want to say "-",
111 # instead of @{-1}, in the message
112 test_cmp expect.messages actual.messages
115 test_expect_success 'rebase a single mode change' '
116 git checkout main &&
117 git branch -D topic &&
118 echo 1 >X &&
119 git add X &&
120 test_tick &&
121 git commit -m prepare &&
122 git checkout -b modechange HEAD^ &&
123 echo 1 >X &&
124 git add X &&
125 test_chmod +x A &&
126 test_tick &&
127 git commit -m modechange &&
128 GIT_TRACE=1 git rebase main
131 test_expect_success 'rebase is not broken by diff.renames' '
132 test_config diff.renames copies &&
133 git checkout filemove &&
134 GIT_TRACE=1 git rebase force-3way
137 test_expect_success 'setup: recover' '
138 test_might_fail git rebase --abort &&
139 git reset --hard &&
140 git checkout modechange
143 test_expect_success 'Show verbose error when HEAD could not be detached' '
144 >B &&
145 test_when_finished "rm -f B" &&
146 test_must_fail git rebase topic 2>output.err >output.out &&
147 test_grep "The following untracked working tree files would be overwritten by checkout:" output.err &&
148 test_grep B output.err &&
149 test_must_fail git rebase --quit 2>err &&
150 test_grep "no rebase in progress" err
153 test_expect_success 'fail when upstream arg is missing and not on branch' '
154 git checkout topic &&
155 test_must_fail git rebase
158 test_expect_success 'fail when upstream arg is missing and not configured' '
159 git checkout -b no-config topic &&
160 test_must_fail git rebase
163 test_expect_success 'rebase works with format.useAutoBase' '
164 test_config format.useAutoBase true &&
165 git checkout topic &&
166 git rebase main
169 test_expect_success 'default to common base in @{upstream}s reflog if no upstream arg (--merge)' '
170 git checkout -b default-base main &&
171 git checkout -b default topic &&
172 git config branch.default.remote . &&
173 git config branch.default.merge refs/heads/default-base &&
174 git rebase --merge &&
175 git rev-parse --verify default-base >expect &&
176 git rev-parse default~1 >actual &&
177 test_cmp expect actual &&
178 git checkout default-base &&
179 git reset --hard HEAD^ &&
180 git checkout default &&
181 git rebase --merge &&
182 git rev-parse --verify default-base >expect &&
183 git rev-parse default~1 >actual &&
184 test_cmp expect actual
187 test_expect_success 'default to common base in @{upstream}s reflog if no upstream arg (--apply)' '
188 git checkout -B default-base main &&
189 git checkout -B default topic &&
190 git config branch.default.remote . &&
191 git config branch.default.merge refs/heads/default-base &&
192 git rebase --apply &&
193 git rev-parse --verify default-base >expect &&
194 git rev-parse default~1 >actual &&
195 test_cmp expect actual &&
196 git checkout default-base &&
197 git reset --hard HEAD^ &&
198 git checkout default &&
199 git rebase --apply &&
200 git rev-parse --verify default-base >expect &&
201 git rev-parse default~1 >actual &&
202 test_cmp expect actual
205 test_expect_success 'cherry-picked commits and fork-point work together' '
206 git checkout default-base &&
207 echo Amended >A &&
208 git commit -a --no-edit --amend &&
209 test_commit B B &&
210 test_commit new_B B "New B" &&
211 test_commit C C &&
212 git checkout default &&
213 git reset --hard default-base@{4} &&
214 test_commit D D &&
215 git cherry-pick -2 default-base^ &&
216 test_commit final_B B "Final B" &&
217 git rebase &&
218 echo Amended >expect &&
219 test_cmp expect A &&
220 echo "Final B" >expect &&
221 test_cmp expect B &&
222 echo C >expect &&
223 test_cmp expect C &&
224 echo D >expect &&
225 test_cmp expect D
228 test_expect_success 'rebase --apply -q is quiet' '
229 git checkout -b quiet topic &&
230 git rebase --apply -q main >output.out 2>&1 &&
231 test_must_be_empty output.out
234 test_expect_success 'rebase --merge -q is quiet' '
235 git checkout -B quiet topic &&
236 git rebase --merge -q main >output.out 2>&1 &&
237 test_must_be_empty output.out
240 test_expect_success 'rebase --exec -q is quiet' '
241 git checkout -B quiet topic &&
242 git rebase --exec true -q main >output.out 2>&1 &&
243 test_must_be_empty output.out
246 test_expect_success 'Rebase a commit that sprinkles CRs in' '
248 echo "One" &&
249 echo "TwoQ" &&
250 echo "Three" &&
251 echo "FQur" &&
252 echo "Five"
253 ) | q_to_cr >CR &&
254 git add CR &&
255 test_tick &&
256 git commit -a -m "A file with a line with CR" &&
257 git tag file-with-cr &&
258 git checkout HEAD^0 &&
259 git rebase --onto HEAD^^ HEAD^ &&
260 git diff --exit-code file-with-cr:CR HEAD:CR
263 test_expect_success 'rebase can copy notes' '
264 git config notes.rewrite.rebase true &&
265 git config notes.rewriteRef "refs/notes/*" &&
266 test_commit n1 &&
267 test_commit n2 &&
268 test_commit n3 &&
269 git notes add -m"a note" n3 &&
270 git rebase --onto n1 n2 &&
271 test "a note" = "$(git notes show HEAD)"
274 test_expect_success 'rebase -m can copy notes' '
275 git reset --hard n3 &&
276 git rebase -m --onto n1 n2 &&
277 test "a note" = "$(git notes show HEAD)"
280 test_expect_success 'rebase commit with an ancient timestamp' '
281 git reset --hard &&
283 >old.one && git add old.one && test_tick &&
284 git commit --date="@12345 +0400" -m "Old one" &&
285 >old.two && git add old.two && test_tick &&
286 git commit --date="@23456 +0500" -m "Old two" &&
287 >old.three && git add old.three && test_tick &&
288 git commit --date="@34567 +0600" -m "Old three" &&
290 git cat-file commit HEAD^^ >actual &&
291 grep "author .* 12345 +0400$" actual &&
292 git cat-file commit HEAD^ >actual &&
293 grep "author .* 23456 +0500$" actual &&
294 git cat-file commit HEAD >actual &&
295 grep "author .* 34567 +0600$" actual &&
297 git rebase --onto HEAD^^ HEAD^ &&
299 git cat-file commit HEAD >actual &&
300 grep "author .* 34567 +0600$" actual
303 test_expect_success 'rebase with "From " line in commit message' '
304 git checkout -b preserve-from main~1 &&
305 cat >From_.msg <<EOF &&
306 Somebody embedded an mbox in a commit message
308 This is from so-and-so:
310 From a@b Mon Sep 17 00:00:00 2001
311 From: John Doe <nobody@example.com>
312 Date: Sat, 11 Nov 2017 00:00:00 +0000
313 Subject: not this message
315 something
317 >From_ &&
318 git add From_ &&
319 git commit -F From_.msg &&
320 git rebase main &&
321 git log -1 --pretty=format:%B >out &&
322 test_cmp From_.msg out
325 test_expect_success 'rebase --apply and --show-current-patch' '
326 test_create_repo conflict-apply &&
328 cd conflict-apply &&
329 test_commit init &&
330 echo one >>init.t &&
331 git commit -a -m one &&
332 echo two >>init.t &&
333 git commit -a -m two &&
334 git tag two &&
335 test_must_fail git rebase --apply -f --onto init HEAD^ &&
336 GIT_TRACE=1 git rebase --show-current-patch >/dev/null 2>stderr &&
337 grep "show.*$(git rev-parse two)" stderr
341 test_expect_success 'rebase --apply and .gitattributes' '
342 test_create_repo attributes &&
344 cd attributes &&
345 test_commit init &&
346 git config filter.test.clean "sed -e '\''s/smudged/clean/g'\''" &&
347 git config filter.test.smudge "sed -e '\''s/clean/smudged/g'\''" &&
349 test_commit second &&
350 git checkout -b test HEAD^ &&
352 echo "*.txt filter=test" >.gitattributes &&
353 git add .gitattributes &&
354 test_commit third &&
356 echo "This text is smudged." >a.txt &&
357 git add a.txt &&
358 test_commit fourth &&
360 git checkout -b removal HEAD^ &&
361 git rm .gitattributes &&
362 git add -u &&
363 test_commit fifth &&
364 git cherry-pick test &&
366 git checkout test &&
367 git rebase main &&
368 grep "smudged" a.txt &&
370 git checkout removal &&
371 git reset --hard &&
372 git rebase main &&
373 grep "clean" a.txt
377 test_expect_success 'rebase--merge.sh and --show-current-patch' '
378 test_create_repo conflict-merge &&
380 cd conflict-merge &&
381 test_commit init &&
382 echo one >>init.t &&
383 git commit -a -m one &&
384 echo two >>init.t &&
385 git commit -a -m two &&
386 git tag two &&
387 test_must_fail git rebase --merge --onto init HEAD^ &&
388 git rebase --show-current-patch >actual.patch &&
389 GIT_TRACE=1 git rebase --show-current-patch >/dev/null 2>stderr &&
390 grep "show.*REBASE_HEAD" stderr &&
391 test "$(git rev-parse REBASE_HEAD)" = "$(git rev-parse two)"
395 test_expect_success 'switch to branch checked out here' '
396 git checkout main &&
397 git rebase main main
400 test_expect_success 'switch to branch checked out elsewhere fails' '
401 test_when_finished "
402 git worktree remove wt1 &&
403 git worktree remove wt2 &&
404 git branch -d shared
405 " &&
406 git worktree add wt1 -b shared &&
407 git worktree add wt2 -f shared &&
408 # we test in both worktrees to ensure that works
409 # as expected with "first" and "next" worktrees
410 test_must_fail git -C wt1 rebase shared shared &&
411 test_must_fail git -C wt2 rebase shared shared
414 test_expect_success 'switch to branch not checked out' '
415 git checkout main &&
416 git branch other &&
417 git rebase main other
420 test_expect_success 'switch to non-branch detaches HEAD' '
421 git checkout main &&
422 old_main=$(git rev-parse HEAD) &&
423 git rebase First Second^0 &&
424 test_cmp_rev HEAD Second &&
425 test_cmp_rev main $old_main &&
426 test_must_fail git symbolic-ref HEAD
429 test_expect_success 'refuse to switch to branch checked out elsewhere' '
430 git checkout main &&
431 git worktree add wt &&
432 test_must_fail git -C wt rebase main main 2>err &&
433 test_grep "already used by worktree at" err &&
434 test_must_fail git -C wt rebase --quit 2>err &&
435 test_grep "no rebase in progress" err
438 test_expect_success 'rebase when inside worktree subdirectory' '
439 git init main-wt &&
441 cd main-wt &&
442 git commit --allow-empty -m "initial" &&
443 mkdir -p foo/bar &&
444 test_commit foo/bar/baz &&
445 mkdir -p a/b &&
446 test_commit a/b/c &&
447 # create another branch for our other worktree
448 git branch other &&
449 git worktree add ../other-wt other &&
450 cd ../other-wt &&
451 # create and cd into a subdirectory
452 mkdir -p random/dir &&
453 cd random/dir &&
454 # now do the rebase
455 git rebase --onto HEAD^^ HEAD^ # drops the HEAD^ commit
459 test_done