Skip to content

Commit

Permalink
show-branch --reflog: show the reflog message at the top.
Browse files Browse the repository at this point in the history
This changes the output so the list at the top shows the reflog
message, along with their relative timestamps.

You can use --reflog=<n> to show <n> most recent log entries, or
use --reflog=<n>,<b> to show <n> entries going back from the
entry <b>.  <b> can be either a number (so --reflog=4,20 shows 4
records starting from @{20}) or a timestamp (e.g. --reflog='4,1 day').

Here is a sample output (with --list option):

  $ git show-branch --reflog=10 --list jc/show-reflog
    [jc/show-reflog@{0}] (3 minutes ago) commit (amend): show-branch --ref
    [jc/show-reflog@{1}] (5 minutes ago) reset HEAD^
    [jc/show-reflog@{2}] (14 minutes ago) commit: show-branch --reflog: sho
    [jc/show-reflog@{3}] (14 minutes ago) commit: show-branch --reflog: sho
    [jc/show-reflog@{4}] (18 minutes ago) commit (amend): Extend read_ref_a
    [jc/show-reflog@{5}] (18 minutes ago) commit (amend): Extend read_ref_a
    [jc/show-reflog@{6}] (18 minutes ago) commit (amend): Extend read_ref_a
    [jc/show-reflog@{7}] (18 minutes ago) am: read_ref_at(): allow retrievi
    [jc/show-reflog@{8}] (18 minutes ago) reset --hard HEAD~4
    [jc/show-reflog@{9}] (61 minutes ago) commit: show-branch --reflog: use

This shows what I did more cleanly:

  $ git show-branch --reflog=10 jc/show-reflog
  ! [jc/show-reflog@{0}] (3 minutes ago) commit (amend): show-branch --ref
   ! [jc/show-reflog@{1}] (5 minutes ago) reset HEAD^
    ! [jc/show-reflog@{2}] (14 minutes ago) commit: show-branch --reflog:
     ! [jc/show-reflog@{3}] (14 minutes ago) commit: show-branch --reflog:
      ! [jc/show-reflog@{4}] (18 minutes ago) commit (amend): Extend read_
       ! [jc/show-reflog@{5}] (18 minutes ago) commit (amend): Extend read
        ! [jc/show-reflog@{6}] (18 minutes ago) commit (amend): Extend rea
         ! [jc/show-reflog@{7}] (18 minutes ago) am: read_ref_at(): allow
          ! [jc/show-reflog@{8}] (18 minutes ago) reset --hard HEAD~4
           ! [jc/show-reflog@{9}] (61 minutes ago) commit: show-branch --r
  ----------
  +          [jc/show-reflog@{0}] show-branch --reflog: show the reflog
    +        [jc/show-reflog@{2}] show-branch --reflog: show the reflog
   +++       [jc/show-reflog@{1}] show-branch --reflog: show the reflog
  +++++      [jc/show-reflog@{4}] Extend read_ref_at() to be usable fro
       +     [jc/show-reflog@{5}] Extend read_ref_at() to be usable fro
        +    [jc/show-reflog@{6}] Extend read_ref_at() to be usable fro
         +   [jc/show-reflog@{7}] read_ref_at(): allow retrieving the r
           + [jc/show-reflog@{9}] show-branch --reflog: use updated rea
           + [jc/show-reflog@{9}^] read_ref_at(): allow reporting the c
           + [jc/show-reflog@{9}~2] show-branch --reflog: show the refl
           + [jc/show-reflog@{9}~3] read_ref_at(): allow retrieving the
  ++++++++++ [jc/show-reflog@{8}] dwim_ref(): Separate name-to-ref DWIM

At @{9}, I had a commit to complete 5 patch series, but I wanted
to consolidate two commits that enhances read_ref_at() into one
(they were @{9}^ and @{9}~3), and another two that touch show-branch
into one (@{9} and @{9}~2).

I first saved them with "format-patch -4", and then did a reset
at @{8}.  At @{7}, I applied one of them with "am", and then
used "git-apply" on the other one, and amended the commit at
@{6} (so @{6} and @{7} has the same parent).  I did not like the
log message, so I amended again at @{5}.

Then I cherry-picked @{9}~2 to create @{3} (the log message
shows that it needs to learn to set GIT_REFLOG_ACTION -- it uses
"git-commit" and the log entry is attributed for it).  Another
cherry-pick built @{2} out of @{9}, but what I wanted to do was
to squash these two into one, so I did a "reset HEAD^" at @{1}
and then made the final commit by amending what was at the top.

Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
Junio C Hamano committed Jan 20, 2007
1 parent 16d7cc9 commit 76a44c5
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 33 deletions.
15 changes: 12 additions & 3 deletions Documentation/git-show-branch.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ SYNOPSIS
'git-show-branch' [--all] [--remotes] [--topo-order] [--current]
[--more=<n> | --list | --independent | --merge-base]
[--no-name | --sha1-name] [--topics] [<rev> | <glob>]...
'git-show-branch' --reflog[=<n>] <ref>
'git-show-branch' --reflog[=<n>[,<base>]] [--list] <ref>

