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:
Junio C Hamano
2019-12-10 13:11:42 -08:00
9 changed files with 134 additions and 26 deletions

View File

@ -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]]

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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 ()

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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