1#!/bin/sh
2#
3# Copyright (c) 2013 Ramkumar Ramachandra
4#
5
6test_description='git rebase --autostash tests'
7. ./test-lib.sh
8
9test_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
37create_expected_success_am () {
38 cat >expected <<-EOF
39 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
40 HEAD is now at $(git rev-parse --short feature-branch) third commit
41 First, rewinding head to replay your work on top of it...
42 Applying: second commit
43 Applying: third commit
44 Applied autostash.
45 EOF
46}
47
48create_expected_success_interactive () {
49 q_to_cr >expected <<-EOF
50 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
51 HEAD is now at $(git rev-parse --short feature-branch) third commit
52 Applied autostash.
53 Successfully rebased and updated refs/heads/rebased-feature-branch.
54 EOF
55}
56
57create_expected_failure_am () {
58 cat >expected <<-EOF
59 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
60 HEAD is now at $(git rev-parse --short feature-branch) third commit
61 First, rewinding head to replay your work on top of it...
62 Applying: second commit
63 Applying: third commit
64 Applying autostash resulted in conflicts.
65 Your changes are safe in the stash.
66 You can run "git stash pop" or "git stash drop" at any time.
67 EOF
68}
69
70create_expected_failure_interactive () {
71 cat >expected <<-EOF
72 $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
73 HEAD is now at $(git rev-parse --short feature-branch) third commit
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
79}
80
81testrebase () {
82 type=$1
83 dotest=$2
84
85 test_expect_success "rebase$type: dirty worktree, --no-autostash" '
86 test_config rebase.autostash true &&
87 git reset --hard &&
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 &&
91 echo dirty >>file3 &&
92 test_must_fail git rebase$type --no-autostash unrelated-onto-branch
93 '
94
95 test_expect_success "rebase$type: dirty worktree, non-conflicting rebase" '
96 test_config rebase.autostash true &&
97 git reset --hard &&
98 git checkout -b rebased-feature-branch feature-branch &&
99 echo dirty >>file3 &&
100 git rebase$type unrelated-onto-branch >actual 2>&1 &&
101 grep unrelated file4 &&
102 grep dirty file3 &&
103 git checkout feature-branch
104 '
105
106 test_expect_success "rebase$type --autostash: check output" '
107 test_when_finished git branch -D rebased-feature-branch &&
108 suffix=${type#\ --} && suffix=${suffix:-am} &&
109 if test ${suffix} = "merge"; then
110 suffix=interactive
111 fi &&
112 create_expected_success_$suffix &&
113 sed "$remove_progress_re" <actual >actual2 &&
114 test_i18ncmp expected actual2
115 '
116
117 test_expect_success "rebase$type: dirty index, non-conflicting rebase" '
118 test_config rebase.autostash true &&
119 git reset --hard &&
120 git checkout -b rebased-feature-branch feature-branch &&
121 test_when_finished git branch -D rebased-feature-branch &&
122 echo dirty >>file3 &&
123 git add file3 &&
124 git rebase$type unrelated-onto-branch &&
125 grep unrelated file4 &&
126 grep dirty file3 &&
127 git checkout feature-branch
128 '
129
130 test_expect_success "rebase$type: conflicting rebase" '
131 test_config rebase.autostash true &&
132 git reset --hard &&
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 &&
139 rm -rf $dotest &&
140 git reset --hard &&
141 git checkout feature-branch
142 '
143
144 test_expect_success "rebase$type: --continue" '
145 test_config rebase.autostash true &&
146 git reset --hard &&
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 &&
154 git add file2 &&
155 git rebase --continue &&
156 test_path_is_missing $dotest/autostash &&
157 grep dirty file3 &&
158 git checkout feature-branch
159 '
160
161 test_expect_success "rebase$type: --skip" '
162 test_config rebase.autostash true &&
163 git reset --hard &&
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 &&
170 git rebase --skip &&
171 test_path_is_missing $dotest/autostash &&
172 grep dirty file3 &&
173 git checkout feature-branch
174 '
175
176 test_expect_success "rebase$type: --abort" '
177 test_config rebase.autostash true &&
178 git reset --hard &&
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 &&
187 grep dirty file3 &&
188 git checkout feature-branch
189 '
190
191 test_expect_success "rebase$type: non-conflicting rebase, conflicting stash" '
192 test_config rebase.autostash true &&
193 git reset --hard &&
194 git checkout -b rebased-feature-branch feature-branch &&
195 echo dirty >file4 &&
196 git add file4 &&
197 git rebase$type unrelated-onto-branch >actual 2>&1 &&
198 test_path_is_missing $dotest &&
199 git reset --hard &&
200 grep unrelated file4 &&
201 ! grep dirty file4 &&
202 git checkout feature-branch &&
203 git stash pop &&
204 grep dirty file4
205 '
206
207 test_expect_success "rebase$type: check output with conflicting stash" '
208 test_when_finished git branch -D rebased-feature-branch &&
209 suffix=${type#\ --} && suffix=${suffix:-am} &&
210 if test ${suffix} = "merge"; then
211 suffix=interactive
212 fi &&
213 create_expected_failure_$suffix &&
214 sed "$remove_progress_re" <actual >actual2 &&
215 test_i18ncmp expected actual2
216 '
217}
218
219test_expect_success "rebase: fast-forward rebase" '
220 test_config rebase.autostash true &&
221 git reset --hard &&
222 git checkout -b behind-feature-branch feature-branch~1 &&
223 test_when_finished git branch -D behind-feature-branch &&
224 echo dirty >>file1 &&
225 git rebase feature-branch &&
226 grep dirty file1 &&
227 git checkout feature-branch
228'
229
230test_expect_success "rebase: noop rebase" '
231 test_config rebase.autostash true &&
232 git reset --hard &&
233 git checkout -b same-feature-branch feature-branch &&
234 test_when_finished git branch -D same-feature-branch &&
235 echo dirty >>file1 &&
236 git rebase feature-branch &&
237 grep dirty file1 &&
238 git checkout feature-branch
239'
240
241testrebase "" .git/rebase-apply
242testrebase " --merge" .git/rebase-merge
243testrebase " --interactive" .git/rebase-merge
244
245test_expect_success 'abort rebase -i with --autostash' '
246 test_when_finished "git reset --hard" &&
247 echo uncommitted-content >file0 &&
248 (
249 write_script abort-editor.sh <<-\EOF &&
250 echo >"$1"
251 EOF
252 test_set_editor "$(pwd)/abort-editor.sh" &&
253 test_must_fail git rebase -i --autostash HEAD^ &&
254 rm -f abort-editor.sh
255 ) &&
256 echo uncommitted-content >expected &&
257 test_cmp expected file0
258'
259
260test_expect_success 'restore autostash on editor failure' '
261 test_when_finished "git reset --hard" &&
262 echo uncommitted-content >file0 &&
263 (
264 test_set_editor "false" &&
265 test_must_fail git rebase -i --autostash HEAD^
266 ) &&
267 echo uncommitted-content >expected &&
268 test_cmp expected file0
269'
270
271test_expect_success 'autostash is saved on editor failure with conflict' '
272 test_when_finished "git reset --hard" &&
273 echo uncommitted-content >file0 &&
274 (
275 write_script abort-editor.sh <<-\EOF &&
276 echo conflicting-content >file0
277 exit 1
278 EOF
279 test_set_editor "$(pwd)/abort-editor.sh" &&
280 test_must_fail git rebase -i --autostash HEAD^ &&
281 rm -f abort-editor.sh
282 ) &&
283 echo conflicting-content >expected &&
284 test_cmp expected file0 &&
285 git checkout file0 &&
286 git stash pop &&
287 echo uncommitted-content >expected &&
288 test_cmp expected file0
289'
290
291test_expect_success 'autostash with dirty submodules' '
292 test_when_finished "git reset --hard && git checkout master" &&
293 git checkout -b with-submodule &&
294 git submodule add ./ sub &&
295 test_tick &&
296 git commit -m add-submodule &&
297 echo changed >sub/file0 &&
298 git rebase -i --autostash HEAD
299'
300
301test_expect_success 'branch is left alone when possible' '
302 git checkout -b unchanged-branch &&
303 echo changed >file0 &&
304 git rebase --autostash unchanged-branch &&
305 test changed = "$(cat file0)" &&
306 test unchanged-branch = "$(git rev-parse --abbrev-ref HEAD)"
307'
308
309test_done