Merge branch 'dl/pretty-reference'
"git log" family learned "--pretty=reference" that gives the name of a commit in the format that is often used to refer to it in log messages. * dl/pretty-reference: SubmittingPatches: use `--pretty=reference` pretty: implement 'reference' format pretty: add struct cmt_fmt_map::default_date_mode_type pretty: provide short date format t4205: cover `git log --reflog -z` blindspot pretty.c: inline initalize format_context revision: make get_revision_mark() return const pointer completion: complete `tformat:` pretty format SubmittingPatches: remove dq from commit reference pretty-formats.txt: use generic terms for hash SubmittingPatches: use generic terms for hash
This commit is contained in:
@ -142,19 +142,25 @@ archive, summarize the relevant points of the discussion.
|
|||||||
|
|
||||||
[[commit-reference]]
|
[[commit-reference]]
|
||||||
If you want to reference a previous commit in the history of a stable
|
If you want to reference a previous commit in the history of a stable
|
||||||
branch, use the format "abbreviated sha1 (subject, date)",
|
branch, use the format "abbreviated hash (subject, date)", like this:
|
||||||
with the subject enclosed in a pair of double-quotes, like this:
|
|
||||||
|
|
||||||
....
|
....
|
||||||
Commit f86a374 ("pack-bitmap.c: fix a memleak", 2015-03-30)
|
Commit f86a374 (pack-bitmap.c: fix a memleak, 2015-03-30)
|
||||||
noticed that ...
|
noticed that ...
|
||||||
....
|
....
|
||||||
|
|
||||||
The "Copy commit summary" command of gitk can be used to obtain this
|
The "Copy commit summary" command of gitk can be used to obtain this
|
||||||
format, or this invocation of `git show`:
|
format (with the subject enclosed in a pair of double-quotes), or this
|
||||||
|
invocation of `git show`:
|
||||||
|
|
||||||
....
|
....
|
||||||
git show -s --date=short --pretty='format:%h ("%s", %ad)' <commit>
|
git show -s --pretty=reference <commit>
|
||||||
|
....
|
||||||
|
|
||||||
|
or, on an older version of Git without support for --pretty=reference:
|
||||||
|
|
||||||
|
....
|
||||||
|
git show -s --date=short --pretty='format:%h (%s, %ad)' <commit>
|
||||||
....
|
....
|
||||||
|
|
||||||
[[git-tools]]
|
[[git-tools]]
|
||||||
|
@ -4,7 +4,7 @@ PRETTY FORMATS
|
|||||||
If the commit is a merge, and if the pretty-format
|
If the commit is a merge, and if the pretty-format
|
||||||
is not 'oneline', 'email' or 'raw', an additional line is
|
is not 'oneline', 'email' or 'raw', an additional line is
|
||||||
inserted before the 'Author:' line. This line begins with
|
inserted before the 'Author:' line. This line begins with
|
||||||
"Merge: " and the sha1s of ancestral commits are printed,
|
"Merge: " and the hashes of ancestral commits are printed,
|
||||||
separated by spaces. Note that the listed commits may not
|
separated by spaces. Note that the listed commits may not
|
||||||
necessarily be the list of the *direct* parent commits if you
|
necessarily be the list of the *direct* parent commits if you
|
||||||
have limited your view of history: for example, if you are
|
have limited your view of history: for example, if you are
|
||||||
@ -20,20 +20,20 @@ built-in formats:
|
|||||||
|
|
||||||
* 'oneline'
|
* 'oneline'
|
||||||
|
|
||||||
<sha1> <title line>
|
<hash> <title line>
|
||||||
+
|
+
|
||||||
This is designed to be as compact as possible.
|
This is designed to be as compact as possible.
|
||||||
|
|
||||||
* 'short'
|
* 'short'
|
||||||
|
|
||||||
commit <sha1>
|
commit <hash>
|
||||||
Author: <author>
|
Author: <author>
|
||||||
|
|
||||||
<title line>
|
<title line>
|
||||||
|
|
||||||
* 'medium'
|
* 'medium'
|
||||||
|
|
||||||
commit <sha1>
|
commit <hash>
|
||||||
Author: <author>
|
Author: <author>
|
||||||
Date: <author date>
|
Date: <author date>
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ This is designed to be as compact as possible.
|
|||||||
|
|
||||||
* 'full'
|
* 'full'
|
||||||
|
|
||||||
commit <sha1>
|
commit <hash>
|
||||||
Author: <author>
|
Author: <author>
|
||||||
Commit: <committer>
|
Commit: <committer>
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ This is designed to be as compact as possible.
|
|||||||
|
|
||||||
* 'fuller'
|
* 'fuller'
|
||||||
|
|
||||||
commit <sha1>
|
commit <hash>
|
||||||
Author: <author>
|
Author: <author>
|
||||||
AuthorDate: <author date>
|
AuthorDate: <author date>
|
||||||
Commit: <committer>
|
Commit: <committer>
|
||||||
@ -63,9 +63,20 @@ This is designed to be as compact as possible.
|
|||||||
|
|
||||||
<full commit message>
|
<full commit message>
|
||||||
|
|
||||||
|
* 'reference'
|
||||||
|
|
||||||
|
<abbrev hash> (<title line>, <short author date>)
|
||||||
|
+
|
||||||
|
This format is used to refer to another commit in a commit message and
|
||||||
|
is the same as `--pretty='format:%C(auto)%h (%s, %ad)'`. By default,
|
||||||
|
the date is formatted with `--date=short` unless another `--date` option
|
||||||
|
is explicitly specified. As with any `format:` with format
|
||||||
|
placeholders, its output is not affected by other options like
|
||||||
|
`--decorate` and `--walk-reflogs`.
|
||||||
|
|
||||||
* 'email'
|
* 'email'
|
||||||
|
|
||||||
From <sha1> <date>
|
From <hash> <date>
|
||||||
From: <author>
|
From: <author>
|
||||||
Date: <author date>
|
Date: <author date>
|
||||||
Subject: [PATCH] <title line>
|
Subject: [PATCH] <title line>
|
||||||
@ -75,7 +86,7 @@ This is designed to be as compact as possible.
|
|||||||
* 'raw'
|
* 'raw'
|
||||||
+
|
+
|
||||||
The 'raw' format shows the entire commit exactly as
|
The 'raw' format shows the entire commit exactly as
|
||||||
stored in the commit object. Notably, the SHA-1s are
|
stored in the commit object. Notably, the hashes are
|
||||||
displayed in full, regardless of whether --abbrev or
|
displayed in full, regardless of whether --abbrev or
|
||||||
--no-abbrev are used, and 'parents' information show the
|
--no-abbrev are used, and 'parents' information show the
|
||||||
true parent commits, without taking grafts or history
|
true parent commits, without taking grafts or history
|
||||||
@ -172,6 +183,7 @@ The placeholders are:
|
|||||||
'%at':: author date, UNIX timestamp
|
'%at':: author date, UNIX timestamp
|
||||||
'%ai':: author date, ISO 8601-like format
|
'%ai':: author date, ISO 8601-like format
|
||||||
'%aI':: author date, strict ISO 8601 format
|
'%aI':: author date, strict ISO 8601 format
|
||||||
|
'%as':: author date, short format (`YYYY-MM-DD`)
|
||||||
'%cn':: committer name
|
'%cn':: committer name
|
||||||
'%cN':: committer name (respecting .mailmap, see
|
'%cN':: committer name (respecting .mailmap, see
|
||||||
linkgit:git-shortlog[1] or linkgit:git-blame[1])
|
linkgit:git-shortlog[1] or linkgit:git-blame[1])
|
||||||
@ -187,6 +199,7 @@ The placeholders are:
|
|||||||
'%ct':: committer date, UNIX timestamp
|
'%ct':: committer date, UNIX timestamp
|
||||||
'%ci':: committer date, ISO 8601-like format
|
'%ci':: committer date, ISO 8601-like format
|
||||||
'%cI':: committer date, strict ISO 8601 format
|
'%cI':: committer date, strict ISO 8601 format
|
||||||
|
'%cs':: committer date, short format (`YYYY-MM-DD`)
|
||||||
'%d':: ref names, like the --decorate option of linkgit:git-log[1]
|
'%d':: ref names, like the --decorate option of linkgit:git-log[1]
|
||||||
'%D':: ref names without the " (", ")" wrapping.
|
'%D':: ref names without the " (", ")" wrapping.
|
||||||
'%S':: ref name given on the command line by which the commit was reached
|
'%S':: ref name given on the command line by which the commit was reached
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
Pretty-print the contents of the commit logs in a given format,
|
Pretty-print the contents of the commit logs in a given format,
|
||||||
where '<format>' can be one of 'oneline', 'short', 'medium',
|
where '<format>' can be one of 'oneline', 'short', 'medium',
|
||||||
'full', 'fuller', 'email', 'raw', 'format:<string>'
|
'full', 'fuller', 'reference', 'email', 'raw', 'format:<string>'
|
||||||
and 'tformat:<string>'. When '<format>' is none of the above,
|
and 'tformat:<string>'. When '<format>' is none of the above,
|
||||||
and has '%placeholder' in it, it acts as if
|
and has '%placeholder' in it, it acts as if
|
||||||
'--pretty=tformat:<format>' were given.
|
'--pretty=tformat:<format>' were given.
|
||||||
|
@ -269,7 +269,7 @@ list.
|
|||||||
exclude (that is, '{caret}commit', 'commit1..commit2',
|
exclude (that is, '{caret}commit', 'commit1..commit2',
|
||||||
and 'commit1\...commit2' notations cannot be used).
|
and 'commit1\...commit2' notations cannot be used).
|
||||||
+
|
+
|
||||||
With `--pretty` format other than `oneline` (for obvious reasons),
|
With `--pretty` format other than `oneline` and `reference` (for obvious reasons),
|
||||||
this causes the output to have two extra lines of information
|
this causes the output to have two extra lines of information
|
||||||
taken from the reflog. The reflog designator in the output may be shown
|
taken from the reflog. The reflog designator in the output may be shown
|
||||||
as `ref@{Nth}` (where `Nth` is the reverse-chronological index in the
|
as `ref@{Nth}` (where `Nth` is the reverse-chronological index in the
|
||||||
@ -293,6 +293,8 @@ Under `--pretty=oneline`, the commit message is
|
|||||||
prefixed with this information on the same line.
|
prefixed with this information on the same line.
|
||||||
This option cannot be combined with `--reverse`.
|
This option cannot be combined with `--reverse`.
|
||||||
See also linkgit:git-reflog[1].
|
See also linkgit:git-reflog[1].
|
||||||
|
+
|
||||||
|
Under `--pretty=reference`, this information will not be shown at all.
|
||||||
|
|
||||||
--merge::
|
--merge::
|
||||||
After a failed merge, show refs that touch files having a
|
After a failed merge, show refs that touch files having a
|
||||||
|
@ -1749,7 +1749,7 @@ __git_log_shortlog_options="
|
|||||||
--all-match --invert-grep
|
--all-match --invert-grep
|
||||||
"
|
"
|
||||||
|
|
||||||
__git_log_pretty_formats="oneline short medium full fuller email raw format: mboxrd"
|
__git_log_pretty_formats="oneline short medium full fuller reference email raw format: tformat: mboxrd"
|
||||||
__git_log_date_formats="relative iso8601 iso8601-strict rfc2822 short local default raw unix format:"
|
__git_log_date_formats="relative iso8601 iso8601-strict rfc2822 short local default raw unix format:"
|
||||||
|
|
||||||
_git_log ()
|
_git_log ()
|
||||||
|
20
pretty.c
20
pretty.c
@ -20,6 +20,7 @@ static struct cmt_fmt_map {
|
|||||||
int is_tformat;
|
int is_tformat;
|
||||||
int expand_tabs_in_log;
|
int expand_tabs_in_log;
|
||||||
int is_alias;
|
int is_alias;
|
||||||
|
enum date_mode_type default_date_mode_type;
|
||||||
const char *user_format;
|
const char *user_format;
|
||||||
} *commit_formats;
|
} *commit_formats;
|
||||||
static size_t builtin_formats_len;
|
static size_t builtin_formats_len;
|
||||||
@ -97,7 +98,9 @@ static void setup_commit_formats(void)
|
|||||||
{ "mboxrd", CMIT_FMT_MBOXRD, 0, 0 },
|
{ "mboxrd", CMIT_FMT_MBOXRD, 0, 0 },
|
||||||
{ "fuller", CMIT_FMT_FULLER, 0, 8 },
|
{ "fuller", CMIT_FMT_FULLER, 0, 8 },
|
||||||
{ "full", CMIT_FMT_FULL, 0, 8 },
|
{ "full", CMIT_FMT_FULL, 0, 8 },
|
||||||
{ "oneline", CMIT_FMT_ONELINE, 1, 0 }
|
{ "oneline", CMIT_FMT_ONELINE, 1, 0 },
|
||||||
|
{ "reference", CMIT_FMT_USERFORMAT, 1, 0,
|
||||||
|
0, DATE_SHORT, "%C(auto)%h (%s, %ad)" },
|
||||||
/*
|
/*
|
||||||
* Please update $__git_log_pretty_formats in
|
* Please update $__git_log_pretty_formats in
|
||||||
* git-completion.bash when you add new formats.
|
* git-completion.bash when you add new formats.
|
||||||
@ -181,6 +184,8 @@ void get_commit_format(const char *arg, struct rev_info *rev)
|
|||||||
rev->commit_format = commit_format->format;
|
rev->commit_format = commit_format->format;
|
||||||
rev->use_terminator = commit_format->is_tformat;
|
rev->use_terminator = commit_format->is_tformat;
|
||||||
rev->expand_tabs_in_log_default = commit_format->expand_tabs_in_log;
|
rev->expand_tabs_in_log_default = commit_format->expand_tabs_in_log;
|
||||||
|
if (!rev->date_mode_explicit && commit_format->default_date_mode_type)
|
||||||
|
rev->date_mode.type = commit_format->default_date_mode_type;
|
||||||
if (commit_format->format == CMIT_FMT_USERFORMAT) {
|
if (commit_format->format == CMIT_FMT_USERFORMAT) {
|
||||||
save_user_format(rev, commit_format->user_format,
|
save_user_format(rev, commit_format->user_format,
|
||||||
commit_format->is_tformat);
|
commit_format->is_tformat);
|
||||||
@ -738,6 +743,9 @@ static size_t format_person_part(struct strbuf *sb, char part,
|
|||||||
case 'I': /* date, ISO 8601 strict */
|
case 'I': /* date, ISO 8601 strict */
|
||||||
strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(ISO8601_STRICT)));
|
strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(ISO8601_STRICT)));
|
||||||
return placeholder_len;
|
return placeholder_len;
|
||||||
|
case 's':
|
||||||
|
strbuf_addstr(sb, show_ident_date(&s, DATE_MODE(SHORT)));
|
||||||
|
return placeholder_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
skip:
|
skip:
|
||||||
@ -1617,14 +1625,14 @@ void repo_format_commit_message(struct repository *r,
|
|||||||
const char *format, struct strbuf *sb,
|
const char *format, struct strbuf *sb,
|
||||||
const struct pretty_print_context *pretty_ctx)
|
const struct pretty_print_context *pretty_ctx)
|
||||||
{
|
{
|
||||||
struct format_commit_context context;
|
struct format_commit_context context = {
|
||||||
|
.commit = commit,
|
||||||
|
.pretty_ctx = pretty_ctx,
|
||||||
|
.wrap_start = sb->len
|
||||||
|
};
|
||||||
const char *output_enc = pretty_ctx->output_encoding;
|
const char *output_enc = pretty_ctx->output_encoding;
|
||||||
const char *utf8 = "UTF-8";
|
const char *utf8 = "UTF-8";
|
||||||
|
|
||||||
memset(&context, 0, sizeof(context));
|
|
||||||
context.commit = commit;
|
|
||||||
context.pretty_ctx = pretty_ctx;
|
|
||||||
context.wrap_start = sb->len;
|
|
||||||
/*
|
/*
|
||||||
* convert a commit message to UTF-8 first
|
* convert a commit message to UTF-8 first
|
||||||
* as far as 'format_commit_item' assumes it in UTF-8
|
* as far as 'format_commit_item' assumes it in UTF-8
|
||||||
|
@ -3960,7 +3960,7 @@ struct commit *get_revision(struct rev_info *revs)
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *get_revision_mark(const struct rev_info *revs, const struct commit *commit)
|
const char *get_revision_mark(const struct rev_info *revs, const struct commit *commit)
|
||||||
{
|
{
|
||||||
if (commit->object.flags & BOUNDARY)
|
if (commit->object.flags & BOUNDARY)
|
||||||
return "-";
|
return "-";
|
||||||
@ -3982,7 +3982,7 @@ char *get_revision_mark(const struct rev_info *revs, const struct commit *commit
|
|||||||
|
|
||||||
void put_revision_mark(const struct rev_info *revs, const struct commit *commit)
|
void put_revision_mark(const struct rev_info *revs, const struct commit *commit)
|
||||||
{
|
{
|
||||||
char *mark = get_revision_mark(revs, commit);
|
const char *mark = get_revision_mark(revs, commit);
|
||||||
if (!strlen(mark))
|
if (!strlen(mark))
|
||||||
return;
|
return;
|
||||||
fputs(mark, stdout);
|
fputs(mark, stdout);
|
||||||
|
@ -322,7 +322,7 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
|
|||||||
void reset_revision_walk(void);
|
void reset_revision_walk(void);
|
||||||
int prepare_revision_walk(struct rev_info *revs);
|
int prepare_revision_walk(struct rev_info *revs);
|
||||||
struct commit *get_revision(struct rev_info *revs);
|
struct commit *get_revision(struct rev_info *revs);
|
||||||
char *get_revision_mark(const struct rev_info *revs,
|
const char *get_revision_mark(const struct rev_info *revs,
|
||||||
const struct commit *commit);
|
const struct commit *commit);
|
||||||
void put_revision_mark(const struct rev_info *revs,
|
void put_revision_mark(const struct rev_info *revs,
|
||||||
const struct commit *commit);
|
const struct commit *commit);
|
||||||
|
@ -134,6 +134,36 @@ test_expect_failure C_LOCALE_OUTPUT 'NUL termination with --stat' '
|
|||||||
test_cmp expected actual
|
test_cmp expected actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
for p in short medium full fuller email raw
|
||||||
|
do
|
||||||
|
test_expect_success "NUL termination with --reflog --pretty=$p" '
|
||||||
|
revs="$(git rev-list --reflog)" &&
|
||||||
|
for r in $revs
|
||||||
|
do
|
||||||
|
git show -s "$r" --pretty="$p" &&
|
||||||
|
printf "\0" || return 1
|
||||||
|
done >expect &&
|
||||||
|
{
|
||||||
|
git log -z --reflog --pretty="$p" &&
|
||||||
|
printf "\0"
|
||||||
|
} >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
done
|
||||||
|
|
||||||
|
test_expect_success 'NUL termination with --reflog --pretty=oneline' '
|
||||||
|
revs="$(git rev-list --reflog)" &&
|
||||||
|
for r in $revs
|
||||||
|
do
|
||||||
|
git show -s --pretty=oneline "$r" >raw &&
|
||||||
|
cat raw | lf_to_nul || exit 1
|
||||||
|
done >expect &&
|
||||||
|
# the trailing NUL is already produced so we do not need to
|
||||||
|
# output another one
|
||||||
|
git log -z --pretty=oneline --reflog >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'setup more commits' '
|
test_expect_success 'setup more commits' '
|
||||||
test_commit "message one" one one message-one &&
|
test_commit "message one" one one message-one &&
|
||||||
test_commit "message two" two two message-two &&
|
test_commit "message two" two two message-two &&
|
||||||
@ -503,6 +533,12 @@ test_expect_success 'ISO and ISO-strict date formats display the same values' '
|
|||||||
test_cmp expected actual
|
test_cmp expected actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'short date' '
|
||||||
|
git log --format=%ad%n%cd --date=short >expected &&
|
||||||
|
git log --format=%as%n%cs >actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
# get new digests (with no abbreviations)
|
# get new digests (with no abbreviations)
|
||||||
test_expect_success 'set up log decoration tests' '
|
test_expect_success 'set up log decoration tests' '
|
||||||
head1=$(git rev-parse --verify HEAD~0) &&
|
head1=$(git rev-parse --verify HEAD~0) &&
|
||||||
@ -788,4 +824,47 @@ test_expect_success '%S in git log --format works with other placeholders (part
|
|||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'log --pretty=reference' '
|
||||||
|
git log --pretty="tformat:%h (%s, %as)" >expect &&
|
||||||
|
git log --pretty=reference >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'log --pretty=reference with log.date is overridden by short date' '
|
||||||
|
git log --pretty="tformat:%h (%s, %as)" >expect &&
|
||||||
|
test_config log.date rfc &&
|
||||||
|
git log --pretty=reference >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'log --pretty=reference with explicit date overrides short date' '
|
||||||
|
git log --date=rfc --pretty="tformat:%h (%s, %ad)" >expect &&
|
||||||
|
git log --date=rfc --pretty=reference >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'log --pretty=reference is never unabbreviated' '
|
||||||
|
git log --pretty="tformat:%h (%s, %as)" >expect &&
|
||||||
|
git log --no-abbrev-commit --pretty=reference >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'log --pretty=reference is never decorated' '
|
||||||
|
git log --pretty="tformat:%h (%s, %as)" >expect &&
|
||||||
|
git log --decorate=short --pretty=reference >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'log --pretty=reference does not output reflog info' '
|
||||||
|
git log --walk-reflogs --pretty="tformat:%h (%s, %as)" >expect &&
|
||||||
|
git log --walk-reflogs --pretty=reference >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'log --pretty=reference is colored appropriately' '
|
||||||
|
git log --color=always --pretty="tformat:%C(auto)%h (%s, %as)" >expect &&
|
||||||
|
git log --color=always --pretty=reference >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Reference in New Issue
Block a user