Skip to content

Commit 287f860

Browse files
author
Junio C Hamano
committed
show-branch: allow glob pattern to name branches to show.
With this, you can say "git-show-branch topic/* master" to show all the topic branches you have under .git/refs/heads/topic/ and your master branch. Another example is "git-show-branch --list v1.0*" to show all the v1.0 tags. You can disambiguate by saying "heads/topic/*" to show only topic branches if you have tags under .git/refs/tags/topic/ as well. Signed-off-by: Junio C Hamano <junkio@cox.net>
1 parent 7b9b4c4 commit 287f860

File tree

2 files changed

+84
-15
lines changed

2 files changed

+84
-15
lines changed

Documentation/git-show-branch.txt

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,29 @@ git-show-branch - Show branches and their commits.
77

88
SYNOPSIS
99
--------
10-
'git-show-branch [--all] [--heads] [--tags] [--more=<n> | --list | --independent | --merge-base] [--no-name | --sha1-name] <reference>...'
10+
'git-show-branch [--all] [--heads] [--tags] [--more=<n> | --list | --independent | --merge-base] [--no-name | --sha1-name] [<rev> | <glob>]...'
1111

1212
DESCRIPTION
1313
-----------
14-
Shows the head commits from the named <reference> (or all refs under
15-
$GIT_DIR/refs/heads), and displays concise list of commit logs
16-
to show their relationship semi-visually.
14+
15+
Shows the commit ancestry graph starting from the commits named
16+
with <rev>s or <globs>s (or all refs under $GIT_DIR/refs/heads
17+
and/or $GIT_DIR/refs/tags) semi-visually.
18+
19+
It cannot show more than 29 branches and commits at a time.
20+
1721

1822
OPTIONS
1923
-------
20-
<reference>::
21-
Name of the reference under $GIT_DIR/refs/.
24+
<rev>::
25+
Arbitrary extended SHA1 expression (see `git-rev-parse`)
26+
that typically names a branch HEAD or a tag.
27+
28+
<glob>::
29+
A glob pattern that matches branch or tag names under
30+
$GIT_DIR/refs. For example, if you have many topic
31+
branches under $GIT_DIR/refs/heads/topic, giving
32+
`topic/*` would show all of them.
2233

2334
--all --heads --tags::
2435
Show all refs under $GIT_DIR/refs, $GIT_DIR/refs/heads,

show-branch.c

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <stdlib.h>
2+
#include <fnmatch.h>
23
#include "cache.h"
34
#include "commit.h"
45
#include "refs.h"
@@ -332,6 +333,39 @@ static int append_tag_ref(const char *refname, const unsigned char *sha1)
332333
return append_ref(refname + 5, sha1);
333334
}
334335

336+
static const char *match_ref_pattern = NULL;
337+
static int match_ref_slash = 0;
338+
static int count_slash(const char *s)
339+
{
340+
int cnt = 0;
341+
while (*s)
342+
if (*s++ == '/')
343+
cnt++;
344+
return cnt;
345+
}
346+
347+
static int append_matching_ref(const char *refname, const unsigned char *sha1)
348+
{
349+
/* we want to allow pattern hold/<asterisk> to show all
350+
* branches under refs/heads/hold/, and v0.99.9? to show
351+
* refs/tags/v0.99.9a and friends.
352+
*/
353+
const char *tail;
354+
int slash = count_slash(refname);
355+
for (tail = refname; *tail && match_ref_slash < slash; )
356+
if (*tail++ == '/')
357+
slash--;
358+
if (!*tail)
359+
return 0;
360+
if (fnmatch(match_ref_pattern, tail, 0))
361+
return 0;
362+
if (!strncmp("refs/heads/", refname, 11))
363+
return append_head_ref(refname, sha1);
364+
if (!strncmp("refs/tags/", refname, 10))
365+
return append_tag_ref(refname, sha1);
366+
return append_ref(refname, sha1);
367+
}
368+
335369
static void snarf_refs(int head, int tag)
336370
{
337371
if (head) {
@@ -400,6 +434,27 @@ static int show_independent(struct commit **rev,
400434
return 0;
401435
}
402436

437+
static void append_one_rev(const char *av)
438+
{
439+
unsigned char revkey[20];
440+
if (!get_sha1(av, revkey)) {
441+
append_ref(av, revkey);
442+
return;
443+
}
444+
if (strchr(av, '*') || strchr(av, '?')) {
445+
/* glob style match */
446+
int saved_matches = ref_name_cnt;
447+
match_ref_pattern = av;
448+
match_ref_slash = count_slash(av);
449+
for_each_ref(append_matching_ref);
450+
if (saved_matches == ref_name_cnt &&
451+
ref_name_cnt < MAX_REVS)
452+
error("no matching refs with %s", av);
453+
return;
454+
}
455+
die("bad sha1 reference %s", av);
456+
}
457+
403458
int main(int ac, char **av)
404459
{
405460
struct commit *rev[MAX_REVS], *commit;
@@ -458,17 +513,20 @@ int main(int ac, char **av)
458513
if (all_heads + all_tags)
459514
snarf_refs(all_heads, all_tags);
460515

461-
while (0 < ac) {
462-
unsigned char revkey[20];
463-
if (get_sha1(*av, revkey))
464-
die("bad sha1 reference %s", *av);
465-
append_ref(*av, revkey);
466-
ac--; av++;
516+
if (ac) {
517+
while (0 < ac) {
518+
append_one_rev(*av);
519+
ac--; av++;
520+
}
467521
}
468-
469-
/* If still no revs, then add heads */
470-
if (!ref_name_cnt)
522+
else {
523+
/* If no revs given, then add heads */
471524
snarf_refs(1, 0);
525+
}
526+
if (!ref_name_cnt) {
527+
fprintf(stderr, "No revs to be shown.\n");
528+
exit(0);
529+
}
472530

473531
for (num_rev = 0; ref_name[num_rev]; num_rev++) {
474532
unsigned char revkey[20];

0 commit comments

Comments
 (0)