Merge branch 'ja/doc-synopsis-markup'
[git/gitster.git] / t / t3420-rebase-autostash.sh
blobb43046b3b0dfb89740692a16f0e365d091590657
1 #!/bin/sh
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
11 . ./test-lib.sh
13 test_expect_success setup '
14 echo hello-world >file0 &&
15 git add . &&
16 test_tick &&
17 git commit -m "initial commit" &&
18 git checkout -b feature-branch &&
19 echo another-hello >file1 &&
20 echo goodbye >file2 &&
21 git add . &&
22 test_tick &&
23 git commit -m "second commit" &&
24 echo final-goodbye >file3 &&
25 git add . &&
26 test_tick &&
27 git commit -m "third commit" &&
28 git checkout -b unrelated-onto-branch main &&
29 echo unrelated >file4 &&
30 git add . &&
31 test_tick &&
32 git commit -m "unrelated commit" &&
33 git checkout -b related-onto-branch main &&
34 echo conflicting-change >file2 &&
35 git add . &&
36 test_tick &&
37 git commit -m "related commit" &&
38 remove_progress_re="$(printf "s/.*\\r//")"
41 create_expected_success_apply () {
42 cat >expected <<-EOF
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
47 Applied autostash.
48 EOF
51 create_expected_success_merge () {
52 q_to_cr >expected <<-EOF
53 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
54 Applied autostash.
55 Successfully rebased and updated refs/heads/rebased-feature-branch.
56 EOF
59 create_expected_failure_apply () {
60 cat >expected <<-EOF
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.
68 EOF
71 create_expected_failure_merge () {
72 cat >expected <<-EOF
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.
78 EOF
81 testrebase () {
82 type=$1
83 dotest=$2
85 test_expect_success "rebase$type: restore autostash when pre-rebase hook fails" '
86 git checkout -f feature-branch &&
87 test_hook pre-rebase <<-\EOF &&
88 exit 1
89 EOF
91 echo changed >file0 &&
92 test_must_fail git rebase $type --autostash -f HEAD^ &&
93 test_must_fail git rebase --quit 2>err &&
94 test_grep "no rebase in progress" err &&
95 echo changed >expect &&
96 test_cmp expect file0
99 test_expect_success "rebase$type: restore autostash when checkout onto fails" '
100 git checkout -f --detach feature-branch &&
101 echo uncommitted-content >file0 &&
102 echo untracked >file4 &&
103 test_when_finished "rm file4" &&
104 test_must_fail git rebase $type --autostash \
105 unrelated-onto-branch &&
106 test_must_fail git rebase --quit 2>err &&
107 test_grep "no rebase in progress" err &&
108 echo uncommitted-content >expect &&
109 test_cmp expect file0
112 test_expect_success "rebase$type: restore autostash when branch checkout fails" '
113 git checkout -f unrelated-onto-branch^ &&
114 echo uncommitted-content >file0 &&
115 echo untracked >file4 &&
116 test_when_finished "rm file4" &&
117 test_must_fail git rebase $type --autostash HEAD \
118 unrelated-onto-branch &&
119 test_must_fail git rebase --quit 2>err &&
120 test_grep "no rebase in progress" err &&
121 echo uncommitted-content >expect &&
122 test_cmp expect file0
125 test_expect_success "rebase$type: dirty worktree, --no-autostash" '
126 test_config rebase.autostash true &&
127 git reset --hard &&
128 git checkout -b rebased-feature-branch feature-branch &&
129 test_when_finished git branch -D rebased-feature-branch &&
130 test_when_finished git checkout feature-branch &&
131 echo dirty >>file3 &&
132 test_must_fail git rebase$type --no-autostash unrelated-onto-branch
135 test_expect_success "rebase$type: dirty worktree, non-conflicting rebase" '
136 test_config rebase.autostash true &&
137 git reset --hard &&
138 git checkout -b rebased-feature-branch feature-branch &&
139 echo dirty >>file3 &&
140 git rebase$type unrelated-onto-branch >actual 2>&1 &&
141 grep unrelated file4 &&
142 grep dirty file3 &&
143 git checkout feature-branch
146 test_expect_success "rebase$type --autostash: check output" '
147 test_when_finished git branch -D rebased-feature-branch &&
148 suffix=${type#\ --} && suffix=${suffix:-apply} &&
149 if test ${suffix} = "interactive"; then
150 suffix=merge
151 fi &&
152 create_expected_success_$suffix &&
153 sed "$remove_progress_re" <actual >actual2 &&
154 test_cmp expected actual2
157 test_expect_success "rebase$type: dirty index, non-conflicting rebase" '
158 test_config rebase.autostash true &&
159 git reset --hard &&
160 git checkout -b rebased-feature-branch feature-branch &&
161 test_when_finished git branch -D rebased-feature-branch &&
162 echo dirty >>file3 &&
163 git add file3 &&
164 git rebase$type unrelated-onto-branch &&
165 grep unrelated file4 &&
166 grep dirty file3 &&
167 git checkout feature-branch
170 test_expect_success "rebase$type: conflicting rebase" '
171 test_config rebase.autostash true &&
172 git reset --hard &&
173 git checkout -b rebased-feature-branch feature-branch &&
174 test_when_finished git branch -D rebased-feature-branch &&
175 echo dirty >>file3 &&
176 test_must_fail git rebase$type related-onto-branch &&
177 test_path_is_file $dotest/autostash &&
178 test_path_is_missing file3 &&
179 rm -rf $dotest &&
180 git reset --hard &&
181 git checkout feature-branch
184 test_expect_success "rebase$type: --continue" '
185 test_config rebase.autostash true &&
186 git reset --hard &&
187 git checkout -b rebased-feature-branch feature-branch &&
188 test_when_finished git branch -D rebased-feature-branch &&
189 echo dirty >>file3 &&
190 test_must_fail git rebase$type related-onto-branch &&
191 test_path_is_file $dotest/autostash &&
192 test_path_is_missing file3 &&
193 echo "conflicting-plus-goodbye" >file2 &&
194 git add file2 &&
195 git rebase --continue &&
196 test_path_is_missing $dotest/autostash &&
197 grep dirty file3 &&
198 git checkout feature-branch
201 test_expect_success "rebase$type: --skip" '
202 test_config rebase.autostash true &&
203 git reset --hard &&
204 git checkout -b rebased-feature-branch feature-branch &&
205 test_when_finished git branch -D rebased-feature-branch &&
206 echo dirty >>file3 &&
207 test_must_fail git rebase$type related-onto-branch &&
208 test_path_is_file $dotest/autostash &&
209 test_path_is_missing file3 &&
210 git rebase --skip &&
211 test_path_is_missing $dotest/autostash &&
212 grep dirty file3 &&
213 git checkout feature-branch
216 test_expect_success "rebase$type: --abort" '
217 test_config rebase.autostash true &&
218 git reset --hard &&
219 git checkout -b rebased-feature-branch feature-branch &&
220 test_when_finished git branch -D rebased-feature-branch &&
221 echo dirty >>file3 &&
222 test_must_fail git rebase$type related-onto-branch &&
223 test_path_is_file $dotest/autostash &&
224 test_path_is_missing file3 &&
225 git rebase --abort &&
226 test_path_is_missing $dotest/autostash &&
227 grep dirty file3 &&
228 git checkout feature-branch
231 test_expect_success "rebase$type: --quit" '
232 test_config rebase.autostash true &&
233 git reset --hard &&
234 git checkout -b rebased-feature-branch feature-branch &&
235 test_when_finished git branch -D rebased-feature-branch &&
236 echo dirty >>file3 &&
237 git diff >expect &&
238 test_must_fail git rebase$type related-onto-branch &&
239 test_path_is_file $dotest/autostash &&
240 test_path_is_missing file3 &&
241 git rebase --quit &&
242 test_when_finished git stash drop &&
243 test_path_is_missing $dotest/autostash &&
244 ! grep dirty file3 &&
245 git stash show -p >actual &&
246 test_cmp expect actual &&
247 git reset --hard &&
248 git checkout feature-branch
251 test_expect_success "rebase$type: non-conflicting rebase, conflicting stash" '
252 test_config rebase.autostash true &&
253 git reset --hard &&
254 git checkout -b rebased-feature-branch feature-branch &&
255 echo dirty >file4 &&
256 git add file4 &&
257 git rebase$type unrelated-onto-branch >actual 2>&1 &&
258 test_path_is_missing $dotest &&
259 git reset --hard &&
260 grep unrelated file4 &&
261 ! grep dirty file4 &&
262 git checkout feature-branch &&
263 git stash pop &&
264 grep dirty file4
267 test_expect_success "rebase$type: check output with conflicting stash" '
268 test_when_finished git branch -D rebased-feature-branch &&
269 suffix=${type#\ --} && suffix=${suffix:-apply} &&
270 if test ${suffix} = "interactive"; then
271 suffix=merge
272 fi &&
273 create_expected_failure_$suffix &&
274 sed "$remove_progress_re" <actual >actual2 &&
275 test_cmp expected actual2
279 test_expect_success "rebase: fast-forward rebase" '
280 test_config rebase.autostash true &&
281 git reset --hard &&
282 git checkout -b behind-feature-branch feature-branch~1 &&
283 test_when_finished git branch -D behind-feature-branch &&
284 echo dirty >>file1 &&
285 git rebase feature-branch &&
286 grep dirty file1 &&
287 git checkout feature-branch
290 test_expect_success "rebase: noop rebase" '
291 test_config rebase.autostash true &&
292 git reset --hard &&
293 git checkout -b same-feature-branch feature-branch &&
294 test_when_finished git branch -D same-feature-branch &&
295 echo dirty >>file1 &&
296 git rebase feature-branch &&
297 grep dirty file1 &&
298 git checkout feature-branch
301 testrebase " --apply" .git/rebase-apply
302 testrebase " --merge" .git/rebase-merge
303 testrebase " --interactive" .git/rebase-merge
305 test_expect_success 'abort rebase -i with --autostash' '
306 test_when_finished "git reset --hard" &&
307 echo uncommitted-content >file0 &&
309 write_script abort-editor.sh <<-\EOF &&
310 echo >"$1"
312 test_set_editor "$(pwd)/abort-editor.sh" &&
313 test_must_fail git rebase -i --autostash HEAD^ &&
314 rm -f abort-editor.sh
315 ) &&
316 echo uncommitted-content >expected &&
317 test_cmp expected file0
320 test_expect_success 'restore autostash on editor failure' '
321 test_when_finished "git reset --hard" &&
322 echo uncommitted-content >file0 &&
324 test_set_editor "false" &&
325 test_must_fail git rebase -i --autostash HEAD^
326 ) &&
327 echo uncommitted-content >expected &&
328 test_cmp expected file0
331 test_expect_success 'autostash is saved on editor failure with conflict' '
332 test_when_finished "git reset --hard" &&
333 echo uncommitted-content >file0 &&
335 write_script abort-editor.sh <<-\EOF &&
336 echo conflicting-content >file0
337 exit 1
339 test_set_editor "$(pwd)/abort-editor.sh" &&
340 test_must_fail git rebase -i --autostash HEAD^ &&
341 rm -f abort-editor.sh
342 ) &&
343 echo conflicting-content >expected &&
344 test_cmp expected file0 &&
345 git checkout file0 &&
346 git stash pop &&
347 echo uncommitted-content >expected &&
348 test_cmp expected file0
351 test_expect_success 'autostash with dirty submodules' '
352 test_when_finished "git reset --hard && git checkout main" &&
353 git checkout -b with-submodule &&
354 git -c protocol.file.allow=always submodule add ./ sub &&
355 test_tick &&
356 git commit -m add-submodule &&
357 echo changed >sub/file0 &&
358 git rebase -i --autostash HEAD
361 test_expect_success 'branch is left alone when possible' '
362 git checkout -b unchanged-branch &&
363 echo changed >file0 &&
364 git rebase --autostash unchanged-branch &&
365 test changed = "$(cat file0)" &&
366 test unchanged-branch = "$(git rev-parse --abbrev-ref HEAD)"
369 test_expect_success 'never change active branch' '
370 git checkout -b not-the-feature-branch unrelated-onto-branch &&
371 test_when_finished "git reset --hard && git checkout main" &&
372 echo changed >file0 &&
373 git rebase --autostash not-the-feature-branch feature-branch &&
374 test_cmp_rev not-the-feature-branch unrelated-onto-branch
377 test_expect_success 'autostash commit is marked as reachable' '
378 echo changed >file0 &&
379 git rebase --autostash --exec "git prune --expire=now" \
380 feature-branch^ feature-branch &&
381 # git rebase succeeds if the stash cannot be applied so we need to check
382 # the contents of file0
383 echo changed >expect &&
384 test_cmp expect file0
387 test_done