DESCRIPTION
-----------
Expand Down Expand Up @@ -97,8 +97,10 @@ OPTIONS
will show the revisions given by "git rev-list {caret}master
topic1 topic2"

--reflog[=<n>] <ref>::
Shows <n> most recent ref-log entries for the given ref.
--reflog[=<n>[,<base>]] <ref>::
Shows <n> most recent ref-log entries for the given
ref. If <base> is given, <n> entries going back from
that entry. <base> can be specified as count or date


Note that --more, --list, --independent and --merge-base options
Expand Down Expand Up @@ -165,6 +167,13 @@ With this, `git show-branch` without extra parameters would show
only the primary branches. In addition, if you happen to be on
your topic branch, it is shown as well.

------------
$ git show-branch --reflog='10,1 hour ago' --list master
------------

shows 10 reflog entries going back from the tip as of 1 hour ago.
Without `--list`, the output also shows how these tips are
topologically related with each other.


Author
Expand Down
122 changes: 95 additions & 27 deletions builtin-show-branch.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,18 +346,21 @@ static void sort_ref_range(int bottom, int top)
compare_ref_name);
}

static int append_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
static int append_ref(const char *refname, const unsigned char *sha1,
int allow_dups)
{
struct commit *commit = lookup_commit_reference_gently(sha1, 1);
int i;

if (!commit)
return 0;
/* Avoid adding the same thing twice */
for (i = 0; i < ref_name_cnt; i++)
if (!strcmp(refname, ref_name[i]))
return 0;

if (!allow_dups) {
/* Avoid adding the same thing twice */
for (i = 0; i < ref_name_cnt; i++)
if (!strcmp(refname, ref_name[i]))
return 0;
}
if (MAX_REVS <= ref_name_cnt) {
fprintf(stderr, "warning: ignoring %s; "
"cannot handle more than %d refs\n",
Expand All @@ -380,7 +383,7 @@ static int append_head_ref(const char *refname, const unsigned char *sha1, int f
*/
if (get_sha1(refname + ofs, tmp) || hashcmp(tmp, sha1))
ofs = 5;
return append_ref(refname + ofs, sha1, flag, cb_data);
return append_ref(refname + ofs, sha1, 0);
}

static int append_remote_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
Expand All @@ -394,14 +397,14 @@ static int append_remote_ref(const char *refname, const unsigned char *sha1, int
*/
if (get_sha1(refname + ofs, tmp) || hashcmp(tmp, sha1))
ofs = 5;
return append_ref(refname + ofs, sha1, flag, cb_data);
return append_ref(refname + ofs, sha1, 0);
}

static int append_tag_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
{
if (strncmp(refname, "refs/tags/", 10))
return 0;
return append_ref(refname + 5, sha1, flag, cb_data);
return append_ref(refname + 5, sha1, 0);
}

static const char *match_ref_pattern = NULL;
Expand Down Expand Up @@ -434,7 +437,7 @@ static int append_matching_ref(const char *refname, const unsigned char *sha1, i
return append_head_ref(refname, sha1, flag, cb_data);
if (!strncmp("refs/tags/", refname, 10))
return append_tag_ref(refname, sha1, flag, cb_data);
return append_ref(refname, sha1, flag, cb_data);
return append_ref(refname, sha1, 0);
}

static void snarf_refs(int head, int remotes)
Expand Down Expand Up @@ -507,7 +510,7 @@ static void append_one_rev(const char *av)
{
unsigned char revkey[20];
if (!get_sha1(av, revkey)) {
append_ref(av, revkey, 0, NULL);
append_ref(av, revkey, 0);
return;
}
if (strchr(av, '*') || strchr(av, '?') || strchr(av, '[')) {
Expand Down Expand Up @@ -562,9 +565,24 @@ static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
return 0;
}

static void parse_reflog_param(const char *arg, int *cnt, const char **base)
{
char *ep;
*cnt = strtoul(arg, &ep, 10);
if (*ep == ',')
*base = ep + 1;
else if (*ep)
die("unrecognized reflog param '%s'", arg + 9);
else
*base = NULL;
if (*cnt <= 0)
*cnt = DEFAULT_REFLOG;
}

int cmd_show_branch(int ac, const char **av, const char *prefix)
{
struct commit *rev[MAX_REVS], *commit;
char *reflog_msg[MAX_REVS];
struct commit_list *list = NULL, *seen = NULL;
unsigned int rev_mask[MAX_REVS];
int num_rev, i, extra = 0;
Expand All @@ -585,6 +603,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
int topics = 0;
int dense = 1;
int reflog = 0;
const char *reflog_base = NULL;

git_config(git_show_branch_config);

Expand Down Expand Up @@ -631,21 +650,27 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
else if (!strcmp(arg, "--reflog")) {
reflog = DEFAULT_REFLOG;
}
else if (!strncmp(arg, "--reflog=", 9)) {
char *end;
reflog = strtoul(arg + 9, &end, 10);
if (*end != '\0')
die("unrecognized reflog count '%s'", arg + 9);
}
else if (!strncmp(arg, "--reflog=", 9))
parse_reflog_param(arg + 9, &reflog, &reflog_base);
else
usage(show_branch_usage);
ac--; av++;
}
ac--; av++;

/* Only one of these is allowed */
if (1 < independent + merge_base + (extra != 0) + (!!reflog))
usage(show_branch_usage);
if (!!extra || !!reflog) {
/* "listing" mode is incompatible with
* independent nor merge-base modes.
*/
if (independent || merge_base)
usage(show_branch_usage);
if (!!reflog && (0 < extra))
/*
* Asking for --more in reflog mode does not
* make sense.
*/
usage(show_branch_usage);
}

/* If nothing is specified, show all branches by default */
if (ac + all_heads + all_remotes == 0)
Expand All @@ -654,14 +679,51 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
if (all_heads + all_remotes)
snarf_refs(all_heads, all_remotes);
if (reflog) {
int reflen;
if (!ac)
unsigned char sha1[20];
char nth_desc[256];
char *ref;
int base = 0;
if (ac != 1)
die("--reflog option needs one branch name");
reflen = strlen(*av);
if (!dwim_ref(*av, strlen(*av), sha1, &ref))
die("No such ref %s", *av);

/* Has the base been specified? */
if (reflog_base) {
char *ep;
base = strtoul(reflog_base, &ep, 10);
if (*ep) {
/* Ah, that is a date spec... */
unsigned long at;
at = approxidate(reflog_base);
read_ref_at(ref, at, -1, sha1, NULL,
NULL, NULL, &base);
}
}

for (i = 0; i < reflog; i++) {
char *name = xmalloc(reflen + 20);
sprintf(name, "%s@{%d}", *av, i);
append_one_rev(name);
char *logmsg, *msg, *m;
unsigned long timestamp;
int tz;

if (read_ref_at(ref, 0, base+i, sha1, &logmsg,
&timestamp, &tz, NULL)) {
reflog = i;
break;
}
msg = strchr(logmsg, '\t');
if (!msg)
msg = "(none)";
else
msg++;
m = xmalloc(strlen(msg) + 200);
sprintf(m, "(%s) %s",
show_date(timestamp, 0, 1),
msg);
reflog_msg[i] = m;
free(logmsg);
sprintf(nth_desc, "%s@{%d}", *av, base+i);
append_ref(nth_desc, sha1, 1);
}
}
else {
Expand Down Expand Up @@ -760,8 +822,14 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
printf("%c [%s] ",
is_head ? '*' : '!', ref_name[i]);
}
/* header lines never need name */
show_one_commit(rev[i], 1);

if (!reflog) {
/* header lines never need name */
show_one_commit(rev[i], 1);
}
else
puts(reflog_msg[i]);

if (is_head)
head_at = i;
}
Expand Down
5 changes: 2 additions & 3 deletions refs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1068,21 +1068,21 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
die("Log %s is corrupt.", logfile);
date = strtoul(lastgt + 1, &tz_c, 10);
if (date <= at_time || cnt == 0) {
tz = strtoul(tz_c, NULL, 10);
if (msg)
*msg = ref_msg(rec, logend);
if (cutoff_time)
*cutoff_time = date;
if (cutoff_tz)
*cutoff_tz = tz;
if (cutoff_cnt)
*cutoff_cnt = reccnt;
*cutoff_cnt = reccnt - 1;
if (lastrec) {
if (get_sha1_hex(lastrec, logged_sha1))
die("Log %s is corrupt.", logfile);
if (get_sha1_hex(rec + 41, sha1))
die("Log %s is corrupt.", logfile);
if (hashcmp(logged_sha1, sha1)) {
tz = strtoul(tz_c, NULL, 10);
fprintf(stderr,
"warning: Log %s has gap after %s.\n",
logfile, show_rfc2822_date(date, tz));
Expand All @@ -1096,7 +1096,6 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
if (get_sha1_hex(rec + 41, logged_sha1))
die("Log %s is corrupt.", logfile);
if (hashcmp(logged_sha1, sha1)) {
tz = strtoul(tz_c, NULL, 10);
fprintf(stderr,
"warning: Log %s unexpectedly ended on %s.\n",
logfile, show_rfc2822_date(date, tz));
Expand Down

0 comments on commit 76a44c5

Please sign in to comment.