3 test_description
='git branch display tests'
5 TEST_PASSES_SANITIZE_LEAK
=true
7 .
"$TEST_DIRECTORY"/lib-terminal.sh
9 test_expect_success
'make commits' '
14 echo content >>file &&
18 test_expect_success
'make branches' '
19 git branch branch-one &&
20 git branch branch-two HEAD^
23 test_expect_success
'make remote branches' '
24 git update-ref refs/remotes/origin/branch-one branch-one &&
25 git update-ref refs/remotes/origin/branch-two branch-two &&
26 git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/branch-one
34 test_expect_success
'git branch shows local branches' '
36 test_cmp expect actual
39 test_expect_success
'git branch --list shows local branches' '
40 git branch --list >actual &&
41 test_cmp expect actual
48 test_expect_success
'git branch --list pattern shows matching local branches' '
49 git branch --list branch* >actual &&
50 test_cmp expect actual
54 origin/HEAD -> origin/branch-one
58 test_expect_success
'git branch -r shows remote branches' '
59 git branch -r >actual &&
60 test_cmp expect actual &&
62 git branch --remotes >actual &&
63 test_cmp expect actual
66 test_expect_success
'git branch --no-remotes is rejected' '
67 test_must_fail git branch --no-remotes 2>err &&
68 grep "unknown option .no-remotes." err
75 remotes/origin/HEAD -> origin/branch-one
76 remotes/origin/branch-one
77 remotes/origin/branch-two
79 test_expect_success
'git branch -a shows local and remote branches' '
80 git branch -a >actual &&
81 test_cmp expect actual &&
83 git branch --all >actual &&
84 test_cmp expect actual
87 test_expect_success
'git branch --no-all is rejected' '
88 test_must_fail git branch --no-all 2>err &&
89 grep "unknown option .no-all." err
97 test_expect_success
'git branch -v shows branch summaries' '
99 awk "{print \$NF}" <tmp >actual &&
100 test_cmp expect actual
107 test_expect_success
'git branch --list -v pattern shows branch summaries' '
108 git branch --list -v branch* >tmp &&
109 awk "{print \$NF}" <tmp >actual &&
110 test_cmp expect actual
112 test_expect_success
'git branch --ignore-case --list -v pattern shows branch summaries' '
113 git branch --list --ignore-case -v BRANCH* >tmp &&
114 awk "{print \$NF}" <tmp >actual &&
115 test_cmp expect actual
118 test_expect_success
'git branch -v pattern does not show branch summaries' '
119 test_must_fail git branch -v branch*
122 test_expect_success
'git branch `--show-current` shows current branch' '
123 cat >expect <<-\EOF &&
126 git checkout branch-two &&
127 git branch --show-current >actual &&
128 test_cmp expect actual
131 test_expect_success
'git branch `--show-current` is silent when detached HEAD' '
132 git checkout HEAD^0 &&
133 git branch --show-current >actual &&
134 test_must_be_empty actual
137 test_expect_success
'git branch `--show-current` works properly when tag exists' '
138 cat >expect <<-\EOF &&
142 git checkout branch-one
143 git branch -D branch-and-tag-name
145 git checkout -b branch-and-tag-name &&
146 test_when_finished "git tag -d branch-and-tag-name" &&
147 git tag branch-and-tag-name &&
148 git branch --show-current >actual &&
149 test_cmp expect actual
152 test_expect_success
'git branch `--show-current` works properly with worktrees' '
153 cat >expect <<-\EOF &&
157 git checkout branch-one &&
159 git worktree remove worktree_dir
161 git worktree add worktree_dir branch-two &&
163 git branch --show-current &&
164 git -C worktree_dir branch --show-current
166 test_cmp expect actual
169 test_expect_success
'git branch shows detached HEAD properly' '
171 * (HEAD detached at $(git rev-parse --short HEAD^0))
176 git checkout HEAD^0 &&
177 git branch >actual &&
178 test_cmp expect actual
181 test_expect_success
'git branch shows detached HEAD properly after checkout --detach' '
184 * (HEAD detached at $(git rev-parse --short HEAD^0))
189 git checkout --detach &&
190 git branch >actual &&
191 test_cmp expect actual
194 test_expect_success
'git branch shows detached HEAD properly after moving' '
196 * (HEAD detached from $(git rev-parse --short HEAD))
201 git reset --hard HEAD^1 &&
202 git branch >actual &&
203 test_cmp expect actual
206 test_expect_success
'git branch shows detached HEAD properly from tag' '
208 * (HEAD detached at fromtag)
213 git tag fromtag main &&
214 git checkout fromtag &&
215 git branch >actual &&
216 test_cmp expect actual
219 test_expect_success
'git branch shows detached HEAD properly after moving from tag' '
221 * (HEAD detached from fromtag)
226 git reset --hard HEAD^1 &&
227 git branch >actual &&
228 test_cmp expect actual
231 test_expect_success
'git branch `--sort=[-]objectsize` option' '
232 cat >expect <<-\EOF &&
233 * (HEAD detached from fromtag)
238 git branch --sort=objectsize >actual &&
239 test_cmp expect actual &&
241 cat >expect <<-\EOF &&
242 * (HEAD detached from fromtag)
247 git branch --sort=-objectsize >actual &&
248 test_cmp expect actual
251 test_expect_success
'git branch `--sort=[-]type` option' '
252 cat >expect <<-\EOF &&
253 * (HEAD detached from fromtag)
258 git branch --sort=type >actual &&
259 test_cmp expect actual &&
261 cat >expect <<-\EOF &&
262 * (HEAD detached from fromtag)
267 git branch --sort=-type >actual &&
268 test_cmp expect actual
271 test_expect_success
'git branch `--sort=[-]version:refname` option' '
272 cat >expect <<-\EOF &&
273 * (HEAD detached from fromtag)
278 git branch --sort=version:refname >actual &&
279 test_cmp expect actual &&
281 cat >expect <<-\EOF &&
282 * (HEAD detached from fromtag)
287 git branch --sort=-version:refname >actual &&
288 test_cmp expect actual
291 test_expect_success
'git branch --points-at option' '
292 cat >expect <<-\EOF &&
296 git branch --points-at=branch-one >actual &&
297 test_cmp expect actual
300 test_expect_success
'ambiguous branch/tag not marked' '
302 git branch ambiguous &&
303 echo " ambiguous" >expect &&
304 git branch --list ambiguous >actual &&
305 test_cmp expect actual
308 test_expect_success
'local-branch symrefs shortened properly' '
309 git symbolic-ref refs/heads/ref-to-branch refs/heads/branch-one &&
310 git symbolic-ref refs/heads/ref-to-remote refs/remotes/origin/branch-one &&
311 cat >expect <<-\EOF &&
312 ref-to-branch -> branch-one
313 ref-to-remote -> origin/branch-one
315 git branch >actual.raw &&
316 grep ref-to <actual.raw >actual &&
317 test_cmp expect actual
320 test_expect_success
'sort branches, ignore case' '
322 git init -b main sort-icase &&
324 test_commit initial &&
325 git branch branch-one &&
326 git branch BRANCH-two &&
327 git branch --list | awk "{print \$NF}" >actual &&
328 cat >expected <<-\EOF &&
333 test_cmp expected actual &&
334 git branch --list -i | awk "{print \$NF}" >actual &&
335 cat >expected <<-\EOF &&
340 test_cmp expected actual
344 test_expect_success
'git branch --format option' '
345 cat >expect <<-\EOF &&
346 Refname is (HEAD detached from fromtag)
347 Refname is refs/heads/ambiguous
348 Refname is refs/heads/branch-one
349 Refname is refs/heads/branch-two
350 Refname is refs/heads/main
351 Refname is refs/heads/ref-to-branch
352 Refname is refs/heads/ref-to-remote
354 git branch --format="Refname is %(refname)" >actual &&
355 test_cmp expect actual
358 test_expect_success
'git branch --format with ahead-behind' '
359 cat >expect <<-\EOF &&
360 (HEAD detached from fromtag) 0 0
361 refs/heads/ambiguous 0 0
362 refs/heads/branch-one 1 0
363 refs/heads/branch-two 0 0
365 refs/heads/ref-to-branch 1 0
366 refs/heads/ref-to-remote 1 0
368 git branch --format="%(refname) %(ahead-behind:HEAD)" >actual &&
369 test_cmp expect actual
372 test_expect_success
'git branch with --format=%(rest) must fail' '
373 test_must_fail git branch --format="%(rest)" >actual
376 test_expect_success
'git branch --format --omit-empty' '
377 cat >expect <<-\EOF &&
378 Refname is (HEAD detached from fromtag)
379 Refname is refs/heads/ambiguous
380 Refname is refs/heads/branch-one
381 Refname is refs/heads/branch-two
383 Refname is refs/heads/ref-to-branch
384 Refname is refs/heads/ref-to-remote
386 git branch --format="%(if:notequals=refs/heads/main)%(refname)%(then)Refname is %(refname)%(end)" >actual &&
387 test_cmp expect actual &&
388 cat >expect <<-\EOF &&
389 Refname is (HEAD detached from fromtag)
390 Refname is refs/heads/ambiguous
391 Refname is refs/heads/branch-one
392 Refname is refs/heads/branch-two
393 Refname is refs/heads/ref-to-branch
394 Refname is refs/heads/ref-to-remote
396 git branch --omit-empty --format="%(if:notequals=refs/heads/main)%(refname)%(then)Refname is %(refname)%(end)" >actual &&
397 test_cmp expect actual
400 test_expect_success
'worktree colors correct' '
401 cat >expect <<-EOF &&
402 * <GREEN>(HEAD detached from fromtag)<RESET>
405 + <CYAN>branch-two<RESET>
407 ref-to-branch<RESET> -> branch-one
408 ref-to-remote<RESET> -> origin/branch-one
410 git worktree add worktree_dir branch-two &&
411 git branch --color >actual.raw &&
412 rm -r worktree_dir &&
413 git worktree prune &&
414 test_decode_color <actual.raw >actual &&
415 test_cmp expect actual
418 test_expect_success
"set up color tests" '
419 echo "<RED>main<RESET>" >expect.color &&
420 echo "main" >expect.bare &&
421 color_args="--format=%(color:red)%(refname:short) --list main"
424 test_expect_success
'%(color) omitted without tty' '
425 TERM=vt100 git branch $color_args >actual.raw &&
426 test_decode_color <actual.raw >actual &&
427 test_cmp expect.bare actual
430 test_expect_success TTY
'%(color) present with tty' '
431 test_terminal git branch $color_args >actual.raw &&
432 test_decode_color <actual.raw >actual &&
433 test_cmp expect.color actual
436 test_expect_success
'--color overrides auto-color' '
437 git branch --color $color_args >actual.raw &&
438 test_decode_color <actual.raw >actual &&
439 test_cmp expect.color actual
442 test_expect_success
'verbose output lists worktree path' '
443 one=$(git rev-parse --short HEAD) &&
444 two=$(git rev-parse --short main) &&
445 cat >expect <<-EOF &&
446 * (HEAD detached from fromtag) $one one
449 + branch-two $one ($(pwd)/worktree_dir) one
451 ref-to-branch $two two
452 ref-to-remote $two two
454 git worktree add worktree_dir branch-two &&
455 git branch -vv >actual &&
456 rm -r worktree_dir &&
457 git worktree prune &&
458 test_cmp expect actual