Merge branch 'js/vreportf-wo-buffering'
[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_am () {
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_interactive () {
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_am () {
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_interactive () {
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:-am} &&
105                 if test ${suffix} = "merge"; then
106                         suffix=interactive
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: non-conflicting rebase, conflicting stash" '
188                 test_config rebase.autostash true &&
189                 git reset --hard &&
190                 git checkout -b rebased-feature-branch feature-branch &&
191                 echo dirty >file4 &&
192                 git add file4 &&
193                 git rebase$type unrelated-onto-branch >actual 2>&1 &&
194                 test_path_is_missing $dotest &&
195                 git reset --hard &&
196                 grep unrelated file4 &&
197                 ! grep dirty file4 &&
198                 git checkout feature-branch &&
199                 git stash pop &&
200                 grep dirty file4
201         '
202
203         test_expect_success "rebase$type: check output with conflicting stash" '
204                 test_when_finished git branch -D rebased-feature-branch &&
205                 suffix=${type#\ --} && suffix=${suffix:-am} &&
206                 if test ${suffix} = "merge"; then
207                         suffix=interactive
208                 fi &&
209                 create_expected_failure_$suffix &&
210                 sed "$remove_progress_re" <actual >actual2 &&
211                 test_i18ncmp expected actual2
212         '
213 }
214
215 test_expect_success "rebase: fast-forward rebase" '
216         test_config rebase.autostash true &&
217         git reset --hard &&
218         git checkout -b behind-feature-branch feature-branch~1 &&
219         test_when_finished git branch -D behind-feature-branch &&
220         echo dirty >>file1 &&
221         git rebase feature-branch &&
222         grep dirty file1 &&
223         git checkout feature-branch
224 '
225
226 test_expect_success "rebase: noop rebase" '
227         test_config rebase.autostash true &&
228         git reset --hard &&
229         git checkout -b same-feature-branch feature-branch &&
230         test_when_finished git branch -D same-feature-branch &&
231         echo dirty >>file1 &&
232         git rebase feature-branch &&
233         grep dirty file1 &&
234         git checkout feature-branch
235 '
236
237 testrebase "" .git/rebase-apply
238 testrebase " --merge" .git/rebase-merge
239 testrebase " --interactive" .git/rebase-merge
240
241 test_expect_success 'abort rebase -i with --autostash' '
242         test_when_finished "git reset --hard" &&
243         echo uncommitted-content >file0 &&
244         (
245                 write_script abort-editor.sh <<-\EOF &&
246                         echo >"$1"
247                 EOF
248                 test_set_editor "$(pwd)/abort-editor.sh" &&
249                 test_must_fail git rebase -i --autostash HEAD^ &&
250                 rm -f abort-editor.sh
251         ) &&
252         echo uncommitted-content >expected &&
253         test_cmp expected file0
254 '
255
256 test_expect_success 'restore autostash on editor failure' '
257         test_when_finished "git reset --hard" &&
258         echo uncommitted-content >file0 &&
259         (
260                 test_set_editor "false" &&
261                 test_must_fail git rebase -i --autostash HEAD^
262         ) &&
263         echo uncommitted-content >expected &&
264         test_cmp expected file0
265 '
266
267 test_expect_success 'autostash is saved on editor failure with conflict' '
268         test_when_finished "git reset --hard" &&
269         echo uncommitted-content >file0 &&
270         (
271                 write_script abort-editor.sh <<-\EOF &&
272                         echo conflicting-content >file0
273                         exit 1
274                 EOF
275                 test_set_editor "$(pwd)/abort-editor.sh" &&
276                 test_must_fail git rebase -i --autostash HEAD^ &&
277                 rm -f abort-editor.sh
278         ) &&
279         echo conflicting-content >expected &&
280         test_cmp expected file0 &&
281         git checkout file0 &&
282         git stash pop &&
283         echo uncommitted-content >expected &&
284         test_cmp expected file0
285 '
286
287 test_expect_success 'autostash with dirty submodules' '
288         test_when_finished "git reset --hard && git checkout master" &&
289         git checkout -b with-submodule &&
290         git submodule add ./ sub &&
291         test_tick &&
292         git commit -m add-submodule &&
293         echo changed >sub/file0 &&
294         git rebase -i --autostash HEAD
295 '
296
297 test_expect_success 'branch is left alone when possible' '
298         git checkout -b unchanged-branch &&
299         echo changed >file0 &&
300         git rebase --autostash unchanged-branch &&
301         test changed = "$(cat file0)" &&
302         test unchanged-branch = "$(git rev-parse --abbrev-ref HEAD)"
303 '
304
305 test_expect_success 'never change active branch' '
306         git checkout -b not-the-feature-branch unrelated-onto-branch &&
307         test_when_finished "git reset --hard && git checkout master" &&
308         echo changed >file0 &&
309         git rebase --autostash not-the-feature-branch feature-branch &&
310         test_cmp_rev not-the-feature-branch unrelated-onto-branch
311 '
312
313 test_done