Skip to content

Commit 9fef65a

Browse files
committed
Merge branch 'kh/name-rev-custom-format' into seen
A new builtin "git format-rev" is introduced for pretty formatting one revision expression per line or commit object names found in running text. * kh/name-rev-custom-format: SQUASH??? SQUASH??? format-rev: introduce builtin for on-demand pretty formatting name-rev: make dedicated --annotate-stdin --name-only test name-rev: factor code for sharing with a new command name-rev: run clang-format before factoring code name-rev: wrap both blocks in braces
2 parents 1942770 + c158425 commit 9fef65a

9 files changed

Lines changed: 511 additions & 26 deletions

File tree

Documentation/git-format-rev.adoc

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
git-format-rev(1)
2+
=================
3+
4+
NAME
5+
----
6+
git-format-rev - EXPERIMENTAL: Pretty format revisions on demand
7+
8+
9+
SYNOPSIS
10+
--------
11+
[synopsis]
12+
(EXPERIMENTAL!) git format-rev --stdin-mode=<mode> --format=<pretty> [--notes=<ref>]
13+
14+
DESCRIPTION
15+
-----------
16+
17+
Pretty format revisions from standard input.
18+
19+
THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
20+
21+
OPTIONS
22+
-------
23+
24+
`--stdin-mode=<mode>`::
25+
How to interpret standard input data:
26+
+
27+
--
28+
`revs`:: Each line is interpreted as a commit. Any kind of revision
29+
expression can be used (see linkgit:gitrevisions[7]). Annotated
30+
tags are peeled (see linkgit:gitglossary[7]).
31+
+
32+
The argument `rev` is also accepted.
33+
`text`:: Formats all commit object names found in freeform text. These
34+
must the full object names, i.e. abbreviated hexidecimal object
35+
names will not be interpreted.
36+
--
37+
38+
`--format=<pretty>`::
39+
Pretty format string.
40+
41+
`--notes=<ref>`::
42+
`--no-notes`::
43+
Custom notes ref. Notes are displayed when using the `%N`
44+
atom. See linkgit:git-notes[1].
45+
46+
EXAMPLES
47+
--------
48+
49+
The command linkgit:git-last-modified[1] shows the commit that each file
50+
was last modified in.
51+
52+
----
53+
$ git last-modified -- README.md Makefile
54+
7798034171030be0909c56377a4e0e10e6d2df93 Makefile
55+
c50fbb2dd225e7e82abba4380423ae105089f4d7 README.md
56+
----
57+
58+
We can pipe the result to this command in order to replace the object
59+
name with the commit author.
60+
61+
----
62+
$ git last-modified -- README.md Makefile |
63+
git format-rev --stdin-mode=text --format=%an
64+
Junio C Hamano Makefile
65+
Todd Zullinger README.md
66+
----
67+
68+
Another example is _formatting commits in commit messages_. Given this commit message:
69+
70+
----
71+
Fix off-by-one error
72+
73+
Fix off-by-one error introduced in
74+
e83c5163316f89bfbde7d9ab23ca2e25604af290.
75+
76+
We thought we fixed this in 5569bf9bbedd63a00780fc5c110e0cfab3aa97b9 but
77+
that only covered 1/3 of the faulty cases.
78+
----
79+
80+
We can format the commits and use par(1) to reflow the text, say in a
81+
`commit-msg` hook:
82+
83+
----
84+
$ git config set hook.reference-commits.event commit-msg
85+
$ git config set hook.reference-commits.command reference-commits
86+
$ cat $(which reference-commits)
87+
#/bin/sh
88+
89+
msg="$1"
90+
rewritten=$(mktemp)
91+
git format-rev --stdin-mode=text --format=reference <"$msg" |
92+
par >"$rewritten"
93+
mv "$rewritten" "$msg"
94+
----
95+
96+
Which will produce something like this:
97+
98+
----
99+
Fix off-by-one error
100+
101+
Fix off-by-one error introduced in e83c5163316 (Implement better memory
102+
allocator, 2005-04-07).
103+
104+
We thought we fixed this in 5569bf9bbed (Fix memory allocator,
105+
2005-06-22) but that only covered 1/3 of the faulty cases.
106+
----
107+
108+
DISCUSSION
109+
----------
110+
111+
This command lets you format any number of revisions in any order
112+
through one command invocation. Consider the
113+
linkgit:git-last-modified[1] case from the "EXAMPLES" section above:
114+
115+
1. There might be hundreds of files
116+
2. Commits can be repeated, i.e. two or more files were last modified in
117+
the same commit
118+
119+
Two widely-used commands which pretty formats commits are
120+
linkgit:git-log[1] and linkgit:git-show[1]. It turns out that they are
121+
not a good fit for the above use case.
122+
123+
- The output of linkgit:git-last-modified[1] would have to be processed
124+
in stages since you need to transform the first column separately and
125+
then link the author to the filename. But this is surmountable.
126+
- You can feed each commit to `git show` or `git show --no-walk -1`. But
127+
that means that you need to create a process for each line.
128+
- Let’s say that you want to use one process, not one per line. So you
129+
want to feed all the commits to the command. Now you face the problem
130+
that you have to feed all the commits to the commands before you get
131+
any output (this is also the case for the `--stdin` modes). In other
132+
words, you cannot loop through each line, get the author for the
133+
commit, and output the author and the filename. You need to feed all
134+
the commits, get back all the output, and match the output with the
135+
filename.
136+
- But the next problem is that commands will deduplicate the input and
137+
only output one commit one single time only. Thus you cannot make the
138+
output order match the input order, since a commit could have been
139+
repeated in the original input.
140+
141+
In short, it is straightforward to use these two commands if you use one
142+
process per line. It is much more work if you just want to use one
143+
process, but still doable. In contrast, this problem is just another
144+
shell pipeline with this command.
145+
146+
GIT
147+
---
148+
Part of the linkgit:git[1] suite

Documentation/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ manpages = {
5555
'git-for-each-ref.adoc' : 1,
5656
'git-for-each-repo.adoc' : 1,
5757
'git-format-patch.adoc' : 1,
58+
'git-format-rev.adoc' : 1,
5859
'git-fsck-objects.adoc' : 1,
5960
'git-fsck.adoc' : 1,
6061
'git-fsmonitor--daemon.adoc' : 1,

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,7 @@ BUILT_INS += $(patsubst builtin/%.o,git-%$X,$(BUILTIN_OBJS))
896896
BUILT_INS += git-cherry$X
897897
BUILT_INS += git-cherry-pick$X
898898
BUILT_INS += git-format-patch$X
899+
BUILT_INS += git-format-rev$X
899900
BUILT_INS += git-fsck-objects$X
900901
BUILT_INS += git-init$X
901902
BUILT_INS += git-maintenance$X

builtin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix, struct re
189189
int cmd_for_each_ref(int argc, const char **argv, const char *prefix, struct repository *repo);
190190
int cmd_for_each_repo(int argc, const char **argv, const char *prefix, struct repository *repo);
191191
int cmd_format_patch(int argc, const char **argv, const char *prefix, struct repository *repo);
192+
int cmd_format_rev(int argc, const char **argv, const char *prefix, struct repository *repo);
192193
int cmd_fsck(int argc, const char **argv, const char *prefix, struct repository *repo);
193194
int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix, struct repository *repo);
194195
int cmd_gc(int argc, const char **argv, const char *prefix, struct repository *repo);

0 commit comments

Comments
 (0)