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