Merge branch 'al/t3200-back-on-a-branch'
[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         remove_progress_re="$(printf "s/.*\\r//")"
35 '
36
37 create_expected_success_apply () {
38         cat >expected <<-EOF
39         $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
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_merge () {
48         q_to_cr >expected <<-EOF
49         $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
50         Applied autostash.
51         Successfully rebased and updated refs/heads/rebased-feature-branch.
52         EOF
53 }
54
55 create_expected_failure_apply () {
56         cat >expected <<-EOF
57         $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
58         First, rewinding head to replay your work on top of it...
59         Applying: second commit
60         Applying: third commit
61         Applying autostash resulted in conflicts.
62         Your changes are safe in the stash.
63         You can run "git stash pop" or "git stash drop" at any time.
64         EOF
65 }
66
67 create_expected_failure_merge () {
68         cat >expected <<-EOF
69         $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
70         Applying autostash resulted in conflicts.
71         Your changes are safe in the stash.
72         You can run "git stash pop" or "git stash drop" at any time.
73         Successfully rebased and updated refs/heads/rebased-feature-branch.
74         EOF
75 }
76
77 testrebase () {
78         type=$1
79         dotest=$2
80
81         test_expect_success "rebase$type: dirty worktree, --no-autostash" '
82                 test_config rebase.autostash true &&
83                 git reset --hard &&
84                 git checkout -b rebased-feature-branch feature-branch &&
85                 test_when_finished git branch -D rebased-feature-branch &&
86                 test_when_finished git checkout feature-branch &&
87                 echo dirty >>file3 &&
88                 test_must_fail git rebase$type --no-autostash unrelated-onto-branch
89         '
90
91         test_expect_success "rebase$type: dirty worktree, non-conflicting rebase" '
92                 test_config rebase.autostash true &&
93                 git reset --hard &&
94                 git checkout -b rebased-feature-branch feature-branch &&
95                 echo dirty >>file3 &&
96                 git rebase$type unrelated-onto-branch >actual 2>&1 &&
97                 grep unrelated file4 &&
98                 grep dirty file3 &&
99                 git checkout feature-branch
100         '
101
102         test_expect_success "rebase$type --autostash: check output" '
103                 test_when_finished git branch -D rebased-feature-branch &&
104                 suffix=${type#\ --} && suffix=${suffix:-apply} &&
105                 if test ${suffix} = "interactive"; then
106                         suffix=merge
107                 fi &&
108                 create_expected_success_$suffix &&
109                 sed "$remove_progress_re" <actual >actual2 &&
110                 test_i18ncmp expected actual2
111         '
112
113         test_expect_success "rebase$type: dirty index, non-conflicting rebase" '
114                 test_config rebase.autostash true &&
115                 git reset --hard &&
116                 git checkout -b rebased-feature-branch feature-branch &&
117                 test_when_finished git branch -D rebased-feature-branch &&
118                 echo dirty >>file3 &&
119                 git add file3 &&
120                 git rebase$type unrelated-onto-branch &&
121                 grep unrelated file4 &&
122                 grep dirty file3 &&
123                 git checkout feature-branch
124         '
125
126         test_expect_success "rebase$type: conflicting rebase" '
127                 test_config rebase.autostash true &&
128                 git reset --hard &&
129                 git checkout -b rebased-feature-branch feature-branch &&
130                 test_when_finished git branch -D rebased-feature-branch &&
131                 echo dirty >>file3 &&
132                 test_must_fail git rebase$type related-onto-branch &&
133                 test_path_is_file $dotest/autostash &&
134                 test_path_is_missing file3 &&
135                 rm -rf $dotest &&
136                 git reset --hard &&
137                 git checkout feature-branch
138         '
139
140         test_expect_success "rebase$type: --continue" '
141                 test_config rebase.autostash true &&
142                 git reset --hard &&
143                 git checkout -b rebased-feature-branch feature-branch &&
144                 test_when_finished git branch -D rebased-feature-branch &&
145                 echo dirty >>file3 &&
146                 test_must_fail git rebase$type related-onto-branch &&
147                 test_path_is_file $dotest/autostash &&
148                 test_path_is_missing file3 &&
149                 echo "conflicting-plus-goodbye" >file2 &&
150                 git add file2 &&
151                 git rebase --continue &&
152                 test_path_is_missing $dotest/autostash &&
153                 grep dirty file3 &&
154                 git checkout feature-branch
155         '
156
157         test_expect_success "rebase$type: --skip" '
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                 test_must_fail git rebase$type related-onto-branch &&
164                 test_path_is_file $dotest/autostash &&
165                 test_path_is_missing file3 &&
166                 git rebase --skip &&
167                 test_path_is_missing $dotest/autostash &&
168                 grep dirty file3 &&
169                 git checkout feature-branch
170         '
171
172         test_expect_success "rebase$type: --abort" '
173                 test_config rebase.autostash true &&
174                 git reset --hard &&
175                 git checkout -b rebased-feature-branch feature-branch &&
176                 test_when_finished git branch -D rebased-feature-branch &&
177                 echo dirty >>file3 &&
178                 test_must_fail git rebase$type related-onto-branch &&
179                 test_path_is_file $dotest/autostash &&
180                 test_path_is_missing file3 &&
181                 git rebase --abort &&
182                 test_path_is_missing $dotest/autostash &&
183                 grep dirty file3 &&
184                 git checkout feature-branch
185         '
186
187         test_expect_success "rebase$type: --quit" '
188                 test_config rebase.autostash true &&
189                 git reset --hard &&
190                 git checkout -b rebased-feature-branch feature-branch &&
191                 test_when_finished git branch -D rebased-feature-branch &&
192                 echo dirty >>file3 &&
193                 git diff >expect &&
194                 test_must_fail git rebase$type related-onto-branch &&
195                 test_path_is_file $dotest/autostash &&
196                 test_path_is_missing file3 &&
197                 git rebase --quit &&
198                 test_when_finished git stash drop &&
199                 test_path_is_missing $dotest/autostash &&
200                 ! grep dirty file3 &&
201                 git stash show -p >actual &&
202                 test_cmp expect actual &&
203                 git reset --hard &&
204                 git checkout feature-branch
205         '
206
207         test_expect_success "rebase$type: non-conflicting rebase, conflicting stash" '
208                 test_config rebase.autostash true &&
209                 git reset --hard &&
210                 git checkout -b rebased-feature-branch feature-branch &&
211                 echo dirty >file4 &&
212                 git add file4 &&
213                 git rebase$type unrelated-onto-branch >actual 2>&1 &&
214                 test_path_is_missing $dotest &&
215                 git reset --hard &&
216                 grep unrelated file4 &&
217                 ! grep dirty file4 &&
218                 git checkout feature-branch &&
219                 git stash pop &&
220                 grep dirty file4
221         '
222
223         test_expect_success "rebase$type: check output with conflicting stash" '
224                 test_when_finished git branch -D rebased-feature-branch &&
225                 suffix=${type#\ --} && suffix=${suffix:-apply} &&
226                 if test ${suffix} = "interactive"; then
227                         suffix=merge
228                 fi &&
229                 create_expected_failure_$suffix &&
230                 sed "$remove_progress_re" <actual >actual2 &&
231                 test_i18ncmp expected actual2
232         '
233 }
234
235 test_expect_success "rebase: fast-forward rebase" '
236         test_config rebase.autostash true &&
237         git reset --hard &&
238         git checkout -b behind-feature-branch feature-branch~1 &&
239         test_when_finished git branch -D behind-feature-branch &&
240         echo dirty >>file1 &&
241         git rebase feature-branch &&
242         grep dirty file1 &&
243         git checkout feature-branch
244 '
245
246 test_expect_success "rebase: noop rebase" '
247         test_config rebase.autostash true &&
248         git reset --hard &&
249         git checkout -b same-feature-branch feature-branch &&
250         test_when_finished git branch -D same-feature-branch &&
251         echo dirty >>file1 &&
252         git rebase feature-branch &&
253         grep dirty file1 &&
254         git checkout feature-branch
255 '
256
257 testrebase " --apply" .git/rebase-apply
258 testrebase " --merge" .git/rebase-merge
259 testrebase " --interactive" .git/rebase-merge
260
261 test_expect_success 'abort rebase -i with --autostash' '
262         test_when_finished "git reset --hard" &&
263         echo uncommitted-content >file0 &&
264         (
265                 write_script abort-editor.sh <<-\EOF &&
266                         echo >"$1"
267                 EOF
268                 test_set_editor "$(pwd)/abort-editor.sh" &&
269                 test_must_fail git rebase -i --autostash HEAD^ &&
270                 rm -f abort-editor.sh
271         ) &&
272         echo uncommitted-content >expected &&
273         test_cmp expected file0
274 '
275
276 test_expect_success 'restore autostash on editor failure' '
277         test_when_finished "git reset --hard" &&
278         echo uncommitted-content >file0 &&
279         (
280                 test_set_editor "false" &&
281                 test_must_fail git rebase -i --autostash HEAD^
282         ) &&
283         echo uncommitted-content >expected &&
284         test_cmp expected file0
285 '
286
287 test_expect_success 'autostash is saved on editor failure with conflict' '
288         test_when_finished "git reset --hard" &&
289         echo uncommitted-content >file0 &&
290         (
291                 write_script abort-editor.sh <<-\EOF &&
292                         echo conflicting-content >file0
293                         exit 1
294                 EOF
295                 test_set_editor "$(pwd)/abort-editor.sh" &&
296                 test_must_fail git rebase -i --autostash HEAD^ &&
297                 rm -f abort-editor.sh
298         ) &&
299         echo conflicting-content >expected &&
300         test_cmp expected file0 &&
301         git checkout file0 &&
302         git stash pop &&
303         echo uncommitted-content >expected &&
304         test_cmp expected file0
305 '
306
307 test_expect_success 'autostash with dirty submodules' '
308         test_when_finished "git reset --hard && git checkout master" &&
309         git checkout -b with-submodule &&
310         git submodule add ./ sub &&
311         test_tick &&
312         git commit -m add-submodule &&
313         echo changed >sub/file0 &&
314         git rebase -i --autostash HEAD
315 '
316
317 test_expect_success 'branch is left alone when possible' '
318         git checkout -b unchanged-branch &&
319         echo changed >file0 &&
320         git rebase --autostash unchanged-branch &&
321         test changed = "$(cat file0)" &&
322         test unchanged-branch = "$(git rev-parse --abbrev-ref HEAD)"
323 '
324
325 test_expect_success 'never change active branch' '
326         git checkout -b not-the-feature-branch unrelated-onto-branch &&
327         test_when_finished "git reset --hard && git checkout master" &&
328         echo changed >file0 &&
329         git rebase --autostash not-the-feature-branch feature-branch &&
330         test_cmp_rev not-the-feature-branch unrelated-onto-branch
331 '
332
333 test_done