rebase --autostash: fix issue with dirty submodules
[git/git.git] / t / t3420-rebase-autostash.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2013 Ramkumar Ramachandra
4 #
5
6 test_description='git rebase --autostash tests'
7 . ./test-lib.sh
8
9 test_expect_success setup '
10 echo hello-world >file0 &&
11 git add . &&
12 test_tick &&
13 git commit -m "initial commit" &&
14 git checkout -b feature-branch &&
15 echo another-hello >file1 &&
16 echo goodbye >file2 &&
17 git add . &&
18 test_tick &&
19 git commit -m "second commit" &&
20 echo final-goodbye >file3 &&
21 git add . &&
22 test_tick &&
23 git commit -m "third commit" &&
24 git checkout -b unrelated-onto-branch master &&
25 echo unrelated >file4 &&
26 git add . &&
27 test_tick &&
28 git commit -m "unrelated commit" &&
29 git checkout -b related-onto-branch master &&
30 echo conflicting-change >file2 &&
31 git add . &&
32 test_tick &&
33 git commit -m "related commit"
34 '
35
36 create_expected_success_am () {
37 cat >expected <<-EOF
38 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
39 HEAD is now at $(git rev-parse --short feature-branch) third commit
40 First, rewinding head to replay your work on top of it...
41 Applying: second commit
42 Applying: third commit
43 Applied autostash.
44 EOF
45 }
46
47 create_expected_success_interactive () {
48 q_to_cr >expected <<-EOF
49 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
50 HEAD is now at $(git rev-parse --short feature-branch) third commit
51 Rebasing (1/2)QRebasing (2/2)QApplied autostash.
52 Successfully rebased and updated refs/heads/rebased-feature-branch.
53 EOF
54 }
55
56 create_expected_success_merge () {
57 cat >expected <<-EOF
58 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
59 HEAD is now at $(git rev-parse --short feature-branch) third commit
60 First, rewinding head to replay your work on top of it...
61 Merging unrelated-onto-branch with HEAD~1
62 Merging:
63 $(git rev-parse --short unrelated-onto-branch) unrelated commit
64 $(git rev-parse --short feature-branch^) second commit
65 found 1 common ancestor:
66 $(git rev-parse --short feature-branch~2) initial commit
67 [detached HEAD $(git rev-parse --short rebased-feature-branch~1)] second commit
68 Author: A U Thor <author@example.com>
69 Date: Thu Apr 7 15:14:13 2005 -0700
70 2 files changed, 2 insertions(+)
71 create mode 100644 file1
72 create mode 100644 file2
73 Committed: 0001 second commit
74 Merging unrelated-onto-branch with HEAD~0
75 Merging:
76 $(git rev-parse --short rebased-feature-branch~1) second commit
77 $(git rev-parse --short feature-branch) third commit
78 found 1 common ancestor:
79 $(git rev-parse --short feature-branch~1) second commit
80 [detached HEAD $(git rev-parse --short rebased-feature-branch)] third commit
81 Author: A U Thor <author@example.com>
82 Date: Thu Apr 7 15:15:13 2005 -0700
83 1 file changed, 1 insertion(+)
84 create mode 100644 file3
85 Committed: 0002 third commit
86 All done.
87 Applied autostash.
88 EOF
89 }
90
91 create_expected_failure_am () {
92 cat >expected <<-EOF
93 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
94 HEAD is now at $(git rev-parse --short feature-branch) third commit
95 First, rewinding head to replay your work on top of it...
96 Applying: second commit
97 Applying: third commit
98 Applying autostash resulted in conflicts.
99 Your changes are safe in the stash.
100 You can run "git stash pop" or "git stash drop" at any time.
101 EOF
102 }
103
104 create_expected_failure_interactive () {
105 q_to_cr >expected <<-EOF
106 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
107 HEAD is now at $(git rev-parse --short feature-branch) third commit
108 Rebasing (1/2)QRebasing (2/2)QApplying autostash resulted in conflicts.
109 Your changes are safe in the stash.
110 You can run "git stash pop" or "git stash drop" at any time.
111 Successfully rebased and updated refs/heads/rebased-feature-branch.
112 EOF
113 }
114
115 create_expected_failure_merge () {
116 cat >expected <<-EOF
117 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
118 HEAD is now at $(git rev-parse --short feature-branch) third commit
119 First, rewinding head to replay your work on top of it...
120 Merging unrelated-onto-branch with HEAD~1
121 Merging:
122 $(git rev-parse --short unrelated-onto-branch) unrelated commit
123 $(git rev-parse --short feature-branch^) second commit
124 found 1 common ancestor:
125 $(git rev-parse --short feature-branch~2) initial commit
126 [detached HEAD $(git rev-parse --short rebased-feature-branch~1)] second commit
127 Author: A U Thor <author@example.com>
128 Date: Thu Apr 7 15:14:13 2005 -0700
129 2 files changed, 2 insertions(+)
130 create mode 100644 file1
131 create mode 100644 file2
132 Committed: 0001 second commit
133 Merging unrelated-onto-branch with HEAD~0
134 Merging:
135 $(git rev-parse --short rebased-feature-branch~1) second commit
136 $(git rev-parse --short feature-branch) third commit
137 found 1 common ancestor:
138 $(git rev-parse --short feature-branch~1) second commit
139 [detached HEAD $(git rev-parse --short rebased-feature-branch)] third commit
140 Author: A U Thor <author@example.com>
141 Date: Thu Apr 7 15:15:13 2005 -0700
142 1 file changed, 1 insertion(+)
143 create mode 100644 file3
144 Committed: 0002 third commit
145 All done.
146 Applying autostash resulted in conflicts.
147 Your changes are safe in the stash.
148 You can run "git stash pop" or "git stash drop" at any time.
149 EOF
150 }
151
152 testrebase () {
153 type=$1
154 dotest=$2
155
156 test_expect_success "rebase$type: dirty worktree, --no-autostash" '
157 test_config rebase.autostash true &&
158 git reset --hard &&
159 git checkout -b rebased-feature-branch feature-branch &&
160 test_when_finished git branch -D rebased-feature-branch &&
161 test_when_finished git checkout feature-branch &&
162 echo dirty >>file3 &&
163 test_must_fail git rebase$type --no-autostash unrelated-onto-branch
164 '
165
166 test_expect_success "rebase$type: dirty worktree, non-conflicting rebase" '
167 test_config rebase.autostash true &&
168 git reset --hard &&
169 git checkout -b rebased-feature-branch feature-branch &&
170 echo dirty >>file3 &&
171 git rebase$type unrelated-onto-branch >actual 2>&1 &&
172 grep unrelated file4 &&
173 grep dirty file3 &&
174 git checkout feature-branch
175 '
176
177 test_expect_success "rebase$type --autostash: check output" '
178 test_when_finished git branch -D rebased-feature-branch &&
179 suffix=${type#\ --} && suffix=${suffix:-am} &&
180 create_expected_success_$suffix &&
181 test_i18ncmp expected actual
182 '
183
184 test_expect_success "rebase$type: dirty index, non-conflicting rebase" '
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 git add file3 &&
191 git rebase$type unrelated-onto-branch &&
192 grep unrelated file4 &&
193 grep dirty file3 &&
194 git checkout feature-branch
195 '
196
197 test_expect_success "rebase$type: conflicting rebase" '
198 test_config rebase.autostash true &&
199 git reset --hard &&
200 git checkout -b rebased-feature-branch feature-branch &&
201 test_when_finished git branch -D rebased-feature-branch &&
202 echo dirty >>file3 &&
203 test_must_fail git rebase$type related-onto-branch &&
204 test_path_is_file $dotest/autostash &&
205 ! grep dirty file3 &&
206 rm -rf $dotest &&
207 git reset --hard &&
208 git checkout feature-branch
209 '
210
211 test_expect_success "rebase$type: --continue" '
212 test_config rebase.autostash true &&
213 git reset --hard &&
214 git checkout -b rebased-feature-branch feature-branch &&
215 test_when_finished git branch -D rebased-feature-branch &&
216 echo dirty >>file3 &&
217 test_must_fail git rebase$type related-onto-branch &&
218 test_path_is_file $dotest/autostash &&
219 ! grep dirty file3 &&
220 echo "conflicting-plus-goodbye" >file2 &&
221 git add file2 &&
222 git rebase --continue &&
223 test_path_is_missing $dotest/autostash &&
224 grep dirty file3 &&
225 git checkout feature-branch
226 '
227
228 test_expect_success "rebase$type: --skip" '
229 test_config rebase.autostash true &&
230 git reset --hard &&
231 git checkout -b rebased-feature-branch feature-branch &&
232 test_when_finished git branch -D rebased-feature-branch &&
233 echo dirty >>file3 &&
234 test_must_fail git rebase$type related-onto-branch &&
235 test_path_is_file $dotest/autostash &&
236 ! grep dirty file3 &&
237 git rebase --skip &&
238 test_path_is_missing $dotest/autostash &&
239 grep dirty file3 &&
240 git checkout feature-branch
241 '
242
243 test_expect_success "rebase$type: --abort" '
244 test_config rebase.autostash true &&
245 git reset --hard &&
246 git checkout -b rebased-feature-branch feature-branch &&
247 test_when_finished git branch -D rebased-feature-branch &&
248 echo dirty >>file3 &&
249 test_must_fail git rebase$type related-onto-branch &&
250 test_path_is_file $dotest/autostash &&
251 ! grep dirty file3 &&
252 git rebase --abort &&
253 test_path_is_missing $dotest/autostash &&
254 grep dirty file3 &&
255 git checkout feature-branch
256 '
257
258 test_expect_success "rebase$type: non-conflicting rebase, conflicting stash" '
259 test_config rebase.autostash true &&
260 git reset --hard &&
261 git checkout -b rebased-feature-branch feature-branch &&
262 echo dirty >file4 &&
263 git add file4 &&
264 git rebase$type unrelated-onto-branch >actual 2>&1 &&
265 test_path_is_missing $dotest &&
266 git reset --hard &&
267 grep unrelated file4 &&
268 ! grep dirty file4 &&
269 git checkout feature-branch &&
270 git stash pop &&
271 grep dirty file4
272 '
273
274 test_expect_success "rebase$type: check output with conflicting stash" '
275 test_when_finished git branch -D rebased-feature-branch &&
276 suffix=${type#\ --} && suffix=${suffix:-am} &&
277 create_expected_failure_$suffix &&
278 test_i18ncmp expected actual
279 '
280 }
281
282 test_expect_success "rebase: fast-forward rebase" '
283 test_config rebase.autostash true &&
284 git reset --hard &&
285 git checkout -b behind-feature-branch feature-branch~1 &&
286 test_when_finished git branch -D behind-feature-branch &&
287 echo dirty >>file1 &&
288 git rebase feature-branch &&
289 grep dirty file1 &&
290 git checkout feature-branch
291 '
292
293 test_expect_success "rebase: noop rebase" '
294 test_config rebase.autostash true &&
295 git reset --hard &&
296 git checkout -b same-feature-branch feature-branch &&
297 test_when_finished git branch -D same-feature-branch &&
298 echo dirty >>file1 &&
299 git rebase feature-branch &&
300 grep dirty file1 &&
301 git checkout feature-branch
302 '
303
304 testrebase "" .git/rebase-apply
305 testrebase " --merge" .git/rebase-merge
306 testrebase " --interactive" .git/rebase-merge
307
308 test_expect_success 'abort rebase -i with --autostash' '
309 test_when_finished "git reset --hard" &&
310 echo uncommitted-content >file0 &&
311 (
312 write_script abort-editor.sh <<-\EOF &&
313 echo >"$1"
314 EOF
315 test_set_editor "$(pwd)/abort-editor.sh" &&
316 test_must_fail git rebase -i --autostash HEAD^ &&
317 rm -f abort-editor.sh
318 ) &&
319 echo uncommitted-content >expected &&
320 test_cmp expected file0
321 '
322
323 test_expect_success 'restore autostash on editor failure' '
324 test_when_finished "git reset --hard" &&
325 echo uncommitted-content >file0 &&
326 (
327 test_set_editor "false" &&
328 test_must_fail git rebase -i --autostash HEAD^
329 ) &&
330 echo uncommitted-content >expected &&
331 test_cmp expected file0
332 '
333
334 test_expect_success 'autostash is saved on editor failure with conflict' '
335 test_when_finished "git reset --hard" &&
336 echo uncommitted-content >file0 &&
337 (
338 write_script abort-editor.sh <<-\EOF &&
339 echo conflicting-content >file0
340 exit 1
341 EOF
342 test_set_editor "$(pwd)/abort-editor.sh" &&
343 test_must_fail git rebase -i --autostash HEAD^ &&
344 rm -f abort-editor.sh
345 ) &&
346 echo conflicting-content >expected &&
347 test_cmp expected file0 &&
348 git checkout file0 &&
349 git stash pop &&
350 echo uncommitted-content >expected &&
351 test_cmp expected file0
352 '
353
354 test_expect_success 'autostash with dirty submodules' '
355 test_when_finished "git reset --hard && git checkout master" &&
356 git checkout -b with-submodule &&
357 git submodule add ./ sub &&
358 test_tick &&
359 git commit -m add-submodule &&
360 echo changed >sub/file0 &&
361 git rebase -i --autostash HEAD
362 '
363
364 test_done