]>
Commit | Line | Data |
---|---|---|
39ac7a7d TRC |
1 | #!/bin/sh |
2 | ||
f1842ff5 | 3 | test_description='checkout' |
39ac7a7d | 4 | |
ead74601 | 5 | TEST_CREATE_REPO_NO_TEMPLATE=1 |
b5fcb1c0 | 6 | TEST_PASSES_SANITIZE_LEAK=true |
39ac7a7d TRC |
7 | . ./test-lib.sh |
8 | ||
4a6f11fd | 9 | # Arguments: [!] <branch> <oid> [<checkout options>] |
39ac7a7d TRC |
10 | # |
11 | # Runs "git checkout" to switch to <branch>, testing that | |
12 | # | |
13 | # 1) we are on the specified branch, <branch>; | |
4a6f11fd | 14 | # 2) HEAD is <oid>; if <oid> is not specified, the old HEAD is used. |
39ac7a7d TRC |
15 | # |
16 | # If <checkout options> is not specified, "git checkout" is run with -b. | |
30c03676 DL |
17 | # |
18 | # If the first argument is `!`, "git checkout" is expected to fail when | |
19 | # it is run. | |
7ffb5461 | 20 | do_checkout () { |
30c03676 DL |
21 | should_fail= && |
22 | if test "x$1" = "x!" | |
23 | then | |
24 | should_fail=yes && | |
25 | shift | |
26 | fi && | |
39ac7a7d TRC |
27 | exp_branch=$1 && |
28 | exp_ref="refs/heads/$exp_branch" && | |
29 | ||
4a6f11fd DL |
30 | # if <oid> is not specified, use HEAD. |
31 | exp_oid=${2:-$(git rev-parse --verify HEAD)} && | |
39ac7a7d TRC |
32 | |
33 | # default options for git checkout: -b | |
5020f680 DL |
34 | if test -z "$3" |
35 | then | |
39ac7a7d TRC |
36 | opts="-b" |
37 | else | |
38 | opts="$3" | |
39 | fi | |
40 | ||
30c03676 DL |
41 | if test -n "$should_fail" |
42 | then | |
4a6f11fd | 43 | test_must_fail git checkout $opts $exp_branch $exp_oid |
30c03676 | 44 | else |
4a6f11fd | 45 | git checkout $opts $exp_branch $exp_oid && |
62e80fcb DL |
46 | echo "$exp_ref" >ref.expect && |
47 | git rev-parse --symbolic-full-name HEAD >ref.actual && | |
48 | test_cmp ref.expect ref.actual && | |
4a6f11fd DL |
49 | echo "$exp_oid" >oid.expect && |
50 | git rev-parse --verify HEAD >oid.actual && | |
51 | test_cmp oid.expect oid.actual | |
30c03676 | 52 | fi |
39ac7a7d TRC |
53 | } |
54 | ||
7ffb5461 | 55 | test_dirty_unmergeable () { |
40caa536 DL |
56 | test_expect_code 1 git diff --exit-code |
57 | } | |
58 | ||
59 | test_dirty_unmergeable_discards_changes () { | |
60 | git diff --exit-code | |
39ac7a7d TRC |
61 | } |
62 | ||
7ffb5461 | 63 | setup_dirty_unmergeable () { |
39ac7a7d TRC |
64 | echo >>file1 change2 |
65 | } | |
66 | ||
7ffb5461 | 67 | test_dirty_mergeable () { |
40caa536 DL |
68 | test_expect_code 1 git diff --cached --exit-code |
69 | } | |
70 | ||
71 | test_dirty_mergeable_discards_changes () { | |
72 | git diff --cached --exit-code | |
39ac7a7d TRC |
73 | } |
74 | ||
7ffb5461 | 75 | setup_dirty_mergeable () { |
39ac7a7d TRC |
76 | echo >file2 file2 && |
77 | git add file2 | |
78 | } | |
79 | ||
80 | test_expect_success 'setup' ' | |
81 | test_commit initial file1 && | |
82 | HEAD1=$(git rev-parse --verify HEAD) && | |
83 | ||
84 | test_commit change1 file1 && | |
85 | HEAD2=$(git rev-parse --verify HEAD) && | |
86 | ||
87 | git branch -m branch1 | |
88 | ' | |
89 | ||
519947b6 JH |
90 | test_expect_success 'checkout a branch without refs/heads/* prefix' ' |
91 | git clone --no-tags . repo-odd-prefix && | |
92 | ( | |
93 | cd repo-odd-prefix && | |
94 | ||
95 | origin=$(git symbolic-ref refs/remotes/origin/HEAD) && | |
96 | git symbolic-ref refs/heads/a-branch "$origin" && | |
97 | ||
98 | git checkout -f a-branch && | |
99 | git checkout -f a-branch | |
100 | ) | |
101 | ' | |
102 | ||
39ac7a7d | 103 | test_expect_success 'checkout -b to a new branch, set to HEAD' ' |
27434bf0 DL |
104 | test_when_finished " |
105 | git checkout branch1 && | |
106 | test_might_fail git branch -D branch2" && | |
39ac7a7d TRC |
107 | do_checkout branch2 |
108 | ' | |
109 | ||
e3d6539d DL |
110 | test_expect_success 'checkout -b to a merge base' ' |
111 | test_when_finished " | |
112 | git checkout branch1 && | |
113 | test_might_fail git branch -D branch2" && | |
114 | git checkout -b branch2 branch1... | |
115 | ' | |
116 | ||
39ac7a7d | 117 | test_expect_success 'checkout -b to a new branch, set to an explicit ref' ' |
27434bf0 DL |
118 | test_when_finished " |
119 | git checkout branch1 && | |
120 | test_might_fail git branch -D branch2" && | |
39ac7a7d TRC |
121 | do_checkout branch2 $HEAD1 |
122 | ' | |
123 | ||
124 | test_expect_success 'checkout -b to a new branch with unmergeable changes fails' ' | |
39ac7a7d | 125 | setup_dirty_unmergeable && |
30c03676 | 126 | do_checkout ! branch2 $HEAD1 && |
39ac7a7d TRC |
127 | test_dirty_unmergeable |
128 | ' | |
129 | ||
130 | test_expect_success 'checkout -f -b to a new branch with unmergeable changes discards changes' ' | |
27434bf0 DL |
131 | test_when_finished " |
132 | git checkout branch1 && | |
133 | test_might_fail git branch -D branch2" && | |
134 | ||
39ac7a7d TRC |
135 | # still dirty and on branch1 |
136 | do_checkout branch2 $HEAD1 "-f -b" && | |
40caa536 | 137 | test_dirty_unmergeable_discards_changes |
39ac7a7d TRC |
138 | ' |
139 | ||
140 | test_expect_success 'checkout -b to a new branch preserves mergeable changes' ' | |
27434bf0 DL |
141 | test_when_finished " |
142 | git reset --hard && | |
143 | git checkout branch1 && | |
144 | test_might_fail git branch -D branch2" && | |
39ac7a7d TRC |
145 | |
146 | setup_dirty_mergeable && | |
147 | do_checkout branch2 $HEAD1 && | |
148 | test_dirty_mergeable | |
149 | ' | |
150 | ||
151 | test_expect_success 'checkout -f -b to a new branch with mergeable changes discards changes' ' | |
27434bf0 | 152 | test_when_finished git reset --hard HEAD && |
39ac7a7d TRC |
153 | setup_dirty_mergeable && |
154 | do_checkout branch2 $HEAD1 "-f -b" && | |
40caa536 | 155 | test_dirty_mergeable_discards_changes |
39ac7a7d TRC |
156 | ' |
157 | ||
158 | test_expect_success 'checkout -b to an existing branch fails' ' | |
27434bf0 | 159 | test_when_finished git reset --hard HEAD && |
30c03676 | 160 | do_checkout ! branch2 $HEAD2 |
39ac7a7d TRC |
161 | ' |
162 | ||
587a9ee7 | 163 | test_expect_success 'checkout -b to @{-1} fails with the right branch name' ' |
587a9ee7 CI |
164 | git checkout branch1 && |
165 | git checkout branch2 && | |
7435e7e2 | 166 | echo >expect "fatal: a branch named '\''branch1'\'' already exists" && |
587a9ee7 | 167 | test_must_fail git checkout -b @{-1} 2>actual && |
1108cea7 | 168 | test_cmp expect actual |
587a9ee7 CI |
169 | ' |
170 | ||
02ac9837 TRC |
171 | test_expect_success 'checkout -B to an existing branch resets branch to HEAD' ' |
172 | git checkout branch1 && | |
173 | ||
174 | do_checkout branch2 "" -B | |
175 | ' | |
176 | ||
e3d6539d DL |
177 | test_expect_success 'checkout -B to a merge base' ' |
178 | git checkout branch1 && | |
179 | ||
180 | git checkout -B branch2 branch1... | |
181 | ' | |
182 | ||
cc701483 | 183 | test_expect_success 'checkout -B to an existing branch from detached HEAD resets branch to HEAD' ' |
62e80fcb DL |
184 | head=$(git rev-parse --verify HEAD) && |
185 | git checkout "$head" && | |
cc701483 TRC |
186 | |
187 | do_checkout branch2 "" -B | |
188 | ' | |
189 | ||
02ac9837 TRC |
190 | test_expect_success 'checkout -B to an existing branch with an explicit ref resets branch to that ref' ' |
191 | git checkout branch1 && | |
192 | ||
193 | do_checkout branch2 $HEAD1 -B | |
194 | ' | |
195 | ||
196 | test_expect_success 'checkout -B to an existing branch with unmergeable changes fails' ' | |
197 | git checkout branch1 && | |
198 | ||
199 | setup_dirty_unmergeable && | |
30c03676 | 200 | do_checkout ! branch2 $HEAD1 -B && |
02ac9837 TRC |
201 | test_dirty_unmergeable |
202 | ' | |
203 | ||
204 | test_expect_success 'checkout -f -B to an existing branch with unmergeable changes discards changes' ' | |
205 | # still dirty and on branch1 | |
206 | do_checkout branch2 $HEAD1 "-f -B" && | |
40caa536 | 207 | test_dirty_unmergeable_discards_changes |
02ac9837 TRC |
208 | ' |
209 | ||
210 | test_expect_success 'checkout -B to an existing branch preserves mergeable changes' ' | |
27434bf0 | 211 | test_when_finished git reset --hard && |
02ac9837 TRC |
212 | git checkout branch1 && |
213 | ||
214 | setup_dirty_mergeable && | |
215 | do_checkout branch2 $HEAD1 -B && | |
216 | test_dirty_mergeable | |
217 | ' | |
218 | ||
219 | test_expect_success 'checkout -f -B to an existing branch with mergeable changes discards changes' ' | |
02ac9837 TRC |
220 | git checkout branch1 && |
221 | ||
222 | setup_dirty_mergeable && | |
223 | do_checkout branch2 $HEAD1 "-f -B" && | |
40caa536 | 224 | test_dirty_mergeable_discards_changes |
02ac9837 TRC |
225 | ' |
226 | ||
c17b2294 JH |
227 | test_expect_success 'checkout -b <describe>' ' |
228 | git tag -f -m "First commit" initial initial && | |
229 | git checkout -f change1 && | |
230 | name=$(git describe) && | |
231 | git checkout -b $name && | |
232 | git diff --exit-code change1 && | |
233 | echo "refs/heads/$name" >expect && | |
234 | git symbolic-ref HEAD >actual && | |
235 | test_cmp expect actual | |
236 | ' | |
237 | ||
39bd6f72 | 238 | test_expect_success 'checkout -B to the current branch works' ' |
55c4a673 | 239 | git checkout branch1 && |
39bd6f72 JN |
240 | git checkout -B branch1-scratch && |
241 | ||
55c4a673 | 242 | setup_dirty_mergeable && |
39bd6f72 JN |
243 | git checkout -B branch1-scratch initial && |
244 | test_dirty_mergeable | |
55c4a673 CI |
245 | ' |
246 | ||
8424bfd4 | 247 | test_expect_success 'checkout -b after clone --no-checkout does a checkout of HEAD' ' |
91e3d7ca BP |
248 | git init src && |
249 | test_commit -C src a && | |
250 | rev="$(git -C src rev-parse HEAD)" && | |
251 | git clone --no-checkout src dest && | |
252 | git -C dest checkout "$rev" -b branch && | |
253 | test_path_is_file dest/a.t | |
254 | ' | |
255 | ||
681c637b EN |
256 | test_expect_success 'checkout -b to a new branch preserves mergeable changes despite sparse-checkout' ' |
257 | test_when_finished " | |
258 | git reset --hard && | |
259 | git checkout branch1-scratch && | |
260 | test_might_fail git branch -D branch3 && | |
261 | git config core.sparseCheckout false && | |
ead74601 | 262 | rm -rf .git/info" && |
681c637b EN |
263 | |
264 | test_commit file2 && | |
265 | ||
266 | echo stuff >>file1 && | |
ead74601 | 267 | mkdir .git/info && |
681c637b EN |
268 | echo file2 >.git/info/sparse-checkout && |
269 | git config core.sparseCheckout true && | |
270 | ||
271 | CURHEAD=$(git rev-parse HEAD) && | |
272 | do_checkout branch3 $CURHEAD && | |
273 | ||
274 | echo file1 >expect && | |
275 | git diff --name-only >actual && | |
276 | test_cmp expect actual | |
277 | ' | |
278 | ||
16ab794b RS |
279 | test_expect_success 'checkout -b rejects an invalid start point' ' |
280 | test_must_fail git checkout -b branch4 file1 2>err && | |
6789275d | 281 | test_grep "is not a commit" err |
16ab794b RS |
282 | ' |
283 | ||
bb2198fb | 284 | test_expect_success 'checkout -b rejects an extra path argument' ' |
16ab794b | 285 | test_must_fail git checkout -b branch5 branch1 file1 2>err && |
6789275d | 286 | test_grep "Cannot update paths and switch to branch" err |
16ab794b RS |
287 | ' |
288 | ||
39ac7a7d | 289 | test_done |