]> git.ipfire.org Git - thirdparty/git.git/blob - t/t2018-checkout-branch.sh
t2018: teach do_checkout() to accept `!` arg
[thirdparty/git.git] / t / t2018-checkout-branch.sh
1 #!/bin/sh
2
3 test_description='checkout'
4
5 . ./test-lib.sh
6
7 # Arguments: [!] <branch> <sha> [<checkout options>]
8 #
9 # Runs "git checkout" to switch to <branch>, testing that
10 #
11 # 1) we are on the specified branch, <branch>;
12 # 2) HEAD is <sha>; if <sha> is not specified, the old HEAD is used.
13 #
14 # If <checkout options> is not specified, "git checkout" is run with -b.
15 #
16 # If the first argument is `!`, "git checkout" is expected to fail when
17 # it is run.
18 do_checkout () {
19 should_fail= &&
20 if test "x$1" = "x!"
21 then
22 should_fail=yes &&
23 shift
24 fi &&
25 exp_branch=$1 &&
26 exp_ref="refs/heads/$exp_branch" &&
27
28 # if <sha> is not specified, use HEAD.
29 exp_sha=${2:-$(git rev-parse --verify HEAD)} &&
30
31 # default options for git checkout: -b
32 if test -z "$3"
33 then
34 opts="-b"
35 else
36 opts="$3"
37 fi
38
39 if test -n "$should_fail"
40 then
41 test_must_fail git checkout $opts $exp_branch $exp_sha
42 else
43 git checkout $opts $exp_branch $exp_sha &&
44 test $exp_ref = $(git rev-parse --symbolic-full-name HEAD) &&
45 test $exp_sha = $(git rev-parse --verify HEAD)
46 fi
47 }
48
49 test_dirty_unmergeable () {
50 test_expect_code 1 git diff --exit-code
51 }
52
53 test_dirty_unmergeable_discards_changes () {
54 git diff --exit-code
55 }
56
57 setup_dirty_unmergeable () {
58 echo >>file1 change2
59 }
60
61 test_dirty_mergeable () {
62 test_expect_code 1 git diff --cached --exit-code
63 }
64
65 test_dirty_mergeable_discards_changes () {
66 git diff --cached --exit-code
67 }
68
69 setup_dirty_mergeable () {
70 echo >file2 file2 &&
71 git add file2
72 }
73
74 test_expect_success 'setup' '
75 test_commit initial file1 &&
76 HEAD1=$(git rev-parse --verify HEAD) &&
77
78 test_commit change1 file1 &&
79 HEAD2=$(git rev-parse --verify HEAD) &&
80
81 git branch -m branch1
82 '
83
84 test_expect_success 'checkout -b to a new branch, set to HEAD' '
85 test_when_finished "
86 git checkout branch1 &&
87 test_might_fail git branch -D branch2" &&
88 do_checkout branch2
89 '
90
91 test_expect_success 'checkout -b to a merge base' '
92 test_when_finished "
93 git checkout branch1 &&
94 test_might_fail git branch -D branch2" &&
95 git checkout -b branch2 branch1...
96 '
97
98 test_expect_success 'checkout -b to a new branch, set to an explicit ref' '
99 test_when_finished "
100 git checkout branch1 &&
101 test_might_fail git branch -D branch2" &&
102 do_checkout branch2 $HEAD1
103 '
104
105 test_expect_success 'checkout -b to a new branch with unmergeable changes fails' '
106 setup_dirty_unmergeable &&
107 do_checkout ! branch2 $HEAD1 &&
108 test_dirty_unmergeable
109 '
110
111 test_expect_success 'checkout -f -b to a new branch with unmergeable changes discards changes' '
112 test_when_finished "
113 git checkout branch1 &&
114 test_might_fail git branch -D branch2" &&
115
116 # still dirty and on branch1
117 do_checkout branch2 $HEAD1 "-f -b" &&
118 test_dirty_unmergeable_discards_changes
119 '
120
121 test_expect_success 'checkout -b to a new branch preserves mergeable changes' '
122 test_when_finished "
123 git reset --hard &&
124 git checkout branch1 &&
125 test_might_fail git branch -D branch2" &&
126
127 setup_dirty_mergeable &&
128 do_checkout branch2 $HEAD1 &&
129 test_dirty_mergeable
130 '
131
132 test_expect_success 'checkout -f -b to a new branch with mergeable changes discards changes' '
133 test_when_finished git reset --hard HEAD &&
134 setup_dirty_mergeable &&
135 do_checkout branch2 $HEAD1 "-f -b" &&
136 test_dirty_mergeable_discards_changes
137 '
138
139 test_expect_success 'checkout -b to an existing branch fails' '
140 test_when_finished git reset --hard HEAD &&
141 do_checkout ! branch2 $HEAD2
142 '
143
144 test_expect_success 'checkout -b to @{-1} fails with the right branch name' '
145 git checkout branch1 &&
146 git checkout branch2 &&
147 echo >expect "fatal: A branch named '\''branch1'\'' already exists." &&
148 test_must_fail git checkout -b @{-1} 2>actual &&
149 test_i18ncmp expect actual
150 '
151
152 test_expect_success 'checkout -B to an existing branch resets branch to HEAD' '
153 git checkout branch1 &&
154
155 do_checkout branch2 "" -B
156 '
157
158 test_expect_success 'checkout -B to a merge base' '
159 git checkout branch1 &&
160
161 git checkout -B branch2 branch1...
162 '
163
164 test_expect_success 'checkout -B to an existing branch from detached HEAD resets branch to HEAD' '
165 git checkout $(git rev-parse --verify HEAD) &&
166
167 do_checkout branch2 "" -B
168 '
169
170 test_expect_success 'checkout -B to an existing branch with an explicit ref resets branch to that ref' '
171 git checkout branch1 &&
172
173 do_checkout branch2 $HEAD1 -B
174 '
175
176 test_expect_success 'checkout -B to an existing branch with unmergeable changes fails' '
177 git checkout branch1 &&
178
179 setup_dirty_unmergeable &&
180 do_checkout ! branch2 $HEAD1 -B &&
181 test_dirty_unmergeable
182 '
183
184 test_expect_success 'checkout -f -B to an existing branch with unmergeable changes discards changes' '
185 # still dirty and on branch1
186 do_checkout branch2 $HEAD1 "-f -B" &&
187 test_dirty_unmergeable_discards_changes
188 '
189
190 test_expect_success 'checkout -B to an existing branch preserves mergeable changes' '
191 test_when_finished git reset --hard &&
192 git checkout branch1 &&
193
194 setup_dirty_mergeable &&
195 do_checkout branch2 $HEAD1 -B &&
196 test_dirty_mergeable
197 '
198
199 test_expect_success 'checkout -f -B to an existing branch with mergeable changes discards changes' '
200 git checkout branch1 &&
201
202 setup_dirty_mergeable &&
203 do_checkout branch2 $HEAD1 "-f -B" &&
204 test_dirty_mergeable_discards_changes
205 '
206
207 test_expect_success 'checkout -b <describe>' '
208 git tag -f -m "First commit" initial initial &&
209 git checkout -f change1 &&
210 name=$(git describe) &&
211 git checkout -b $name &&
212 git diff --exit-code change1 &&
213 echo "refs/heads/$name" >expect &&
214 git symbolic-ref HEAD >actual &&
215 test_cmp expect actual
216 '
217
218 test_expect_success 'checkout -B to the current branch works' '
219 git checkout branch1 &&
220 git checkout -B branch1-scratch &&
221
222 setup_dirty_mergeable &&
223 git checkout -B branch1-scratch initial &&
224 test_dirty_mergeable
225 '
226
227 test_expect_success 'checkout -b after clone --no-checkout does a checkout of HEAD' '
228 git init src &&
229 test_commit -C src a &&
230 rev="$(git -C src rev-parse HEAD)" &&
231 git clone --no-checkout src dest &&
232 git -C dest checkout "$rev" -b branch &&
233 test_path_is_file dest/a.t
234 '
235
236 test_done