From: Toon Claes <toon@iotcl•com>
To: git@vger•kernel.org
Cc: Toon Claes <toon@iotcl•com>,
Kristoffer Haugsbakk <kristofferhaugsbakk@fastmail•com>,
Derrick Stolee <stolee@gmail•com>, Taylor Blau <me@ttaylorr•com>,
Junio C Hamano <gitster@pobox•com>
Subject: [PATCH v5 5/6] last-modified: support --extended format
Date: Wed, 16 Jul 2025 15:35:17 +0200 [thread overview]
Message-ID: <20250716133518.1788126-5-toon@iotcl.com> (raw)
In-Reply-To: <20250716133206.1787549-1-toon@iotcl.com>
On many forges when they display a tree view, they show which commit
last modified each entry of the tree. The command git-last-modified(1)
was introduced to feed the data for this view. But it only returned the
commit OID and the path.
Add option --extended to git-last-modified(1). In combination with the
path and the commit OID, it shows the raw commit data which can be used
directly to feed the tree view on a forge.
Signed-off-by: Toon Claes <toon@iotcl•com>
---
Documentation/git-last-modified.adoc | 46 ++++++++++++++++++++++++++++
builtin/last-modified.c | 46 +++++++++++++++++++++++-----
t/t8020-last-modified.sh | 22 +++++++++++++
3 files changed, 107 insertions(+), 7 deletions(-)
diff --git a/Documentation/git-last-modified.adoc b/Documentation/git-last-modified.adoc
index 89138ebeb7..af028c7b74 100644
--- a/Documentation/git-last-modified.adoc
+++ b/Documentation/git-last-modified.adoc
@@ -27,6 +27,14 @@ OPTIONS
-t::
Show tree entry itself as well as subtrees. Implies `-r`.
+-z::
+
+ Instead of separating output entries with newlines, use a NUL byte to
+ delimit them. See 'OUTPUT' for more details.
+
+--extended::
+ Show output in extended format. See 'OUTPUT' below.
+
<revision-range>::
Only traverse commits in the specified revision range. When no
`<revision-range>` is specified, it defaults to `HEAD` (i.e. the whole
@@ -39,6 +47,44 @@ OPTIONS
Without an optional path parameter, all files and subdirectories
in path traversal the are included in the output.
+OUTPUT
+------
+
+The default format prints for each path:
+
+ <oid> TAB <path> LF
+
+When the commit is at boundary, it's prefixed with a caret `^`.
+
+Or when option `-z` is given:
+
+ <oid> TAB <path> NUL
+
+When `--extended` is provided, the output will be in the format:
+
+ path SP <path> LF
+ commit SP <oid> LF
+ tree SP <tree> LF
+ parent SP <parent> LF
+ author SP <author> LF
+ <message>
+
+Each line of the commit message is indented with four spaces.
+
+Unless together with `--extended` option `-z` is given, then the output is:
+
+ path SP <path> NUL
+ commit SP <oid> LF
+ tree SP <tree> LF
+ parent SP <parent> LF
+ author SP <author> LF
+ <message>
+
+In this situation the commit message is not indented.
+
+A path containing SP or special characters is enclosed in double-quotes in the C
+style as needed, unless option `-z` is provided.
+
SEE ALSO
--------
linkgit:git-blame[1],
diff --git a/builtin/last-modified.c b/builtin/last-modified.c
index 466df04fba..71c66e8782 100644
--- a/builtin/last-modified.c
+++ b/builtin/last-modified.c
@@ -12,6 +12,7 @@
#include "object-name.h"
#include "object.h"
#include "parse-options.h"
+#include "pretty.h"
#include "quote.h"
#include "repository.h"
#include "revision.h"
@@ -39,6 +40,7 @@ struct last_modified {
struct hashmap paths;
struct rev_info rev;
int recursive, tree_in_recursive;
+ int extended;
};
static void last_modified_release(struct last_modified *lm)
@@ -244,14 +246,42 @@ static void show_entry(const char *path, const struct commit *commit, void *d)
{
struct last_modified *lm = d;
- if (commit->object.flags & BOUNDARY)
- putchar('^');
- printf("%s\t", oid_to_hex(&commit->object.oid));
+ if (lm->extended) {
+ struct strbuf buf = STRBUF_INIT;
+ struct pretty_print_context pp = { 0 };
- if (lm->rev.diffopt.line_termination)
- write_name_quoted(path, stdout, '\n');
- else
- printf("%s%c", path, '\0');
+ pp.abbrev = lm->rev.abbrev;
+ pp.date_mode = lm->rev.date_mode;
+ pp.date_mode_explicit = lm->rev.date_mode_explicit;
+ pp.fmt = CMIT_FMT_RAW;
+ pp.color = lm->rev.diffopt.use_color;
+ pp.rev = &lm->rev;
+ pp.no_indent = !lm->rev.diffopt.line_termination;
+
+ pretty_print_commit(&pp, commit, &buf);
+
+ printf("path ");
+ if (lm->rev.diffopt.line_termination)
+ write_name_quoted(path, stdout, '\n');
+ else
+ printf("%s%c", path, '\0');
+
+ printf("commit %s%s\n",
+ (commit->object.flags & BOUNDARY) ? "^" : "",
+ oid_to_hex(&commit->object.oid));
+ printf("%s%c", buf.buf, lm->rev.diffopt.line_termination);
+
+ strbuf_release(&buf);
+ } else {
+ printf("%s%s\t",
+ (commit->object.flags & BOUNDARY) ? "^" : "",
+ oid_to_hex(&commit->object.oid));
+
+ if (lm->rev.diffopt.line_termination)
+ write_name_quoted(path, stdout, '\n');
+ else
+ printf("%s%c", path, '\0');
+ }
fflush(stdout);
}
@@ -306,6 +336,8 @@ int cmd_last_modified(int argc, const char **argv, const char *prefix,
N_("recurse into subtrees")),
OPT_BOOL('t', "tree-in-recursive", &lm.tree_in_recursive,
N_("recurse into subtrees and include the tree entries too")),
+ OPT_BOOL(0, "extended", &lm.extended,
+ N_("extended format will include the commit message in the output")),
OPT_END()
};
diff --git a/t/t8020-last-modified.sh b/t/t8020-last-modified.sh
index 05c113a1f8..008ea708ab 100755
--- a/t/t8020-last-modified.sh
+++ b/t/t8020-last-modified.sh
@@ -48,6 +48,28 @@ test_expect_success 'last-modified non-recursive' '
EOF
'
+test_expect_success 'last-modified extended output' '
+ check_last_modified --extended <<-\EOF
+ path a
+ commit 3
+ tree e9a947598482012e54c9c5d3635d5b526b43a6a4
+ parent 2
+ author A U Thor <author@example•com> 1112912113 -0700
+ committer C O Mitter <committer@example•com> 1112912113 -0700
+
+ 3
+
+ path file
+ commit 1
+ tree f27c6ae26adb8396d3861976ba268f87ad8afa0b
+ author A U Thor <author@example•com> 1112911993 -0700
+ committer C O Mitter <committer@example•com> 1112911993 -0700
+
+ 1
+
+ EOF
+'
+
test_expect_success 'last-modified recursive' '
check_last_modified -r <<-\EOF
3 a/b/file
--
2.50.1.327.g047016eb4a
next prev parent reply other threads:[~2025-07-16 13:36 UTC|newest]
Thread overview: 135+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-22 17:46 [PATCH RFC 0/5] Introduce git-blame-tree(1) command Toon Claes
2025-04-22 17:46 ` [PATCH RFC 1/5] blame-tree: introduce new subcommand to blame files Toon Claes
2025-04-24 16:19 ` Junio C Hamano
2025-05-07 13:13 ` Toon Claes
2025-04-22 17:46 ` [PATCH RFC 2/5] t/perf: add blame-tree perf script Toon Claes
2025-04-22 17:46 ` [PATCH RFC 3/5] blame-tree: use Bloom filters when available Toon Claes
2025-04-22 17:46 ` [PATCH RFC 4/5] blame-tree: implement faster algorithm Toon Claes
2025-04-22 17:46 ` [PATCH RFC 5/5] blame-tree.c: initialize revision machinery without walk Toon Claes
2025-04-23 13:26 ` [PATCH RFC 0/5] Introduce git-blame-tree(1) command Marc Branchaud
2025-05-07 14:22 ` Toon Claes
2025-05-07 20:23 ` Marc Branchaud
2025-05-07 20:45 ` Junio C Hamano
2025-05-08 13:26 ` Marc Branchaud
2025-05-08 14:26 ` Junio C Hamano
2025-05-08 15:12 ` Marc Branchaud
2025-05-14 14:42 ` Toon Claes
2025-05-14 19:29 ` Junio C Hamano
2025-05-14 21:15 ` Marc Branchaud
2025-05-15 13:29 ` Patrick Steinhardt
2025-05-15 16:39 ` Junio C Hamano
2025-05-15 17:39 ` Marc Branchaud
2025-05-15 19:30 ` Jeff King
2025-05-16 4:38 ` Patrick Steinhardt
2025-05-20 8:49 ` Toon Claes
2025-05-15 17:30 ` Marc Branchaud
2025-05-16 4:30 ` Patrick Steinhardt
2025-05-14 21:15 ` Marc Branchaud
2025-05-07 20:49 ` Kristoffer Haugsbakk
2025-05-08 13:20 ` D. Ben Knoble
2025-05-08 13:26 ` Marc Branchaud
2025-05-08 13:18 ` D. Ben Knoble
2025-05-23 9:33 ` [PATCH RFC v2 0/5] Introduce git-last-modified(1) command Toon Claes
2025-05-23 9:33 ` [PATCH RFC v2 1/5] last-modified: new subcommand to show when files were last modified Toon Claes
2025-05-25 20:07 ` Justin Tobler
2025-06-05 8:32 ` Toon Claes
2025-05-27 10:39 ` Patrick Steinhardt
2025-06-13 9:34 ` Toon Claes
2025-06-13 9:52 ` Kristoffer Haugsbakk
2025-05-23 9:33 ` [PATCH RFC v2 2/5] t/perf: add last-modified perf script Toon Claes
2025-05-23 9:33 ` [PATCH RFC v2 3/5] last-modified: use Bloom filters when available Toon Claes
2025-05-27 10:40 ` Patrick Steinhardt
2025-06-13 11:05 ` Toon Claes
2025-05-23 9:33 ` [PATCH RFC v2 4/5] last-modified: implement faster algorithm Toon Claes
2025-05-27 10:39 ` Patrick Steinhardt
2025-05-23 9:33 ` [PATCH RFC v2 5/5] last-modified: initialize revision machinery without walk Toon Claes
2025-05-27 10:39 ` Patrick Steinhardt
2025-07-01 20:35 ` [PATCH RFC v2 0/5] Introduce git-last-modified(1) command Kristoffer Haugsbakk
2025-07-01 21:06 ` Junio C Hamano
2025-07-01 21:30 ` Kristoffer Haugsbakk
2025-07-02 13:00 ` Toon Claes
2025-07-09 15:53 ` Toon Claes
2025-07-09 17:00 ` Junio C Hamano
2025-06-30 18:49 ` [PATCH RFC v3 0/3] " Toon Claes
2025-06-30 18:49 ` [PATCH RFC v3 1/3] last-modified: new subcommand to show when files were last modified Toon Claes
2025-07-01 20:20 ` Kristoffer Haugsbakk
2025-07-02 11:51 ` Junio C Hamano
2025-06-30 18:49 ` [PATCH RFC v3 2/3] t/perf: add last-modified perf script Toon Claes
2025-06-30 18:49 ` [PATCH RFC v3 3/3] last-modified: use Bloom filters when available Toon Claes
2025-07-01 23:01 ` [PATCH RFC v3 0/3] Introduce git-last-modified(1) command Junio C Hamano
2025-07-09 15:26 ` [PATCH v4 " Toon Claes
2025-07-09 21:57 ` Junio C Hamano
2025-07-10 18:37 ` Junio C Hamano
2025-07-16 13:32 ` [PATCH v5 0/6] " Toon Claes
2025-07-16 13:35 ` [PATCH v5 1/6] last-modified: new subcommand to show when files were last modified Toon Claes
2025-07-18 0:02 ` Taylor Blau
2025-07-19 6:44 ` Jeff King
2025-07-22 15:50 ` Toon Claes
2025-08-01 9:09 ` Christian Couder
2025-08-01 16:59 ` Junio C Hamano
2025-07-16 13:35 ` [PATCH v5 2/6] t/perf: add last-modified perf script Toon Claes
2025-07-18 0:08 ` Taylor Blau
2025-07-22 15:52 ` Toon Claes
2025-07-16 13:35 ` [PATCH v5 3/6] last-modified: use Bloom filters when available Toon Claes
2025-07-18 0:16 ` Taylor Blau
2025-07-22 16:02 ` Toon Claes
2025-07-16 13:35 ` [PATCH v5 4/6] pretty: allow caller to disable indentation Toon Claes
2025-07-16 15:50 ` Junio C Hamano
2025-07-17 16:31 ` Toon Claes
2025-07-16 13:35 ` Toon Claes [this message]
2025-07-16 16:09 ` [PATCH v5 5/6] last-modified: support --extended format Junio C Hamano
2025-07-17 16:31 ` Toon Claes
2025-07-17 22:37 ` Junio C Hamano
2025-07-18 17:36 ` Junio C Hamano
2025-07-22 16:06 ` Toon Claes
2025-07-16 13:42 ` [PATCH v5 6/6] fixup! last-modified: use Bloom filters when available Toon Claes
2025-07-17 23:39 ` [PATCH v5 0/6] Introduce git-last-modified(1) command Taylor Blau
2025-07-22 15:35 ` Toon Claes
2025-07-30 17:59 ` Toon Claes
2025-07-31 7:45 ` Patrick Steinhardt
2025-07-30 17:55 ` [PATCH v6 0/4] " Toon Claes
2025-07-31 18:40 ` Junio C Hamano
2025-07-31 23:57 ` Junio C Hamano
2025-08-05 9:33 ` [PATCH v7 0/3] " Toon Claes
2025-08-05 14:34 ` Patrick Steinhardt
2025-08-05 16:21 ` Junio C Hamano
2025-08-05 16:34 ` Junio C Hamano
2025-08-05 16:55 ` Toon Claes
2025-08-05 17:20 ` Jean-Noël AVILA
2025-08-05 21:46 ` Junio C Hamano
2025-08-06 12:01 ` Toon Claes
2025-08-06 15:38 ` Junio C Hamano
2025-08-28 22:44 ` Junio C Hamano
2025-08-05 18:28 ` Junio C Hamano
2025-08-05 9:33 ` [PATCH v7 1/3] last-modified: new subcommand to show when files were last modified Toon Claes
2025-08-05 9:33 ` [PATCH v7 2/3] t/perf: add last-modified perf script Toon Claes
2025-08-05 9:33 ` [PATCH v7 3/3] last-modified: use Bloom filters when available Toon Claes
2025-07-30 17:55 ` [PATCH v6 1/4] last-modified: new subcommand to show when files were last modified Toon Claes
2025-07-31 6:42 ` Patrick Steinhardt
2025-08-01 16:22 ` Toon Claes
2025-08-01 17:09 ` Junio C Hamano
2025-08-04 6:34 ` Patrick Steinhardt
2025-08-04 17:14 ` Junio C Hamano
2025-08-05 5:35 ` Toon Claes
2025-08-01 20:34 ` Jean-Noël AVILA
2025-08-05 5:36 ` Toon Claes
2025-08-04 6:33 ` Patrick Steinhardt
2025-08-01 10:18 ` Christian Couder
2025-08-01 10:22 ` Patrick Steinhardt
2025-08-01 17:06 ` Junio C Hamano
2025-08-02 8:18 ` Christian Couder
2025-08-02 11:31 ` Christian Couder
2025-08-02 13:38 ` Christian Couder
2025-08-02 16:26 ` Junio C Hamano
2025-08-04 6:35 ` Patrick Steinhardt
2025-07-30 17:55 ` [PATCH v6 2/4] t/perf: add last-modified perf script Toon Claes
2025-07-30 17:55 ` [PATCH v6 3/4] commit-graph: export prepare_commit_graph() Toon Claes
2025-07-31 6:42 ` Patrick Steinhardt
2025-07-30 17:55 ` [PATCH v6 4/4] last-modified: use Bloom filters when available Toon Claes
2025-07-31 6:43 ` Patrick Steinhardt
2025-08-01 16:23 ` Toon Claes
2025-08-04 6:33 ` Patrick Steinhardt
2025-07-09 15:26 ` [PATCH v4 1/3] last-modified: new subcommand to show when files were last modified Toon Claes
2025-07-09 15:26 ` [PATCH v4 2/3] t/perf: add last-modified perf script Toon Claes
2025-07-09 15:26 ` [PATCH v4 3/3] last-modified: use Bloom filters when available Toon Claes
2025-07-16 13:35 ` [PATCH v5 6/6] fixup! " Toon Claes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250716133518.1788126-5-toon@iotcl.com \
--to=toon@iotcl$(echo .)com \
--cc=git@vger$(echo .)kernel.org \
--cc=gitster@pobox$(echo .)com \
--cc=kristofferhaugsbakk@fastmail$(echo .)com \
--cc=me@ttaylorr$(echo .)com \
--cc=stolee@gmail$(echo .)com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox