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
10 TEST_PASSES_SANITIZE_LEAK
=true
13 test_expect_success setup
'
14 echo hello-world >file0 &&
17 git commit -m "initial commit" &&
18 git checkout -b feature-branch &&
19 echo another-hello >file1 &&
20 echo goodbye >file2 &&
23 git commit -m "second commit" &&
24 echo final-goodbye >file3 &&
27 git commit -m "third commit" &&
28 git checkout -b unrelated-onto-branch main &&
29 echo unrelated >file4 &&
32 git commit -m "unrelated commit" &&
33 git checkout -b related-onto-branch main &&
34 echo conflicting-change >file2 &&
37 git commit -m "related commit" &&
38 remove_progress_re="$(printf "s/.*\\r//")"
41 create_expected_success_apply
() {
43 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
44 First, rewinding head to replay your work on top of it...
45 Applying: second commit
46 Applying: third commit
51 create_expected_success_merge
() {
52 q_to_cr
>expected
<<-EOF
53 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
55 Successfully rebased and updated refs/heads/rebased-feature-branch.
59 create_expected_failure_apply
() {
61 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
62 First, rewinding head to replay your work on top of it...
63 Applying: second commit
64 Applying: third commit
65 Applying autostash resulted in conflicts.
66 Your changes are safe in the stash.
67 You can run "git stash pop" or "git stash drop" at any time.
71 create_expected_failure_merge
() {
73 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
74 Applying autostash resulted in conflicts.
75 Your changes are safe in the stash.
76 You can run "git stash pop" or "git stash drop" at any time.
77 Successfully rebased and updated refs/heads/rebased-feature-branch.
85 test_expect_success
"rebase$type: dirty worktree, --no-autostash" '
86 test_config rebase.autostash true &&
88 git checkout -b rebased-feature-branch feature-branch &&
89 test_when_finished git branch -D rebased-feature-branch &&
90 test_when_finished git checkout feature-branch &&
92 test_must_fail git rebase$type --no-autostash unrelated-onto-branch
95 test_expect_success
"rebase$type: dirty worktree, non-conflicting rebase" '
96 test_config rebase.autostash true &&
98 git checkout -b rebased-feature-branch feature-branch &&
100 git rebase$type unrelated-onto-branch >actual 2>&1 &&
101 grep unrelated file4 &&
103 git checkout feature-branch
106 test_expect_success
"rebase$type --autostash: check output" '
107 test_when_finished git branch -D rebased-feature-branch &&
108 suffix=${type#\ --} && suffix=${suffix:-apply} &&
109 if test ${suffix} = "interactive"; then
112 create_expected_success_$suffix &&
113 sed "$remove_progress_re" <actual >actual2 &&
114 test_cmp expected actual2
117 test_expect_success
"rebase$type: dirty index, non-conflicting rebase" '
118 test_config rebase.autostash true &&
120 git checkout -b rebased-feature-branch feature-branch &&
121 test_when_finished git branch -D rebased-feature-branch &&
122 echo dirty >>file3 &&
124 git rebase$type unrelated-onto-branch &&
125 grep unrelated file4 &&
127 git checkout feature-branch
130 test_expect_success
"rebase$type: conflicting rebase" '
131 test_config rebase.autostash true &&
133 git checkout -b rebased-feature-branch feature-branch &&
134 test_when_finished git branch -D rebased-feature-branch &&
135 echo dirty >>file3 &&
136 test_must_fail git rebase$type related-onto-branch &&
137 test_path_is_file $dotest/autostash &&
138 test_path_is_missing file3 &&
141 git checkout feature-branch
144 test_expect_success
"rebase$type: --continue" '
145 test_config rebase.autostash true &&
147 git checkout -b rebased-feature-branch feature-branch &&
148 test_when_finished git branch -D rebased-feature-branch &&
149 echo dirty >>file3 &&
150 test_must_fail git rebase$type related-onto-branch &&
151 test_path_is_file $dotest/autostash &&
152 test_path_is_missing file3 &&
153 echo "conflicting-plus-goodbye" >file2 &&
155 git rebase --continue &&
156 test_path_is_missing $dotest/autostash &&
158 git checkout feature-branch
161 test_expect_success
"rebase$type: --skip" '
162 test_config rebase.autostash true &&
164 git checkout -b rebased-feature-branch feature-branch &&
165 test_when_finished git branch -D rebased-feature-branch &&
166 echo dirty >>file3 &&
167 test_must_fail git rebase$type related-onto-branch &&
168 test_path_is_file $dotest/autostash &&
169 test_path_is_missing file3 &&
171 test_path_is_missing $dotest/autostash &&
173 git checkout feature-branch
176 test_expect_success
"rebase$type: --abort" '
177 test_config rebase.autostash true &&
179 git checkout -b rebased-feature-branch feature-branch &&
180 test_when_finished git branch -D rebased-feature-branch &&
181 echo dirty >>file3 &&
182 test_must_fail git rebase$type related-onto-branch &&
183 test_path_is_file $dotest/autostash &&
184 test_path_is_missing file3 &&
185 git rebase --abort &&
186 test_path_is_missing $dotest/autostash &&
188 git checkout feature-branch
191 test_expect_success
"rebase$type: --quit" '
192 test_config rebase.autostash true &&
194 git checkout -b rebased-feature-branch feature-branch &&
195 test_when_finished git branch -D rebased-feature-branch &&
196 echo dirty >>file3 &&
198 test_must_fail git rebase$type related-onto-branch &&
199 test_path_is_file $dotest/autostash &&
200 test_path_is_missing file3 &&
202 test_when_finished git stash drop &&
203 test_path_is_missing $dotest/autostash &&
204 ! grep dirty file3 &&
205 git stash show -p >actual &&
206 test_cmp expect actual &&
208 git checkout feature-branch
211 test_expect_success
"rebase$type: non-conflicting rebase, conflicting stash" '
212 test_config rebase.autostash true &&
214 git checkout -b rebased-feature-branch feature-branch &&
217 git rebase$type unrelated-onto-branch >actual 2>&1 &&
218 test_path_is_missing $dotest &&
220 grep unrelated file4 &&
221 ! grep dirty file4 &&
222 git checkout feature-branch &&
227 test_expect_success
"rebase$type: check output with conflicting stash" '
228 test_when_finished git branch -D rebased-feature-branch &&
229 suffix=${type#\ --} && suffix=${suffix:-apply} &&
230 if test ${suffix} = "interactive"; then
233 create_expected_failure_$suffix &&
234 sed "$remove_progress_re" <actual >actual2 &&
235 test_cmp expected actual2
239 test_expect_success
"rebase: fast-forward rebase" '
240 test_config rebase.autostash true &&
242 git checkout -b behind-feature-branch feature-branch~1 &&
243 test_when_finished git branch -D behind-feature-branch &&
244 echo dirty >>file1 &&
245 git rebase feature-branch &&
247 git checkout feature-branch
250 test_expect_success
"rebase: noop rebase" '
251 test_config rebase.autostash true &&
253 git checkout -b same-feature-branch feature-branch &&
254 test_when_finished git branch -D same-feature-branch &&
255 echo dirty >>file1 &&
256 git rebase feature-branch &&
258 git checkout feature-branch
261 testrebase
" --apply" .git
/rebase-apply
262 testrebase
" --merge" .git
/rebase-merge
263 testrebase
" --interactive" .git
/rebase-merge
265 test_expect_success
'abort rebase -i with --autostash' '
266 test_when_finished "git reset --hard" &&
267 echo uncommitted-content >file0 &&
269 write_script abort-editor.sh <<-\EOF &&
272 test_set_editor "$(pwd)/abort-editor.sh" &&
273 test_must_fail git rebase -i --autostash HEAD^ &&
274 rm -f abort-editor.sh
276 echo uncommitted-content >expected &&
277 test_cmp expected file0
280 test_expect_success
'restore autostash on editor failure' '
281 test_when_finished "git reset --hard" &&
282 echo uncommitted-content >file0 &&
284 test_set_editor "false" &&
285 test_must_fail git rebase -i --autostash HEAD^
287 echo uncommitted-content >expected &&
288 test_cmp expected file0
291 test_expect_success
'autostash is saved on editor failure with conflict' '
292 test_when_finished "git reset --hard" &&
293 echo uncommitted-content >file0 &&
295 write_script abort-editor.sh <<-\EOF &&
296 echo conflicting-content >file0
299 test_set_editor "$(pwd)/abort-editor.sh" &&
300 test_must_fail git rebase -i --autostash HEAD^ &&
301 rm -f abort-editor.sh
303 echo conflicting-content >expected &&
304 test_cmp expected file0 &&
305 git checkout file0 &&
307 echo uncommitted-content >expected &&
308 test_cmp expected file0
311 test_expect_success
'autostash with dirty submodules' '
312 test_when_finished "git reset --hard && git checkout main" &&
313 git checkout -b with-submodule &&
314 git -c protocol.file.allow=always submodule add ./ sub &&
316 git commit -m add-submodule &&
317 echo changed >sub/file0 &&
318 git rebase -i --autostash HEAD
321 test_expect_success
'branch is left alone when possible' '
322 git checkout -b unchanged-branch &&
323 echo changed >file0 &&
324 git rebase --autostash unchanged-branch &&
325 test changed = "$(cat file0)" &&
326 test unchanged-branch = "$(git rev-parse --abbrev-ref HEAD)"
329 test_expect_success
'never change active branch' '
330 git checkout -b not-the-feature-branch unrelated-onto-branch &&
331 test_when_finished "git reset --hard && git checkout main" &&
332 echo changed >file0 &&
333 git rebase --autostash not-the-feature-branch feature-branch &&
334 test_cmp_rev not-the-feature-branch unrelated-onto-branch
337 test_expect_success
'autostash commit is marked as reachable' '
338 echo changed >file0 &&
339 git rebase --autostash --exec "git prune --expire=now" \
340 feature-branch^ feature-branch &&
341 # git rebase succeeds if the stash cannot be applied so we need to check
342 # the contents of file0
343 echo changed >expect &&
344 test_cmp expect file0