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 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
47create_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
55create_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
67create_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
77testrebase () {
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
215test_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
226test_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
237testrebase "" .git/rebase-apply
238testrebase " --merge" .git/rebase-merge
239testrebase " --interactive" .git/rebase-merge
240
241test_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
256test_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
267test_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
287test_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
297test_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
305test_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
313test_done