Merge branch 'master' of github.com:linusboyle/git
[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 '
35
36 create_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
47 create_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         Successfully rebased and updated refs/heads/rebased-feature-branch.
53         EOF
54 }
55
56 create_expected_success_merge () {
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         Merging unrelated-onto-branch with HEAD~1
62         Merging:
63         $(git rev-parse --short unrelated-onto-branch) unrelated commit
64         $(git rev-parse --short feature-branch^) second commit
65         found 1 common ancestor:
66         $(git rev-parse --short feature-branch~2) initial commit
67         [detached HEAD $(git rev-parse --short rebased-feature-branch~1)] second commit
68          Author: A U Thor <author@example.com>
69          Date: Thu Apr 7 15:14:13 2005 -0700
70          2 files changed, 2 insertions(+)
71          create mode 100644 file1
72          create mode 100644 file2
73         Committed: 0001 second commit
74         Merging unrelated-onto-branch with HEAD~0
75         Merging:
76         $(git rev-parse --short rebased-feature-branch~1) second commit
77         $(git rev-parse --short feature-branch) third commit
78         found 1 common ancestor:
79         $(git rev-parse --short feature-branch~1) second commit
80         [detached HEAD $(git rev-parse --short rebased-feature-branch)] third commit
81          Author: A U Thor <author@example.com>
82          Date: Thu Apr 7 15:15:13 2005 -0700
83          1 file changed, 1 insertion(+)
84          create mode 100644 file3
85         Committed: 0002 third commit
86         All done.
87         Applied autostash.
88         EOF
89 }
90
91 create_expected_failure_am () {
92         cat >expected <<-EOF
93         $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
94         HEAD is now at $(git rev-parse --short feature-branch) third commit
95         First, rewinding head to replay your work on top of it...
96         Applying: second commit
97         Applying: third commit
98         Applying autostash resulted in conflicts.
99         Your changes are safe in the stash.
100         You can run "git stash pop" or "git stash drop" at any time.
101         EOF
102 }
103
104 create_expected_failure_interactive () {
105         q_to_cr >expected <<-EOF
106         $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
107         HEAD is now at $(git rev-parse --short feature-branch) third commit
108         Rebasing (1/2)QRebasing (2/2)QApplying autostash resulted in conflicts.
109         Your changes are safe in the stash.
110         You can run "git stash pop" or "git stash drop" at any time.
111         Successfully rebased and updated refs/heads/rebased-feature-branch.
112         EOF
113 }
114
115 create_expected_failure_merge () {
116         cat >expected <<-EOF
117         $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
118         HEAD is now at $(git rev-parse --short feature-branch) third commit
119         First, rewinding head to replay your work on top of it...
120         Merging unrelated-onto-branch with HEAD~1
121         Merging:
122         $(git rev-parse --short unrelated-onto-branch) unrelated commit
123         $(git rev-parse --short feature-branch^) second commit
124         found 1 common ancestor:
125         $(git rev-parse --short feature-branch~2) initial commit
126         [detached HEAD $(git rev-parse --short rebased-feature-branch~1)] second commit
127          Author: A U Thor <author@example.com>
128          Date: Thu Apr 7 15:14:13 2005 -0700
129          2 files changed, 2 insertions(+)
130          create mode 100644 file1
131          create mode 100644 file2
132         Committed: 0001 second commit
133         Merging unrelated-onto-branch with HEAD~0
134         Merging:
135         $(git rev-parse --short rebased-feature-branch~1) second commit
136         $(git rev-parse --short feature-branch) third commit
137         found 1 common ancestor:
138         $(git rev-parse --short feature-branch~1) second commit
139         [detached HEAD $(git rev-parse --short rebased-feature-branch)] third commit
140          Author: A U Thor <author@example.com>
141          Date: Thu Apr 7 15:15:13 2005 -0700
142          1 file changed, 1 insertion(+)
143          create mode 100644 file3
144         Committed: 0002 third commit
145         All done.
146         Applying autostash resulted in conflicts.
147         Your changes are safe in the stash.
148         You can run "git stash pop" or "git stash drop" at any time.
149         EOF
150 }
151
152 testrebase () {
153         type=$1
154         dotest=$2
155
156         test_expect_success "rebase$type: dirty worktree, --no-autostash" '
157                 test_config rebase.autostash true &&
158                 git reset --hard &&
159                 git checkout -b rebased-feature-branch feature-branch &&
160                 test_when_finished git branch -D rebased-feature-branch &&
161                 test_when_finished git checkout feature-branch &&
162                 echo dirty >>file3 &&
163                 test_must_fail git rebase$type --no-autostash unrelated-onto-branch
164         '
165
166         test_expect_success "rebase$type: dirty worktree, non-conflicting rebase" '
167                 test_config rebase.autostash true &&
168                 git reset --hard &&
169                 git checkout -b rebased-feature-branch feature-branch &&
170                 echo dirty >>file3 &&
171                 git rebase$type unrelated-onto-branch >actual 2>&1 &&
172                 grep unrelated file4 &&
173                 grep dirty file3 &&
174                 git checkout feature-branch
175         '
176
177         test_expect_success "rebase$type --autostash: check output" '
178                 test_when_finished git branch -D rebased-feature-branch &&
179                 suffix=${type#\ --} && suffix=${suffix:-am} &&
180                 create_expected_success_$suffix &&
181                 test_i18ncmp expected actual
182         '
183
184         test_expect_success "rebase$type: dirty index, non-conflicting rebase" '
185                 test_config rebase.autostash true &&
186                 git reset --hard &&
187                 git checkout -b rebased-feature-branch feature-branch &&
188                 test_when_finished git branch -D rebased-feature-branch &&
189                 echo dirty >>file3 &&
190                 git add file3 &&
191                 git rebase$type unrelated-onto-branch &&
192                 grep unrelated file4 &&
193                 grep dirty file3 &&
194                 git checkout feature-branch
195         '
196
197         test_expect_success "rebase$type: conflicting rebase" '
198                 test_config rebase.autostash true &&
199                 git reset --hard &&
200                 git checkout -b rebased-feature-branch feature-branch &&
201                 test_when_finished git branch -D rebased-feature-branch &&
202                 echo dirty >>file3 &&
203                 test_must_fail git rebase$type related-onto-branch &&
204                 test_path_is_file $dotest/autostash &&
205                 test_path_is_missing file3 &&
206                 rm -rf $dotest &&
207                 git reset --hard &&
208                 git checkout feature-branch
209         '
210
211         test_expect_success "rebase$type: --continue" '
212                 test_config rebase.autostash true &&
213                 git reset --hard &&
214                 git checkout -b rebased-feature-branch feature-branch &&
215                 test_when_finished git branch -D rebased-feature-branch &&
216                 echo dirty >>file3 &&
217                 test_must_fail git rebase$type related-onto-branch &&
218                 test_path_is_file $dotest/autostash &&
219                 test_path_is_missing file3 &&
220                 echo "conflicting-plus-goodbye" >file2 &&
221                 git add file2 &&
222                 git rebase --continue &&
223                 test_path_is_missing $dotest/autostash &&
224                 grep dirty file3 &&
225                 git checkout feature-branch
226         '
227
228         test_expect_success "rebase$type: --skip" '
229                 test_config rebase.autostash true &&
230                 git reset --hard &&
231                 git checkout -b rebased-feature-branch feature-branch &&
232                 test_when_finished git branch -D rebased-feature-branch &&
233                 echo dirty >>file3 &&
234                 test_must_fail git rebase$type related-onto-branch &&
235                 test_path_is_file $dotest/autostash &&
236                 test_path_is_missing file3 &&
237                 git rebase --skip &&
238                 test_path_is_missing $dotest/autostash &&
239                 grep dirty file3 &&
240                 git checkout feature-branch
241         '
242
243         test_expect_success "rebase$type: --abort" '
244                 test_config rebase.autostash true &&
245                 git reset --hard &&
246                 git checkout -b rebased-feature-branch feature-branch &&
247                 test_when_finished git branch -D rebased-feature-branch &&
248                 echo dirty >>file3 &&
249                 test_must_fail git rebase$type related-onto-branch &&
250                 test_path_is_file $dotest/autostash &&
251                 test_path_is_missing file3 &&
252                 git rebase --abort &&
253                 test_path_is_missing $dotest/autostash &&
254                 grep dirty file3 &&
255                 git checkout feature-branch
256         '
257
258         test_expect_success "rebase$type: non-conflicting rebase, conflicting stash" '
259                 test_config rebase.autostash true &&
260                 git reset --hard &&
261                 git checkout -b rebased-feature-branch feature-branch &&
262                 echo dirty >file4 &&
263                 git add file4 &&
264                 git rebase$type unrelated-onto-branch >actual 2>&1 &&
265                 test_path_is_missing $dotest &&
266                 git reset --hard &&
267                 grep unrelated file4 &&
268                 ! grep dirty file4 &&
269                 git checkout feature-branch &&
270                 git stash pop &&
271                 grep dirty file4
272         '
273
274         test_expect_success "rebase$type: check output with conflicting stash" '
275                 test_when_finished git branch -D rebased-feature-branch &&
276                 suffix=${type#\ --} && suffix=${suffix:-am} &&
277                 create_expected_failure_$suffix &&
278                 test_i18ncmp expected actual
279         '
280 }
281
282 test_expect_success "rebase: fast-forward rebase" '
283         test_config rebase.autostash true &&
284         git reset --hard &&
285         git checkout -b behind-feature-branch feature-branch~1 &&
286         test_when_finished git branch -D behind-feature-branch &&
287         echo dirty >>file1 &&
288         git rebase feature-branch &&
289         grep dirty file1 &&
290         git checkout feature-branch
291 '
292
293 test_expect_success "rebase: noop rebase" '
294         test_config rebase.autostash true &&
295         git reset --hard &&
296         git checkout -b same-feature-branch feature-branch &&
297         test_when_finished git branch -D same-feature-branch &&
298         echo dirty >>file1 &&
299         git rebase feature-branch &&
300         grep dirty file1 &&
301         git checkout feature-branch
302 '
303
304 testrebase "" .git/rebase-apply
305 testrebase " --merge" .git/rebase-merge
306 testrebase " --interactive" .git/rebase-merge
307
308 test_expect_success 'abort rebase -i with --autostash' '
309         test_when_finished "git reset --hard" &&
310         echo uncommitted-content >file0 &&
311         (
312                 write_script abort-editor.sh <<-\EOF &&
313                         echo >"$1"
314                 EOF
315                 test_set_editor "$(pwd)/abort-editor.sh" &&
316                 test_must_fail git rebase -i --autostash HEAD^ &&
317                 rm -f abort-editor.sh
318         ) &&
319         echo uncommitted-content >expected &&
320         test_cmp expected file0
321 '
322
323 test_expect_success 'restore autostash on editor failure' '
324         test_when_finished "git reset --hard" &&
325         echo uncommitted-content >file0 &&
326         (
327                 test_set_editor "false" &&
328                 test_must_fail git rebase -i --autostash HEAD^
329         ) &&
330         echo uncommitted-content >expected &&
331         test_cmp expected file0
332 '
333
334 test_expect_success 'autostash is saved on editor failure with conflict' '
335         test_when_finished "git reset --hard" &&
336         echo uncommitted-content >file0 &&
337         (
338                 write_script abort-editor.sh <<-\EOF &&
339                         echo conflicting-content >file0
340                         exit 1
341                 EOF
342                 test_set_editor "$(pwd)/abort-editor.sh" &&
343                 test_must_fail git rebase -i --autostash HEAD^ &&
344                 rm -f abort-editor.sh
345         ) &&
346         echo conflicting-content >expected &&
347         test_cmp expected file0 &&
348         git checkout file0 &&
349         git stash pop &&
350         echo uncommitted-content >expected &&
351         test_cmp expected file0
352 '
353
354 test_expect_success 'autostash with dirty submodules' '
355         test_when_finished "git reset --hard && git checkout master" &&
356         git checkout -b with-submodule &&
357         git submodule add ./ sub &&
358         test_tick &&
359         git commit -m add-submodule &&
360         echo changed >sub/file0 &&
361         git rebase -i --autostash HEAD
362 '
363
364 test_expect_success 'branch is left alone when possible' '
365         git checkout -b unchanged-branch &&
366         echo changed >file0 &&
367         git rebase --autostash unchanged-branch &&
368         test changed = "$(cat file0)" &&
369         test unchanged-branch = "$(git rev-parse --abbrev-ref HEAD)"
370 '
371
372 test_done