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
11 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
=main
12 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
16 GIT_AUTHOR_NAME
=author@name
17 GIT_AUTHOR_EMAIL
=bogus@email@address
18 export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL
20 test_expect_success
'prepare repository with topic branches' '
21 test_commit "Add A." A First First &&
22 git checkout -b force-3way &&
24 git update-index --add Y &&
25 git commit -m "Add Y." &&
26 git checkout -b filemove &&
27 git reset --soft main &&
30 git commit -m "Move A." &&
31 git checkout -b my-topic-branch main &&
32 test_commit "Add B." B Second Second &&
33 git checkout -f main &&
36 git commit -m "Modify A." &&
37 git checkout -b side my-topic-branch &&
40 git commit -m "Add C" &&
41 git checkout -f my-topic-branch &&
45 test_expect_success
'rebase on dirty worktree' '
47 test_must_fail git rebase main
50 test_expect_success
'rebase on dirty cache' '
52 test_must_fail git rebase main
55 test_expect_success
'rebase against main' '
56 git reset --hard HEAD &&
60 test_expect_success
'rebase sets ORIG_HEAD to pre-rebase state' '
61 git checkout -b orig-head topic &&
62 pre="$(git rev-parse --verify HEAD)" &&
64 test_cmp_rev "$pre" ORIG_HEAD &&
65 test_cmp_rev ! "$pre" HEAD
68 test_expect_success
'rebase, with <onto> and <upstream> specified as :/quuxery' '
69 test_when_finished "git branch -D torebase" &&
70 git checkout -b torebase my-topic-branch^ &&
71 upstream=$(git rev-parse ":/Add B") &&
72 onto=$(git rev-parse ":/Add A") &&
73 git rebase --onto $onto $upstream &&
74 git reset --hard my-topic-branch^ &&
75 git rebase --onto ":/Add A" ":/Add B" &&
76 git checkout my-topic-branch
79 test_expect_success
'the rebase operation should not have destroyed author information' '
80 ! (git log | grep "Author:" | grep "<>")
83 test_expect_success
'the rebase operation should not have destroyed author information (2)' "
85 grep 'Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>'
88 test_expect_success
'HEAD was detached during rebase' '
89 test $(git rev-parse HEAD@{1}) != $(git rev-parse my-topic-branch@{1})
92 test_expect_success
'rebase from ambiguous branch name' '
93 git checkout -b topic side &&
97 test_expect_success
'rebase off of the previous branch using "-"' '
100 git rebase @{-1} >expect.messages &&
101 git merge-base main HEAD >expect.forkpoint &&
104 git checkout HEAD^ &&
105 git rebase - >actual.messages &&
106 git merge-base main HEAD >actual.forkpoint &&
108 test_cmp expect.forkpoint actual.forkpoint &&
109 # the next one is dubious---we may want to say "-",
110 # instead of @{-1}, in the message
111 test_cmp expect.messages actual.messages
114 test_expect_success
'rebase a single mode change' '
116 git branch -D topic &&
120 git commit -m prepare &&
121 git checkout -b modechange HEAD^ &&
126 git commit -m modechange &&
127 GIT_TRACE=1 git rebase main
130 test_expect_success
'rebase is not broken by diff.renames' '
131 test_config diff.renames copies &&
132 git checkout filemove &&
133 GIT_TRACE=1 git rebase force-3way
136 test_expect_success
'setup: recover' '
137 test_might_fail git rebase --abort &&
139 git checkout modechange
142 test_expect_success
'Show verbose error when HEAD could not be detached' '
144 test_when_finished "rm -f B" &&
145 test_must_fail git rebase topic 2>output.err >output.out &&
146 test_grep "The following untracked working tree files would be overwritten by checkout:" output.err &&
147 test_grep B output.err
150 test_expect_success
'fail when upstream arg is missing and not on branch' '
151 git checkout topic &&
152 test_must_fail git rebase
155 test_expect_success
'fail when upstream arg is missing and not configured' '
156 git checkout -b no-config topic &&
157 test_must_fail git rebase
160 test_expect_success
'rebase works with format.useAutoBase' '
161 test_config format.useAutoBase true &&
162 git checkout topic &&
166 test_expect_success
'default to common base in @{upstream}s reflog if no upstream arg (--merge)' '
167 git checkout -b default-base main &&
168 git checkout -b default topic &&
169 git config branch.default.remote . &&
170 git config branch.default.merge refs/heads/default-base &&
171 git rebase --merge &&
172 git rev-parse --verify default-base >expect &&
173 git rev-parse default~1 >actual &&
174 test_cmp expect actual &&
175 git checkout default-base &&
176 git reset --hard HEAD^ &&
177 git checkout default &&
178 git rebase --merge &&
179 git rev-parse --verify default-base >expect &&
180 git rev-parse default~1 >actual &&
181 test_cmp expect actual
184 test_expect_success
'default to common base in @{upstream}s reflog if no upstream arg (--apply)' '
185 git checkout -B default-base main &&
186 git checkout -B default topic &&
187 git config branch.default.remote . &&
188 git config branch.default.merge refs/heads/default-base &&
189 git rebase --apply &&
190 git rev-parse --verify default-base >expect &&
191 git rev-parse default~1 >actual &&
192 test_cmp expect actual &&
193 git checkout default-base &&
194 git reset --hard HEAD^ &&
195 git checkout default &&
196 git rebase --apply &&
197 git rev-parse --verify default-base >expect &&
198 git rev-parse default~1 >actual &&
199 test_cmp expect actual
202 test_expect_success
'cherry-picked commits and fork-point work together' '
203 git checkout default-base &&
205 git commit -a --no-edit --amend &&
207 test_commit new_B B "New B" &&
209 git checkout default &&
210 git reset --hard default-base@{4} &&
212 git cherry-pick -2 default-base^ &&
213 test_commit final_B B "Final B" &&
215 echo Amended >expect &&
217 echo "Final B" >expect &&
225 test_expect_success
'rebase --apply -q is quiet' '
226 git checkout -b quiet topic &&
227 git rebase --apply -q main >output.out 2>&1 &&
228 test_must_be_empty output.out
231 test_expect_success
'rebase --merge -q is quiet' '
232 git checkout -B quiet topic &&
233 git rebase --merge -q main >output.out 2>&1 &&
234 test_must_be_empty output.out
237 test_expect_success
'Rebase a commit that sprinkles CRs in' '
247 git commit -a -m "A file with a line with CR" &&
248 git tag file-with-cr &&
249 git checkout HEAD^0 &&
250 git rebase --onto HEAD^^ HEAD^ &&
251 git diff --exit-code file-with-cr:CR HEAD:CR
254 test_expect_success
'rebase can copy notes' '
255 git config notes.rewrite.rebase true &&
256 git config notes.rewriteRef "refs/notes/*" &&
260 git notes add -m"a note" n3 &&
261 git rebase --onto n1 n2 &&
262 test "a note" = "$(git notes show HEAD)"
265 test_expect_success
'rebase -m can copy notes' '
266 git reset --hard n3 &&
267 git rebase -m --onto n1 n2 &&
268 test "a note" = "$(git notes show HEAD)"
271 test_expect_success
'rebase commit with an ancient timestamp' '
274 >old.one && git add old.one && test_tick &&
275 git commit --date="@12345 +0400" -m "Old one" &&
276 >old.two && git add old.two && test_tick &&
277 git commit --date="@23456 +0500" -m "Old two" &&
278 >old.three && git add old.three && test_tick &&
279 git commit --date="@34567 +0600" -m "Old three" &&
281 git cat-file commit HEAD^^ >actual &&
282 grep "author .* 12345 +0400$" actual &&
283 git cat-file commit HEAD^ >actual &&
284 grep "author .* 23456 +0500$" actual &&
285 git cat-file commit HEAD >actual &&
286 grep "author .* 34567 +0600$" actual &&
288 git rebase --onto HEAD^^ HEAD^ &&
290 git cat-file commit HEAD >actual &&
291 grep "author .* 34567 +0600$" actual
294 test_expect_success
'rebase with "From " line in commit message' '
295 git checkout -b preserve-from main~1 &&
296 cat >From_.msg <<EOF &&
297 Somebody embedded an mbox in a commit message
299 This is from so-and-so:
301 From a@b Mon Sep 17 00:00:00 2001
302 From: John Doe <nobody@example.com>
303 Date: Sat, 11 Nov 2017 00:00:00 +0000
304 Subject: not this message
310 git commit -F From_.msg &&
312 git log -1 --pretty=format:%B >out &&
313 test_cmp From_.msg out
316 test_expect_success
'rebase --apply and --show-current-patch' '
317 test_create_repo conflict-apply &&
322 git commit -a -m one &&
324 git commit -a -m two &&
326 test_must_fail git rebase --apply -f --onto init HEAD^ &&
327 GIT_TRACE=1 git rebase --show-current-patch >/dev/null 2>stderr &&
328 grep "show.*$(git rev-parse two)" stderr
332 test_expect_success
'rebase --apply and .gitattributes' '
333 test_create_repo attributes &&
337 git config filter.test.clean "sed -e '\''s/smudged/clean/g'\''" &&
338 git config filter.test.smudge "sed -e '\''s/clean/smudged/g'\''" &&
340 test_commit second &&
341 git checkout -b test HEAD^ &&
343 echo "*.txt filter=test" >.gitattributes &&
344 git add .gitattributes &&
347 echo "This text is smudged." >a.txt &&
349 test_commit fourth &&
351 git checkout -b removal HEAD^ &&
352 git rm .gitattributes &&
355 git cherry-pick test &&
359 grep "smudged" a.txt &&
361 git checkout removal &&
368 test_expect_success
'rebase--merge.sh and --show-current-patch' '
369 test_create_repo conflict-merge &&
374 git commit -a -m one &&
376 git commit -a -m two &&
378 test_must_fail git rebase --merge --onto init HEAD^ &&
379 git rebase --show-current-patch >actual.patch &&
380 GIT_TRACE=1 git rebase --show-current-patch >/dev/null 2>stderr &&
381 grep "show.*REBASE_HEAD" stderr &&
382 test "$(git rev-parse REBASE_HEAD)" = "$(git rev-parse two)"
386 test_expect_success
'switch to branch checked out here' '
391 test_expect_success
'switch to branch checked out elsewhere fails' '
393 git worktree remove wt1 &&
394 git worktree remove wt2 &&
397 git worktree add wt1 -b shared &&
398 git worktree add wt2 -f shared &&
399 # we test in both worktrees to ensure that works
400 # as expected with "first" and "next" worktrees
401 test_must_fail git -C wt1 rebase shared shared &&
402 test_must_fail git -C wt2 rebase shared shared
405 test_expect_success
'switch to branch not checked out' '
408 git rebase main other
411 test_expect_success
'switch to non-branch detaches HEAD' '
413 old_main=$(git rev-parse HEAD) &&
414 git rebase First Second^0 &&
415 test_cmp_rev HEAD Second &&
416 test_cmp_rev main $old_main &&
417 test_must_fail git symbolic-ref HEAD
420 test_expect_success
'refuse to switch to branch checked out elsewhere' '
422 git worktree add wt &&
423 test_must_fail git -C wt rebase main main 2>err &&
424 test_grep "already used by worktree at" err
427 test_expect_success
'rebase when inside worktree subdirectory' '
431 git commit --allow-empty -m "initial" &&
433 test_commit foo/bar/baz &&
436 # create another branch for our other worktree
438 git worktree add ../other-wt other &&
440 # create and cd into a subdirectory
441 mkdir -p random/dir &&
444 git rebase --onto HEAD^^ HEAD^ # drops the HEAD^ commit