Raw
1 #!/bin/sh
2
3 test_description='git branch display tests'
4
5 . ./test-lib.sh
6 . "$TEST_DIRECTORY"/lib-terminal.sh
7
8 test_expect_success 'make commits' '
9 echo content >file &&
10 git add file &&
11 git commit -m one &&
12 git branch -M main &&
13 echo content >>file &&
14 git commit -a -m two
15 '
16
17 test_expect_success 'make branches' '
18 git branch branch-one &&
19 git branch branch-two HEAD^
20 '
21
22 test_expect_success 'make remote branches' '
23 git update-ref refs/remotes/origin/branch-one branch-one &&
24 git update-ref refs/remotes/origin/branch-two branch-two &&
25 git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/branch-one
26 '
27
28 cat >expect <<'EOF'
29 branch-one
30 branch-two
31 * main
32 EOF
33 test_expect_success 'git branch shows local branches' '
34 git branch >actual &&
35 test_cmp expect actual
36 '
37
38 test_expect_success 'git branch --list shows local branches' '
39 git branch --list >actual &&
40 test_cmp expect actual
41 '
42
43 cat >expect <<'EOF'
44 branch-one
45 branch-two
46 EOF
47 test_expect_success 'git branch --list pattern shows matching local branches' '
48 git branch --list branch* >actual &&
49 test_cmp expect actual
50 '
51
52 cat >expect <<'EOF'
53 origin/HEAD -> origin/branch-one
54 origin/branch-one
55 origin/branch-two
56 EOF
57 test_expect_success 'git branch -r shows remote branches' '
58 git branch -r >actual &&
59 test_cmp expect actual &&
60
61 git branch --remotes >actual &&
62 test_cmp expect actual
63 '
64
65 test_expect_success 'git branch --no-remotes is rejected' '
66 test_must_fail git branch --no-remotes 2>err &&
67 test_grep "unknown option .no-remotes." err
68 '
69
70 cat >expect <<'EOF'
71 branch-one
72 branch-two
73 * main
74 remotes/origin/HEAD -> origin/branch-one
75 remotes/origin/branch-one
76 remotes/origin/branch-two
77 EOF
78 test_expect_success 'git branch -a shows local and remote branches' '
79 git branch -a >actual &&
80 test_cmp expect actual &&
81
82 git branch --all >actual &&
83 test_cmp expect actual
84 '
85
86 test_expect_success 'git branch --no-all is rejected' '
87 test_must_fail git branch --no-all 2>err &&
88 test_grep "unknown option .no-all." err
89 '
90
91 cat >expect <<'EOF'
92 two
93 one
94 two
95 EOF
96 test_expect_success 'git branch -v shows branch summaries' '
97 git branch -v >tmp &&
98 awk "{print \$NF}" <tmp >actual &&
99 test_cmp expect actual
100 '
101
102 cat >expect <<'EOF'
103 two
104 one
105 EOF
106 test_expect_success 'git branch --list -v pattern shows branch summaries' '
107 git branch --list -v branch* >tmp &&
108 awk "{print \$NF}" <tmp >actual &&
109 test_cmp expect actual
110 '
111 test_expect_success 'git branch --ignore-case --list -v pattern shows branch summaries' '
112 git branch --list --ignore-case -v BRANCH* >tmp &&
113 awk "{print \$NF}" <tmp >actual &&
114 test_cmp expect actual
115 '
116
117 test_expect_success 'git branch -v pattern does not show branch summaries' '
118 test_must_fail git branch -v branch*
119 '
120
121 test_expect_success 'git branch `--show-current` shows current branch' '
122 cat >expect <<-\EOF &&
123 branch-two
124 EOF
125 git checkout branch-two &&
126 git branch --show-current >actual &&
127 test_cmp expect actual
128 '
129
130 test_expect_success 'git branch `--show-current` is silent when detached HEAD' '
131 git checkout HEAD^0 &&
132 git branch --show-current >actual &&
133 test_must_be_empty actual
134 '
135
136 test_expect_success 'git branch `--show-current` works properly when tag exists' '
137 cat >expect <<-\EOF &&
138 branch-and-tag-name
139 EOF
140 test_when_finished "
141 git checkout branch-one
142 git branch -D branch-and-tag-name
143 " &&
144 git checkout -b branch-and-tag-name &&
145 test_when_finished "git tag -d branch-and-tag-name" &&
146 git tag branch-and-tag-name &&
147 git branch --show-current >actual &&
148 test_cmp expect actual
149 '
150
151 test_expect_success 'git branch `--show-current` works properly with worktrees' '
152 cat >expect <<-\EOF &&
153 branch-one
154 branch-two
155 EOF
156 git checkout branch-one &&
157 test_when_finished "
158 git worktree remove worktree_dir
159 " &&
160 git worktree add worktree_dir branch-two &&
161 {
162 git branch --show-current &&
163 git -C worktree_dir branch --show-current
164 } >actual &&
165 test_cmp expect actual
166 '
167
168 test_expect_success 'git branch shows detached HEAD properly' '
169 cat >expect <<EOF &&
170 * (HEAD detached at $(git rev-parse --short HEAD^0))
171 branch-one
172 branch-two
173 main
174 EOF
175 git checkout HEAD^0 &&
176 git branch >actual &&
177 test_cmp expect actual
178 '
179
180 test_expect_success 'git branch shows detached HEAD properly after checkout --detach' '
181 git checkout main &&
182 cat >expect <<EOF &&
183 * (HEAD detached at $(git rev-parse --short HEAD^0))
184 branch-one
185 branch-two
186 main
187 EOF
188 git checkout --detach &&
189 git branch >actual &&
190 test_cmp expect actual
191 '
192
193 test_expect_success 'git branch shows detached HEAD properly after moving' '
194 cat >expect <<EOF &&
195 * (HEAD detached from $(git rev-parse --short HEAD))
196 branch-one
197 branch-two
198 main
199 EOF
200 git reset --hard HEAD^1 &&
201 git branch >actual &&
202 test_cmp expect actual
203 '
204
205 test_expect_success 'git branch shows detached HEAD properly from tag' '
206 cat >expect <<EOF &&
207 * (HEAD detached at fromtag)
208 branch-one
209 branch-two
210 main
211 EOF
212 git tag fromtag main &&
213 git checkout fromtag &&
214 git branch >actual &&
215 test_cmp expect actual
216 '
217
218 test_expect_success 'git branch shows detached HEAD properly after moving from tag' '
219 cat >expect <<EOF &&
220 * (HEAD detached from fromtag)
221 branch-one
222 branch-two
223 main
224 EOF
225 git reset --hard HEAD^1 &&
226 git branch >actual &&
227 test_cmp expect actual
228 '
229
230 test_expect_success 'git branch `--sort=[-]objectsize` option' '
231 cat >expect <<-\EOF &&
232 * (HEAD detached from fromtag)
233 branch-two
234 branch-one
235 main
236 EOF
237 git branch --sort=objectsize >actual &&
238 test_cmp expect actual &&
239
240 cat >expect <<-\EOF &&
241 * (HEAD detached from fromtag)
242 branch-one
243 main
244 branch-two
245 EOF
246 git branch --sort=-objectsize >actual &&
247 test_cmp expect actual
248 '
249
250 test_expect_success 'git branch `--sort=[-]type` option' '
251 cat >expect <<-\EOF &&
252 * (HEAD detached from fromtag)
253 branch-one
254 branch-two
255 main
256 EOF
257 git branch --sort=type >actual &&
258 test_cmp expect actual &&
259
260 cat >expect <<-\EOF &&
261 * (HEAD detached from fromtag)
262 branch-one
263 branch-two
264 main
265 EOF
266 git branch --sort=-type >actual &&
267 test_cmp expect actual
268 '
269
270 test_expect_success 'git branch `--sort=[-]version:refname` option' '
271 cat >expect <<-\EOF &&
272 * (HEAD detached from fromtag)
273 branch-one
274 branch-two
275 main
276 EOF
277 git branch --sort=version:refname >actual &&
278 test_cmp expect actual &&
279
280 cat >expect <<-\EOF &&
281 * (HEAD detached from fromtag)
282 main
283 branch-two
284 branch-one
285 EOF
286 git branch --sort=-version:refname >actual &&
287 test_cmp expect actual
288 '
289
290 test_expect_success 'git branch --points-at option' '
291 cat >expect <<-\EOF &&
292 branch-one
293 main
294 EOF
295 git branch --points-at=branch-one >actual &&
296 test_cmp expect actual
297 '
298
299 test_expect_success 'ambiguous branch/tag not marked' '
300 git tag ambiguous &&
301 git branch ambiguous &&
302 echo " ambiguous" >expect &&
303 git branch --list ambiguous >actual &&
304 test_cmp expect actual
305 '
306
307 test_expect_success 'local-branch symrefs shortened properly' '
308 git symbolic-ref refs/heads/ref-to-branch refs/heads/branch-one &&
309 git symbolic-ref refs/heads/ref-to-remote refs/remotes/origin/branch-one &&
310 cat >expect <<-\EOF &&
311 ref-to-branch -> branch-one
312 ref-to-remote -> origin/branch-one
313 EOF
314 git branch >actual.raw &&
315 grep ref-to <actual.raw >actual &&
316 test_cmp expect actual
317 '
318
319 test_expect_success 'sort branches, ignore case' '
320 (
321 git init -b main sort-icase &&
322 cd sort-icase &&
323 test_commit initial &&
324 git branch branch-one &&
325 git branch BRANCH-two &&
326 git branch --list | awk "{print \$NF}" >actual &&
327 cat >expected <<-\EOF &&
328 BRANCH-two
329 branch-one
330 main
331 EOF
332 test_cmp expected actual &&
333 git branch --list -i | awk "{print \$NF}" >actual &&
334 cat >expected <<-\EOF &&
335 branch-one
336 BRANCH-two
337 main
338 EOF
339 test_cmp expected actual
340 )
341 '
342
343 test_expect_success 'git branch --format option' '
344 cat >expect <<-\EOF &&
345 Refname is (HEAD detached from fromtag)
346 Refname is refs/heads/ambiguous
347 Refname is refs/heads/branch-one
348 Refname is refs/heads/branch-two
349 Refname is refs/heads/main
350 Refname is refs/heads/ref-to-branch
351 Refname is refs/heads/ref-to-remote
352 EOF
353 git branch --format="Refname is %(refname)" >actual &&
354 test_cmp expect actual
355 '
356
357 test_expect_success 'git branch --format with ahead-behind' '
358 cat >expect <<-\EOF &&
359 (HEAD detached from fromtag) 0 0
360 refs/heads/ambiguous 0 0
361 refs/heads/branch-one 1 0
362 refs/heads/branch-two 0 0
363 refs/heads/main 1 0
364 refs/heads/ref-to-branch 1 0
365 refs/heads/ref-to-remote 1 0
366 EOF
367 git branch --format="%(refname) %(ahead-behind:HEAD)" >actual &&
368 test_cmp expect actual
369 '
370
371 test_expect_success 'git branch `--sort=[-]ahead-behind` option' '
372 cat >expect <<-\EOF &&
373 (HEAD detached from fromtag) 0 0
374 refs/heads/ambiguous 0 0
375 refs/heads/branch-two 0 0
376 refs/heads/branch-one 1 0
377 refs/heads/main 1 0
378 refs/heads/ref-to-branch 1 0
379 refs/heads/ref-to-remote 1 0
380 EOF
381 git branch --format="%(refname) %(ahead-behind:HEAD)" \
382 --sort=refname --sort=ahead-behind:HEAD >actual &&
383 test_cmp expect actual &&
384
385 cat >expect <<-\EOF &&
386 (HEAD detached from fromtag) 0 0
387 refs/heads/branch-one 1 0
388 refs/heads/main 1 0
389 refs/heads/ref-to-branch 1 0
390 refs/heads/ref-to-remote 1 0
391 refs/heads/ambiguous 0 0
392 refs/heads/branch-two 0 0
393 EOF
394 git branch --format="%(refname) %(ahead-behind:HEAD)" \
395 --sort=refname --sort=-ahead-behind:HEAD >actual &&
396 test_cmp expect actual
397 '
398
399 test_expect_success 'git branch with --format=%(rest) must fail' '
400 test_must_fail git branch --format="%(rest)" >actual
401 '
402
403 test_expect_success 'git branch --format --omit-empty' '
404 cat >expect <<-\EOF &&
405 Refname is (HEAD detached from fromtag)
406 Refname is refs/heads/ambiguous
407 Refname is refs/heads/branch-one
408 Refname is refs/heads/branch-two
409
410 Refname is refs/heads/ref-to-branch
411 Refname is refs/heads/ref-to-remote
412 EOF
413 git branch --format="%(if:notequals=refs/heads/main)%(refname)%(then)Refname is %(refname)%(end)" >actual &&
414 test_cmp expect actual &&
415 cat >expect <<-\EOF &&
416 Refname is (HEAD detached from fromtag)
417 Refname is refs/heads/ambiguous
418 Refname is refs/heads/branch-one
419 Refname is refs/heads/branch-two
420 Refname is refs/heads/ref-to-branch
421 Refname is refs/heads/ref-to-remote
422 EOF
423 git branch --omit-empty --format="%(if:notequals=refs/heads/main)%(refname)%(then)Refname is %(refname)%(end)" >actual &&
424 test_cmp expect actual
425 '
426
427 test_expect_success 'worktree colors correct' '
428 cat >expect <<-EOF &&
429 * <GREEN>(HEAD detached from fromtag)<RESET>
430 ambiguous<RESET>
431 branch-one<RESET>
432 + <CYAN>branch-two<RESET>
433 main<RESET>
434 ref-to-branch<RESET> -> branch-one
435 ref-to-remote<RESET> -> origin/branch-one
436 EOF
437 git worktree add worktree_dir branch-two &&
438 git branch --color >actual.raw &&
439 rm -r worktree_dir &&
440 git worktree prune &&
441 test_decode_color <actual.raw >actual &&
442 test_cmp expect actual
443 '
444
445 test_expect_success "set up color tests" '
446 echo "<RED>main<RESET>" >expect.color &&
447 echo "main" >expect.bare &&
448 color_args="--format=%(color:red)%(refname:short) --list main"
449 '
450
451 test_expect_success '%(color) omitted without tty' '
452 TERM=vt100 git branch $color_args >actual.raw &&
453 test_decode_color <actual.raw >actual &&
454 test_cmp expect.bare actual
455 '
456
457 test_expect_success TTY '%(color) present with tty' '
458 test_terminal git branch $color_args >actual.raw &&
459 test_decode_color <actual.raw >actual &&
460 test_cmp expect.color actual
461 '
462
463 test_expect_success '--color overrides auto-color' '
464 git branch --color $color_args >actual.raw &&
465 test_decode_color <actual.raw >actual &&
466 test_cmp expect.color actual
467 '
468
469 test_expect_success 'verbose output lists worktree path' '
470 one=$(git rev-parse --short HEAD) &&
471 two=$(git rev-parse --short main) &&
472 cat >expect <<-EOF &&
473 * (HEAD detached from fromtag) $one one
474 ambiguous $one one
475 branch-one $two two
476 + branch-two $one ($(pwd)/worktree_dir) one
477 main $two two
478 ref-to-branch $two two
479 ref-to-remote $two two
480 EOF
481 git worktree add worktree_dir branch-two &&
482 git branch -vv >actual &&
483 rm -r worktree_dir &&
484 git worktree prune &&
485 test_cmp expect actual
486 '
487
488 test_done