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