Git fork
1#!/bin/sh
2#
3# Copyright (c) 2005 Amos Waterland
4#
5
6test_description='git rebase assorted tests
7
8This test runs git rebase and checks that the author information is not lost
9among other things.
10'
11GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
12export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
13
14. ./test-lib.sh
15
16GIT_AUTHOR_NAME=author@name
17GIT_AUTHOR_EMAIL=bogus@email@address
18export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL
19
20test_expect_success 'prepare repository with topic branches' '
21 test_commit "Add A." A First First &&
22 git checkout -b force-3way &&
23 echo Dummy >Y &&
24 git update-index --add Y &&
25 git commit -m "Add Y." &&
26 git checkout -b filemove &&
27 git reset --soft main &&
28 mkdir D &&
29 git mv A D/A &&
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 &&
34 echo Third >>A &&
35 git update-index A &&
36 git commit -m "Modify A." &&
37 git checkout -b side my-topic-branch &&
38 echo Side >>C &&
39 git add C &&
40 git commit -m "Add C" &&
41 git checkout -f my-topic-branch &&
42 git tag topic
43'
44
45test_expect_success 'rebase on dirty worktree' '
46 echo dirty >>A &&
47 test_must_fail git rebase main
48'
49
50test_expect_success 'rebase on dirty cache' '
51 git add A &&
52 test_must_fail git rebase main
53'
54
55test_expect_success 'rebase against main' '
56 git reset --hard HEAD &&
57 git rebase main
58'
59
60test_expect_success 'rebase sets ORIG_HEAD to pre-rebase state' '
61 git checkout -b orig-head topic &&
62 pre="$(git rev-parse --verify HEAD)" &&
63 git rebase main &&
64 test_cmp_rev "$pre" ORIG_HEAD &&
65 test_cmp_rev ! "$pre" HEAD
66'
67
68test_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
77'
78
79test_expect_success 'the rebase operation should not have destroyed author information' '
80 ! (git log | grep "Author:" | grep "<>")
81'
82
83test_expect_success 'the rebase operation should not have destroyed author information (2)' "
84 git log -1 |
85 grep 'Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>'
86"
87
88test_expect_success 'HEAD was detached during rebase' '
89 test $(git rev-parse HEAD@{1}) != $(git rev-parse my-topic-branch@{1})
90'
91
92test_expect_success 'rebase from ambiguous branch name' '
93 git checkout -b topic side &&
94 git rebase main
95'
96
97test_expect_success 'rebase off of the previous branch using "-"' '
98 git checkout main &&
99 git checkout HEAD^ &&
100 git rebase @{-1} >expect.messages &&
101 git merge-base main HEAD >expect.forkpoint &&
102
103 git checkout main &&
104 git checkout HEAD^ &&
105 git rebase - >actual.messages &&
106 git merge-base main HEAD >actual.forkpoint &&
107
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
112'
113
114test_expect_success 'rebase a single mode change' '
115 git checkout main &&
116 git branch -D topic &&
117 echo 1 >X &&
118 git add X &&
119 test_tick &&
120 git commit -m prepare &&
121 git checkout -b modechange HEAD^ &&
122 echo 1 >X &&
123 git add X &&
124 test_chmod +x A &&
125 test_tick &&
126 git commit -m modechange &&
127 GIT_TRACE=1 git rebase main
128'
129
130test_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
134'
135
136test_expect_success 'setup: recover' '
137 test_might_fail git rebase --abort &&
138 git reset --hard &&
139 git checkout modechange
140'
141
142test_expect_success 'Show verbose error when HEAD could not be detached' '
143 >B &&
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 &&
148 test_must_fail git rebase --quit 2>err &&
149 test_grep "no rebase in progress" err
150'
151
152test_expect_success 'fail when upstream arg is missing and not on branch' '
153 git checkout topic &&
154 test_must_fail git rebase
155'
156
157test_expect_success 'fail when upstream arg is missing and not configured' '
158 git checkout -b no-config topic &&
159 test_must_fail git rebase
160'
161
162test_expect_success 'rebase works with format.useAutoBase' '
163 test_config format.useAutoBase true &&
164 git checkout topic &&
165 git rebase main
166'
167
168test_expect_success 'default to common base in @{upstream}s reflog if no upstream arg (--merge)' '
169 git checkout -b default-base main &&
170 git checkout -b default topic &&
171 git config branch.default.remote . &&
172 git config branch.default.merge refs/heads/default-base &&
173 git rebase --merge &&
174 git rev-parse --verify default-base >expect &&
175 git rev-parse default~1 >actual &&
176 test_cmp expect actual &&
177 git checkout default-base &&
178 git reset --hard HEAD^ &&
179 git checkout default &&
180 git rebase --merge &&
181 git rev-parse --verify default-base >expect &&
182 git rev-parse default~1 >actual &&
183 test_cmp expect actual
184'
185
186test_expect_success 'default to common base in @{upstream}s reflog if no upstream arg (--apply)' '
187 git checkout -B default-base main &&
188 git checkout -B default topic &&
189 git config branch.default.remote . &&
190 git config branch.default.merge refs/heads/default-base &&
191 git rebase --apply &&
192 git rev-parse --verify default-base >expect &&
193 git rev-parse default~1 >actual &&
194 test_cmp expect actual &&
195 git checkout default-base &&
196 git reset --hard HEAD^ &&
197 git checkout default &&
198 git rebase --apply &&
199 git rev-parse --verify default-base >expect &&
200 git rev-parse default~1 >actual &&
201 test_cmp expect actual
202'
203
204test_expect_success 'cherry-picked commits and fork-point work together' '
205 git checkout default-base &&
206 echo Amended >A &&
207 git commit -a --no-edit --amend &&
208 test_commit B B &&
209 test_commit new_B B "New B" &&
210 test_commit C C &&
211 git checkout default &&
212 git reset --hard default-base@{4} &&
213 test_commit D D &&
214 git cherry-pick -2 default-base^ &&
215 test_commit final_B B "Final B" &&
216 git rebase &&
217 echo Amended >expect &&
218 test_cmp expect A &&
219 echo "Final B" >expect &&
220 test_cmp expect B &&
221 echo C >expect &&
222 test_cmp expect C &&
223 echo D >expect &&
224 test_cmp expect D
225'
226
227test_expect_success 'rebase --apply -q is quiet' '
228 git checkout -b quiet topic &&
229 git rebase --apply -q main >output.out 2>&1 &&
230 test_must_be_empty output.out
231'
232
233test_expect_success 'rebase --merge -q is quiet' '
234 git checkout -B quiet topic &&
235 git rebase --merge -q main >output.out 2>&1 &&
236 test_must_be_empty output.out
237'
238
239test_expect_success 'rebase --exec -q is quiet' '
240 git checkout -B quiet topic &&
241 git rebase --exec true -q main >output.out 2>&1 &&
242 test_must_be_empty output.out
243'
244
245test_expect_success 'Rebase a commit that sprinkles CRs in' '
246 (
247 echo "One" &&
248 echo "TwoQ" &&
249 echo "Three" &&
250 echo "FQur" &&
251 echo "Five"
252 ) | q_to_cr >CR &&
253 git add CR &&
254 test_tick &&
255 git commit -a -m "A file with a line with CR" &&
256 git tag file-with-cr &&
257 git checkout HEAD^0 &&
258 git rebase --onto HEAD^^ HEAD^ &&
259 git diff --exit-code file-with-cr:CR HEAD:CR
260'
261
262test_expect_success 'rebase can copy notes' '
263 git config notes.rewrite.rebase true &&
264 git config notes.rewriteRef "refs/notes/*" &&
265 test_commit n1 &&
266 test_commit n2 &&
267 test_commit n3 &&
268 git notes add -m"a note" n3 &&
269 git rebase --onto n1 n2 &&
270 test "a note" = "$(git notes show HEAD)"
271'
272
273test_expect_success 'rebase -m can copy notes' '
274 git reset --hard n3 &&
275 git rebase -m --onto n1 n2 &&
276 test "a note" = "$(git notes show HEAD)"
277'
278
279test_expect_success 'rebase commit with an ancient timestamp' '
280 git reset --hard &&
281
282 >old.one && git add old.one && test_tick &&
283 git commit --date="@12345 +0400" -m "Old one" &&
284 >old.two && git add old.two && test_tick &&
285 git commit --date="@23456 +0500" -m "Old two" &&
286 >old.three && git add old.three && test_tick &&
287 git commit --date="@34567 +0600" -m "Old three" &&
288
289 git cat-file commit HEAD^^ >actual &&
290 grep "author .* 12345 +0400$" actual &&
291 git cat-file commit HEAD^ >actual &&
292 grep "author .* 23456 +0500$" actual &&
293 git cat-file commit HEAD >actual &&
294 grep "author .* 34567 +0600$" actual &&
295
296 git rebase --onto HEAD^^ HEAD^ &&
297
298 git cat-file commit HEAD >actual &&
299 grep "author .* 34567 +0600$" actual
300'
301
302test_expect_success 'rebase with "From " line in commit message' '
303 git checkout -b preserve-from main~1 &&
304 cat >From_.msg <<EOF &&
305Somebody embedded an mbox in a commit message
306
307This is from so-and-so:
308
309From a@b Mon Sep 17 00:00:00 2001
310From: John Doe <nobody@example.com>
311Date: Sat, 11 Nov 2017 00:00:00 +0000
312Subject: not this message
313
314something
315EOF
316 >From_ &&
317 git add From_ &&
318 git commit -F From_.msg &&
319 git rebase main &&
320 git log -1 --pretty=format:%B >out &&
321 test_cmp From_.msg out
322'
323
324test_expect_success 'rebase --apply and --show-current-patch' '
325 test_create_repo conflict-apply &&
326 (
327 cd conflict-apply &&
328 test_commit init &&
329 echo one >>init.t &&
330 git commit -a -m one &&
331 echo two >>init.t &&
332 git commit -a -m two &&
333 git tag two &&
334 test_must_fail git rebase --apply -f --onto init HEAD^ &&
335 GIT_TRACE=1 git rebase --show-current-patch >/dev/null 2>stderr &&
336 grep "show.*$(git rev-parse two)" stderr
337 )
338'
339
340test_expect_success 'rebase --apply and .gitattributes' '
341 test_create_repo attributes &&
342 (
343 cd attributes &&
344 test_commit init &&
345 git config filter.test.clean "sed -e '\''s/smudged/clean/g'\''" &&
346 git config filter.test.smudge "sed -e '\''s/clean/smudged/g'\''" &&
347
348 test_commit second &&
349 git checkout -b test HEAD^ &&
350
351 echo "*.txt filter=test" >.gitattributes &&
352 git add .gitattributes &&
353 test_commit third &&
354
355 echo "This text is smudged." >a.txt &&
356 git add a.txt &&
357 test_commit fourth &&
358
359 git checkout -b removal HEAD^ &&
360 git rm .gitattributes &&
361 git add -u &&
362 test_commit fifth &&
363 git cherry-pick test &&
364
365 git checkout test &&
366 git rebase main &&
367 grep "smudged" a.txt &&
368
369 git checkout removal &&
370 git reset --hard &&
371 git rebase main &&
372 grep "clean" a.txt
373 )
374'
375
376test_expect_success 'rebase--merge.sh and --show-current-patch' '
377 test_create_repo conflict-merge &&
378 (
379 cd conflict-merge &&
380 test_commit init &&
381 echo one >>init.t &&
382 git commit -a -m one &&
383 echo two >>init.t &&
384 git commit -a -m two &&
385 git tag two &&
386 test_must_fail git rebase --merge --onto init HEAD^ &&
387 git rebase --show-current-patch >actual.patch &&
388 GIT_TRACE=1 git rebase --show-current-patch >/dev/null 2>stderr &&
389 grep "show.*REBASE_HEAD" stderr &&
390 test "$(git rev-parse REBASE_HEAD)" = "$(git rev-parse two)"
391 )
392'
393
394test_expect_success 'switch to branch checked out here' '
395 git checkout main &&
396 git rebase main main
397'
398
399test_expect_success 'switch to branch checked out elsewhere fails' '
400 test_when_finished "
401 git worktree remove wt1 &&
402 git worktree remove wt2 &&
403 git branch -d shared
404 " &&
405 git worktree add wt1 -b shared &&
406 git worktree add wt2 -f shared &&
407 # we test in both worktrees to ensure that works
408 # as expected with "first" and "next" worktrees
409 test_must_fail git -C wt1 rebase shared shared &&
410 test_must_fail git -C wt2 rebase shared shared
411'
412
413test_expect_success 'switch to branch not checked out' '
414 git checkout main &&
415 git branch other &&
416 git rebase main other
417'
418
419test_expect_success 'switch to non-branch detaches HEAD' '
420 git checkout main &&
421 old_main=$(git rev-parse HEAD) &&
422 git rebase First Second^0 &&
423 test_cmp_rev HEAD Second &&
424 test_cmp_rev main $old_main &&
425 test_must_fail git symbolic-ref HEAD
426'
427
428test_expect_success 'refuse to switch to branch checked out elsewhere' '
429 git checkout main &&
430 git worktree add wt &&
431 test_must_fail git -C wt rebase main main 2>err &&
432 test_grep "already used by worktree at" err &&
433 test_must_fail git -C wt rebase --quit 2>err &&
434 test_grep "no rebase in progress" err
435'
436
437test_expect_success 'rebase when inside worktree subdirectory' '
438 git init main-wt &&
439 (
440 cd main-wt &&
441 git commit --allow-empty -m "initial" &&
442 mkdir -p foo/bar &&
443 test_commit foo/bar/baz &&
444 mkdir -p a/b &&
445 test_commit a/b/c &&
446 # create another branch for our other worktree
447 git branch other &&
448 git worktree add ../other-wt other &&
449 cd ../other-wt &&
450 # create and cd into a subdirectory
451 mkdir -p random/dir &&
452 cd random/dir &&
453 # now do the rebase
454 git rebase --onto HEAD^^ HEAD^ # drops the HEAD^ commit
455 )
456'
457
458test_expect_success 'git rebase --update-ref with core.commentChar and branch on worktree' '
459 test_when_finished git branch -D base topic2 &&
460 test_when_finished git checkout main &&
461 test_when_finished git branch -D wt-topic &&
462 test_when_finished git worktree remove wt-topic &&
463 git checkout main &&
464 git checkout -b base &&
465 git checkout -b topic2 &&
466 test_commit msg2 &&
467 git worktree add wt-topic &&
468 git checkout base &&
469 test_commit msg3 &&
470 git checkout topic2 &&
471 GIT_SEQUENCE_EDITOR="cat >actual" git -c core.commentChar=% \
472 rebase -i --update-refs base &&
473 test_grep "% Ref refs/heads/wt-topic checked out at" actual &&
474 test_grep "% Ref refs/heads/topic2 checked out at" actual
475'
476
477test_done