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 git config core.logAllRefUpdates true &&
23 git update-index --add A &&
24 git commit -m "Add A." &&
25 git checkout -b force-3way &&
27 git update-index --add Y &&
28 git commit -m "Add Y." &&
29 git checkout -b filemove &&
30 git reset --soft main &&
33 git commit -m "Move A." &&
34 git checkout -b my-topic-branch main &&
36 git update-index --add B &&
37 git commit -m "Add B." &&
38 git checkout -f main &&
41 git commit -m "Modify A." &&
42 git checkout -b side my-topic-branch &&
45 git commit -m "Add C" &&
46 git checkout -f my-topic-branch &&
50 test_expect_success
'rebase on dirty worktree' '
52 test_must_fail git rebase main
55 test_expect_success
'rebase on dirty cache' '
57 test_must_fail git rebase main
60 test_expect_success
'rebase against main' '
61 git reset --hard HEAD &&
65 test_expect_success
'rebase sets ORIG_HEAD to pre-rebase state' '
66 git checkout -b orig-head topic &&
67 pre="$(git rev-parse --verify HEAD)" &&
69 test_cmp_rev "$pre" ORIG_HEAD &&
70 test_cmp_rev ! "$pre" HEAD
73 test_expect_success
'rebase, with <onto> and <upstream> specified as :/quuxery' '
74 test_when_finished "git branch -D torebase" &&
75 git checkout -b torebase my-topic-branch^ &&
76 upstream=$(git rev-parse ":/Add B") &&
77 onto=$(git rev-parse ":/Add A") &&
78 git rebase --onto $onto $upstream &&
79 git reset --hard my-topic-branch^ &&
80 git rebase --onto ":/Add A" ":/Add B" &&
81 git checkout my-topic-branch
84 test_expect_success
'the rebase operation should not have destroyed author information' '
85 ! (git log | grep "Author:" | grep "<>")
88 test_expect_success
'the rebase operation should not have destroyed author information (2)' "
90 grep 'Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>'
93 test_expect_success
'HEAD was detached during rebase' '
94 test $(git rev-parse HEAD@{1}) != $(git rev-parse my-topic-branch@{1})
97 test_expect_success
'rebase from ambiguous branch name' '
98 git checkout -b topic side &&
102 test_expect_success
'rebase off of the previous branch using "-"' '
104 git checkout HEAD^ &&
105 git rebase @{-1} >expect.messages &&
106 git merge-base main HEAD >expect.forkpoint &&
109 git checkout HEAD^ &&
110 git rebase - >actual.messages &&
111 git merge-base main HEAD >actual.forkpoint &&
113 test_cmp expect.forkpoint actual.forkpoint &&
114 # the next one is dubious---we may want to say "-",
115 # instead of @{-1}, in the message
116 test_cmp expect.messages actual.messages
119 test_expect_success
'rebase a single mode change' '
121 git branch -D topic &&
125 git commit -m prepare &&
126 git checkout -b modechange HEAD^ &&
131 git commit -m modechange &&
132 GIT_TRACE=1 git rebase main
135 test_expect_success
'rebase is not broken by diff.renames' '
136 test_config diff.renames copies &&
137 git checkout filemove &&
138 GIT_TRACE=1 git rebase force-3way
141 test_expect_success
'setup: recover' '
142 test_might_fail git rebase --abort &&
144 git checkout modechange
147 test_expect_success
'Show verbose error when HEAD could not be detached' '
149 test_when_finished "rm -f B" &&
150 test_must_fail git rebase topic 2>output.err >output.out &&
151 test_i18ngrep "The following untracked working tree files would be overwritten by checkout:" output.err &&
152 test_i18ngrep B output.err
155 test_expect_success
'fail when upstream arg is missing and not on branch' '
156 git checkout topic &&
157 test_must_fail git rebase
160 test_expect_success
'fail when upstream arg is missing and not configured' '
161 git checkout -b no-config topic &&
162 test_must_fail git rebase
165 test_expect_success
'rebase works with format.useAutoBase' '
166 test_config format.useAutoBase true &&
167 git checkout topic &&
171 test_expect_success
'default to common base in @{upstream}s reflog if no upstream arg (--merge)' '
172 git checkout -b default-base main &&
173 git checkout -b default topic &&
174 git config branch.default.remote . &&
175 git config branch.default.merge refs/heads/default-base &&
176 git rebase --merge &&
177 git rev-parse --verify default-base >expect &&
178 git rev-parse default~1 >actual &&
179 test_cmp expect actual &&
180 git checkout default-base &&
181 git reset --hard HEAD^ &&
182 git checkout default &&
183 git rebase --merge &&
184 git rev-parse --verify default-base >expect &&
185 git rev-parse default~1 >actual &&
186 test_cmp expect actual
189 test_expect_success
'default to common base in @{upstream}s reflog if no upstream arg (--apply)' '
190 git checkout -B default-base main &&
191 git checkout -B default topic &&
192 git config branch.default.remote . &&
193 git config branch.default.merge refs/heads/default-base &&
194 git rebase --apply &&
195 git rev-parse --verify default-base >expect &&
196 git rev-parse default~1 >actual &&
197 test_cmp expect actual &&
198 git checkout default-base &&
199 git reset --hard HEAD^ &&
200 git checkout default &&
201 git rebase --apply &&
202 git rev-parse --verify default-base >expect &&
203 git rev-parse default~1 >actual &&
204 test_cmp expect actual
207 test_expect_success
'cherry-picked commits and fork-point work together' '
208 git checkout default-base &&
210 git commit -a --no-edit --amend &&
212 test_commit new_B B "New B" &&
214 git checkout default &&
215 git reset --hard default-base@{4} &&
217 git cherry-pick -2 default-base^ &&
218 test_commit final_B B "Final B" &&
220 echo Amended >expect &&
222 echo "Final B" >expect &&
230 test_expect_success
'rebase --apply -q is quiet' '
231 git checkout -b quiet topic &&
232 git rebase --apply -q main >output.out 2>&1 &&
233 test_must_be_empty output.out
236 test_expect_success
'rebase --merge -q is quiet' '
237 git checkout -B quiet topic &&
238 git rebase --merge -q main >output.out 2>&1 &&
239 test_must_be_empty output.out
242 test_expect_success
'Rebase a commit that sprinkles CRs in' '
252 git commit -a -m "A file with a line with CR" &&
253 git tag file-with-cr &&
254 git checkout HEAD^0 &&
255 git rebase --onto HEAD^^ HEAD^ &&
256 git diff --exit-code file-with-cr:CR HEAD:CR
259 test_expect_success
'rebase can copy notes' '
260 git config notes.rewrite.rebase true &&
261 git config notes.rewriteRef "refs/notes/*" &&
265 git notes add -m"a note" n3 &&
266 git rebase --onto n1 n2 &&
267 test "a note" = "$(git notes show HEAD)"
270 test_expect_success
'rebase -m can copy notes' '
271 git reset --hard n3 &&
272 git rebase -m --onto n1 n2 &&
273 test "a note" = "$(git notes show HEAD)"
276 test_expect_success
'rebase commit with an ancient timestamp' '
279 >old.one && git add old.one && test_tick &&
280 git commit --date="@12345 +0400" -m "Old one" &&
281 >old.two && git add old.two && test_tick &&
282 git commit --date="@23456 +0500" -m "Old two" &&
283 >old.three && git add old.three && test_tick &&
284 git commit --date="@34567 +0600" -m "Old three" &&
286 git cat-file commit HEAD^^ >actual &&
287 grep "author .* 12345 +0400$" actual &&
288 git cat-file commit HEAD^ >actual &&
289 grep "author .* 23456 +0500$" actual &&
290 git cat-file commit HEAD >actual &&
291 grep "author .* 34567 +0600$" actual &&
293 git rebase --onto HEAD^^ HEAD^ &&
295 git cat-file commit HEAD >actual &&
296 grep "author .* 34567 +0600$" actual
299 test_expect_success
'rebase with "From " line in commit message' '
300 git checkout -b preserve-from main~1 &&
301 cat >From_.msg <<EOF &&
302 Somebody embedded an mbox in a commit message
304 This is from so-and-so:
306 From a@b Mon Sep 17 00:00:00 2001
307 From: John Doe <nobody@example.com>
308 Date: Sat, 11 Nov 2017 00:00:00 +0000
309 Subject: not this message
315 git commit -F From_.msg &&
317 git log -1 --pretty=format:%B >out &&
318 test_cmp From_.msg out
321 test_expect_success
'rebase --apply and --show-current-patch' '
322 test_create_repo conflict-apply &&
327 git commit -a -m one &&
329 git commit -a -m two &&
331 test_must_fail git rebase --apply -f --onto init HEAD^ &&
332 GIT_TRACE=1 git rebase --show-current-patch >/dev/null 2>stderr &&
333 grep "show.*$(git rev-parse two)" stderr
337 test_expect_success
'rebase --apply and .gitattributes' '
338 test_create_repo attributes &&
342 git config filter.test.clean "sed -e '\''s/smudged/clean/g'\''" &&
343 git config filter.test.smudge "sed -e '\''s/clean/smudged/g'\''" &&
345 test_commit second &&
346 git checkout -b test HEAD^ &&
348 echo "*.txt filter=test" >.gitattributes &&
349 git add .gitattributes &&
352 echo "This text is smudged." >a.txt &&
354 test_commit fourth &&
356 git checkout -b removal HEAD^ &&
357 git rm .gitattributes &&
360 git cherry-pick test &&
364 grep "smudged" a.txt &&
366 git checkout removal &&
373 test_expect_success
'rebase--merge.sh and --show-current-patch' '
374 test_create_repo conflict-merge &&
379 git commit -a -m one &&
381 git commit -a -m two &&
383 test_must_fail git rebase --merge --onto init HEAD^ &&
384 git rebase --show-current-patch >actual.patch &&
385 GIT_TRACE=1 git rebase --show-current-patch >/dev/null 2>stderr &&
386 grep "show.*REBASE_HEAD" stderr &&
387 test "$(git rev-parse REBASE_HEAD)" = "$(git rev-parse two)"
391 test_expect_success
'switch to branch checked out here' '
396 test_expect_success
'switch to branch not checked out' '
399 git rebase main other
402 test_expect_success
'refuse to switch to branch checked out elsewhere' '
404 git worktree add wt &&
405 test_must_fail git -C wt rebase main main 2>err &&
406 test_i18ngrep "already checked out" err
409 test_expect_success MINGW
,SYMLINKS_WINDOWS
'rebase when .git/logs is a symlink' '
411 mv .git/logs actual_logs &&
412 cmd //c "mklink /D .git\logs ..\actual_logs" &&
413 git rebase -f HEAD^ &&
416 mv actual_logs .git/logs