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