3 # Copyright (c) 2013 Ramkumar Ramachandra
6 test_description
='git rebase --autostash tests'
7 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
=main
8 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
12 test_expect_success setup
'
13 echo hello-world >file0 &&
16 git commit -m "initial commit" &&
17 git checkout -b feature-branch &&
18 echo another-hello >file1 &&
19 echo goodbye >file2 &&
22 git commit -m "second commit" &&
23 echo final-goodbye >file3 &&
26 git commit -m "third commit" &&
27 git checkout -b unrelated-onto-branch main &&
28 echo unrelated >file4 &&
31 git commit -m "unrelated commit" &&
32 git checkout -b related-onto-branch main &&
33 echo conflicting-change >file2 &&
36 git commit -m "related commit" &&
37 remove_progress_re="$(printf "s/.*\\r//")"
40 create_expected_success_apply
() {
42 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
43 First, rewinding head to replay your work on top of it...
44 Applying: second commit
45 Applying: third commit
50 create_expected_success_merge
() {
51 q_to_cr
>expected
<<-EOF
52 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
54 Successfully rebased and updated refs/heads/rebased-feature-branch.
58 create_expected_failure_apply
() {
60 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
61 First, rewinding head to replay your work on top of it...
62 Applying: second commit
63 Applying: third commit
64 Applying autostash resulted in conflicts.
65 Your changes are safe in the stash.
66 You can run "git stash pop" or "git stash drop" at any time.
70 create_expected_failure_merge
() {
72 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
73 Applying autostash resulted in conflicts.
74 Your changes are safe in the stash.
75 You can run "git stash pop" or "git stash drop" at any time.
76 Successfully rebased and updated refs/heads/rebased-feature-branch.
84 test_expect_success
"rebase$type: dirty worktree, --no-autostash" '
85 test_config rebase.autostash true &&
87 git checkout -b rebased-feature-branch feature-branch &&
88 test_when_finished git branch -D rebased-feature-branch &&
89 test_when_finished git checkout feature-branch &&
91 test_must_fail git rebase$type --no-autostash unrelated-onto-branch
94 test_expect_success
"rebase$type: dirty worktree, non-conflicting rebase" '
95 test_config rebase.autostash true &&
97 git checkout -b rebased-feature-branch feature-branch &&
99 git rebase$type unrelated-onto-branch >actual 2>&1 &&
100 grep unrelated file4 &&
102 git checkout feature-branch
105 test_expect_success
"rebase$type --autostash: check output" '
106 test_when_finished git branch -D rebased-feature-branch &&
107 suffix=${type#\ --} && suffix=${suffix:-apply} &&
108 if test ${suffix} = "interactive"; then
111 create_expected_success_$suffix &&
112 sed "$remove_progress_re" <actual >actual2 &&
113 test_cmp expected actual2
116 test_expect_success
"rebase$type: dirty index, non-conflicting rebase" '
117 test_config rebase.autostash true &&
119 git checkout -b rebased-feature-branch feature-branch &&
120 test_when_finished git branch -D rebased-feature-branch &&
121 echo dirty >>file3 &&
123 git rebase$type unrelated-onto-branch &&
124 grep unrelated file4 &&
126 git checkout feature-branch
129 test_expect_success
"rebase$type: conflicting rebase" '
130 test_config rebase.autostash true &&
132 git checkout -b rebased-feature-branch feature-branch &&
133 test_when_finished git branch -D rebased-feature-branch &&
134 echo dirty >>file3 &&
135 test_must_fail git rebase$type related-onto-branch &&
136 test_path_is_file $dotest/autostash &&
137 test_path_is_missing file3 &&
140 git checkout feature-branch
143 test_expect_success
"rebase$type: --continue" '
144 test_config rebase.autostash true &&
146 git checkout -b rebased-feature-branch feature-branch &&
147 test_when_finished git branch -D rebased-feature-branch &&
148 echo dirty >>file3 &&
149 test_must_fail git rebase$type related-onto-branch &&
150 test_path_is_file $dotest/autostash &&
151 test_path_is_missing file3 &&
152 echo "conflicting-plus-goodbye" >file2 &&
154 git rebase --continue &&
155 test_path_is_missing $dotest/autostash &&
157 git checkout feature-branch
160 test_expect_success
"rebase$type: --skip" '
161 test_config rebase.autostash true &&
163 git checkout -b rebased-feature-branch feature-branch &&
164 test_when_finished git branch -D rebased-feature-branch &&
165 echo dirty >>file3 &&
166 test_must_fail git rebase$type related-onto-branch &&
167 test_path_is_file $dotest/autostash &&
168 test_path_is_missing file3 &&
170 test_path_is_missing $dotest/autostash &&
172 git checkout feature-branch
175 test_expect_success
"rebase$type: --abort" '
176 test_config rebase.autostash true &&
178 git checkout -b rebased-feature-branch feature-branch &&
179 test_when_finished git branch -D rebased-feature-branch &&
180 echo dirty >>file3 &&
181 test_must_fail git rebase$type related-onto-branch &&
182 test_path_is_file $dotest/autostash &&
183 test_path_is_missing file3 &&
184 git rebase --abort &&
185 test_path_is_missing $dotest/autostash &&
187 git checkout feature-branch
190 test_expect_success
"rebase$type: --quit" '
191 test_config rebase.autostash true &&
193 git checkout -b rebased-feature-branch feature-branch &&
194 test_when_finished git branch -D rebased-feature-branch &&
195 echo dirty >>file3 &&
197 test_must_fail git rebase$type related-onto-branch &&
198 test_path_is_file $dotest/autostash &&
199 test_path_is_missing file3 &&
201 test_when_finished git stash drop &&
202 test_path_is_missing $dotest/autostash &&
203 ! grep dirty file3 &&
204 git stash show -p >actual &&
205 test_cmp expect actual &&
207 git checkout feature-branch
210 test_expect_success
"rebase$type: non-conflicting rebase, conflicting stash" '
211 test_config rebase.autostash true &&
213 git checkout -b rebased-feature-branch feature-branch &&
216 git rebase$type unrelated-onto-branch >actual 2>&1 &&
217 test_path_is_missing $dotest &&
219 grep unrelated file4 &&
220 ! grep dirty file4 &&
221 git checkout feature-branch &&
226 test_expect_success
"rebase$type: check output with conflicting stash" '
227 test_when_finished git branch -D rebased-feature-branch &&
228 suffix=${type#\ --} && suffix=${suffix:-apply} &&
229 if test ${suffix} = "interactive"; then
232 create_expected_failure_$suffix &&
233 sed "$remove_progress_re" <actual >actual2 &&
234 test_cmp expected actual2
238 test_expect_success
"rebase: fast-forward rebase" '
239 test_config rebase.autostash true &&
241 git checkout -b behind-feature-branch feature-branch~1 &&
242 test_when_finished git branch -D behind-feature-branch &&
243 echo dirty >>file1 &&
244 git rebase feature-branch &&
246 git checkout feature-branch
249 test_expect_success
"rebase: noop rebase" '
250 test_config rebase.autostash true &&
252 git checkout -b same-feature-branch feature-branch &&
253 test_when_finished git branch -D same-feature-branch &&
254 echo dirty >>file1 &&
255 git rebase feature-branch &&
257 git checkout feature-branch
260 testrebase
" --apply" .git
/rebase-apply
261 testrebase
" --merge" .git
/rebase-merge
262 testrebase
" --interactive" .git
/rebase-merge
264 test_expect_success
'abort rebase -i with --autostash' '
265 test_when_finished "git reset --hard" &&
266 echo uncommitted-content >file0 &&
268 write_script abort-editor.sh <<-\EOF &&
271 test_set_editor "$(pwd)/abort-editor.sh" &&
272 test_must_fail git rebase -i --autostash HEAD^ &&
273 rm -f abort-editor.sh
275 echo uncommitted-content >expected &&
276 test_cmp expected file0
279 test_expect_success
'restore autostash on editor failure' '
280 test_when_finished "git reset --hard" &&
281 echo uncommitted-content >file0 &&
283 test_set_editor "false" &&
284 test_must_fail git rebase -i --autostash HEAD^
286 echo uncommitted-content >expected &&
287 test_cmp expected file0
290 test_expect_success
'autostash is saved on editor failure with conflict' '
291 test_when_finished "git reset --hard" &&
292 echo uncommitted-content >file0 &&
294 write_script abort-editor.sh <<-\EOF &&
295 echo conflicting-content >file0
298 test_set_editor "$(pwd)/abort-editor.sh" &&
299 test_must_fail git rebase -i --autostash HEAD^ &&
300 rm -f abort-editor.sh
302 echo conflicting-content >expected &&
303 test_cmp expected file0 &&
304 git checkout file0 &&
306 echo uncommitted-content >expected &&
307 test_cmp expected file0
310 test_expect_success
'autostash with dirty submodules' '
311 test_when_finished "git reset --hard && git checkout main" &&
312 git checkout -b with-submodule &&
313 git -c protocol.file.allow=always submodule add ./ sub &&
315 git commit -m add-submodule &&
316 echo changed >sub/file0 &&
317 git rebase -i --autostash HEAD
320 test_expect_success
'branch is left alone when possible' '
321 git checkout -b unchanged-branch &&
322 echo changed >file0 &&
323 git rebase --autostash unchanged-branch &&
324 test changed = "$(cat file0)" &&
325 test unchanged-branch = "$(git rev-parse --abbrev-ref HEAD)"
328 test_expect_success
'never change active branch' '
329 git checkout -b not-the-feature-branch unrelated-onto-branch &&
330 test_when_finished "git reset --hard && git checkout main" &&
331 echo changed >file0 &&
332 git rebase --autostash not-the-feature-branch feature-branch &&
333 test_cmp_rev not-the-feature-branch unrelated-onto-branch
336 test_expect_success
'autostash commit is marked as reachable' '
337 echo changed >file0 &&
338 git rebase --autostash --exec "git prune --expire=now" \
339 feature-branch^ feature-branch &&
340 # git rebase succeeds if the stash cannot be applied so we need to check
341 # the contents of file0
342 echo changed >expect &&
343 test_cmp expect file0