From 4222b7cd950d6e19d975788d2881919adf664992 Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Fri, 14 Nov 2025 14:22:58 +0100 Subject: [PATCH 1/4] Expand and enhance git-last-modified(1) documentation Option `-z` and `--max-depth` are not documented in git-last-modified(1) while they are pretty crucial. In these patches documentation is added in the man page and the `-h` output. --- b4-submit-tracking --- # This section is used internally by b4 prep for tracking purposes. { "series": { "revision": 1, "change-id": "20251114-toon-last-modified-zzzz-af9c1be74fc4", "prefixes": [] } } -- GitLab From 27aca91086717bef704caf3f9a6a29ed35b607b4 Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Fri, 14 Nov 2025 15:08:28 +0100 Subject: [PATCH 2/4] last-modified: handle and document NUL termination When option `-z` is provided to git-last-modified(1), each line is separated with a NUL instead of a newline. Document this properly and handle parsing of the option in the builtin itself. Signed-off-by: Toon Claes --- Documentation/git-last-modified.adoc | 21 ++++++++++++++++++++- builtin/last-modified.c | 13 ++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/Documentation/git-last-modified.adoc b/Documentation/git-last-modified.adoc index 602843e095..cd4a5040b0 100644 --- a/Documentation/git-last-modified.adoc +++ b/Documentation/git-last-modified.adoc @@ -9,7 +9,7 @@ git-last-modified - EXPERIMENTAL: Show when files were last modified SYNOPSIS -------- [synopsis] -git last-modified [--recursive] [--show-trees] [] [[--] ...] +git last-modified [--recursive] [--show-trees] [-z] [] [[--] ...] DESCRIPTION ----------- @@ -32,6 +32,9 @@ OPTIONS Show tree entries even when recursing into them. It has no effect without `--recursive`. +`-z`:: + Terminate each line with a _NUL_ rather than a newline. + ``:: Only traverse commits in the specified revision range. When no `` is specified, it defaults to `HEAD` (i.e. the whole @@ -44,6 +47,22 @@ OPTIONS Without an optional path parameter, all files and subdirectories in path traversal the are included in the output. +OUTPUT +------ + +The output is in the format: + +------------ + TAB LF +------------ + +If a path contains any special characters, the path is C-style quoted. To +avoid quoting, pass option `-z` to terminate each line with a NUL. + +------------ + TAB NUL +------------ + SEE ALSO -------- linkgit:git-blame[1], diff --git a/builtin/last-modified.c b/builtin/last-modified.c index b0ecbdc540..9206bbdc1d 100644 --- a/builtin/last-modified.c +++ b/builtin/last-modified.c @@ -23,6 +23,10 @@ #define PARENT1 (1u<<16) /* used instead of SEEN */ #define PARENT2 (1u<<17) /* used instead of BOTTOM, BOUNDARY */ +#define LAST_MODIFIED_INIT { \ + .line_termination = '\n', \ +} + struct last_modified_entry { struct hashmap_entry hashent; struct object_id oid; @@ -55,6 +59,7 @@ struct last_modified { struct rev_info rev; bool recursive; bool show_trees; + int line_termination; const char **all_paths; size_t all_paths_nr; @@ -165,7 +170,7 @@ static void last_modified_emit(struct last_modified *lm, putchar('^'); printf("%s\t", oid_to_hex(&commit->object.oid)); - if (lm->rev.diffopt.line_termination) + if (lm->line_termination) write_name_quoted(path, stdout, '\n'); else printf("%s%c", path, '\0'); @@ -507,10 +512,10 @@ int cmd_last_modified(int argc, const char **argv, const char *prefix, struct repository *repo) { int ret; - struct last_modified lm = { 0 }; + struct last_modified lm = LAST_MODIFIED_INIT; const char * const last_modified_usage[] = { - N_("git last-modified [--recursive] [--show-trees] " + N_("git last-modified [--recursive] [--show-trees] [-z] " "[] [[--] ...]"), NULL }; @@ -520,6 +525,8 @@ int cmd_last_modified(int argc, const char **argv, const char *prefix, N_("recurse into subtrees")), OPT_BOOL('t', "show-trees", &lm.show_trees, N_("show tree entries when recursing into subtrees")), + OPT_SET_INT('z', NULL, &lm.line_termination, + N_("lines are separated with NUL character"), '\0'), OPT_END() }; -- GitLab From 28f6476eca78844147f91ba423afbe59038af848 Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Tue, 25 Nov 2025 21:34:19 +0100 Subject: [PATCH 3/4] last-modified: document option --max-depth Option --max-depth is supported by git-last-modified(1), because it was added to the diff machinery in a1dfa5448d (diff: teach tree-diff a max-depth parameter, 2025-08-07). This option is useful for everyday use of the git-last-modified(1) command, so document it's existence in the man page and `-h` output. Signed-off-by: Toon Claes --- Documentation/git-last-modified.adoc | 9 ++++++++- builtin/last-modified.c | 12 +++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Documentation/git-last-modified.adoc b/Documentation/git-last-modified.adoc index cd4a5040b0..8409daebe9 100644 --- a/Documentation/git-last-modified.adoc +++ b/Documentation/git-last-modified.adoc @@ -9,7 +9,8 @@ git-last-modified - EXPERIMENTAL: Show when files were last modified SYNOPSIS -------- [synopsis] -git last-modified [--recursive] [--show-trees] [-z] [] [[--] ...] +git last-modified [--recursive] [--show-trees] [--max-depth=] [-z] + [] [[--] ...] DESCRIPTION ----------- @@ -32,6 +33,12 @@ OPTIONS Show tree entries even when recursing into them. It has no effect without `--recursive`. +`--max-depth=`:: + For each pathspec given on the command line, descend at most `` + levels of directories. A negative value means no limit. + Setting a positive value implies `--recursive`. + Cannot be combined with wildcards in the pathspec. + `-z`:: Terminate each line with a _NUL_ rather than a newline. diff --git a/builtin/last-modified.c b/builtin/last-modified.c index 9206bbdc1d..ccb7ff66d4 100644 --- a/builtin/last-modified.c +++ b/builtin/last-modified.c @@ -25,6 +25,7 @@ #define LAST_MODIFIED_INIT { \ .line_termination = '\n', \ + .max_depth = -1, \ } struct last_modified_entry { @@ -60,6 +61,7 @@ struct last_modified { bool recursive; bool show_trees; int line_termination; + int max_depth; const char **all_paths; size_t all_paths_nr; @@ -487,6 +489,12 @@ static int last_modified_init(struct last_modified *lm, struct repository *r, lm->rev.diffopt.flags.recursive = lm->recursive; lm->rev.diffopt.flags.tree_in_recursive = lm->show_trees; + if (lm->max_depth >= 0) { + lm->rev.diffopt.flags.recursive = 1; + lm->rev.diffopt.max_depth = lm->max_depth; + lm->rev.diffopt.max_depth_valid = 1; + } + argc = setup_revisions(argc, argv, &lm->rev, NULL); if (argc > 1) { error(_("unknown last-modified argument: %s"), argv[1]); @@ -515,7 +523,7 @@ int cmd_last_modified(int argc, const char **argv, const char *prefix, struct last_modified lm = LAST_MODIFIED_INIT; const char * const last_modified_usage[] = { - N_("git last-modified [--recursive] [--show-trees] [-z] " + N_("git last-modified [--recursive] [--show-trees] [--max-depth=] [-z] " "[] [[--] ...]"), NULL }; @@ -525,6 +533,8 @@ int cmd_last_modified(int argc, const char **argv, const char *prefix, N_("recurse into subtrees")), OPT_BOOL('t', "show-trees", &lm.show_trees, N_("show tree entries when recursing into subtrees")), + OPT_INTEGER_F(0, "max-depth", &lm.max_depth, + N_("maximum tree depth to recurse"), PARSE_OPT_NONEG), OPT_SET_INT('z', NULL, &lm.line_termination, N_("lines are separated with NUL character"), '\0'), OPT_END() -- GitLab From 201699d8cb9fb729e91e7fcf18df90de400115a8 Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Tue, 25 Nov 2025 21:31:12 +0100 Subject: [PATCH 4/4] last-modified: better document how depth in handled By default git-last-modified(1) only shows information about paths at the root level. This can be confusing. Clarify the command's behavior in the documentation. Signed-off-by: Toon Claes --- Documentation/git-last-modified.adoc | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/Documentation/git-last-modified.adoc b/Documentation/git-last-modified.adoc index 8409daebe9..36f72954a5 100644 --- a/Documentation/git-last-modified.adoc +++ b/Documentation/git-last-modified.adoc @@ -27,6 +27,7 @@ OPTIONS `--recursive`:: Instead of showing tree entries, step into subtrees and show all entries inside them recursively. + See the section "NOTES ABOUT DEPTH" below for more details. `-t`:: `--show-trees`:: @@ -38,6 +39,7 @@ OPTIONS levels of directories. A negative value means no limit. Setting a positive value implies `--recursive`. Cannot be combined with wildcards in the pathspec. + See the section "NOTES ABOUT DEPTH" below for more details. `-z`:: Terminate each line with a _NUL_ rather than a newline. @@ -70,6 +72,47 @@ avoid quoting, pass option `-z` to terminate each line with a NUL. TAB NUL ------------ +NOTES ABOUT DEPTH +----------------- + +By default this command only shows information about paths at the root level. +When a path that lives in a subtree is provided, information about the top-level +subtree is printed. For example: + +------------ +$ git last-modified -- sub/file + +abcd1234abcd1234abcd1234abcd1234abcd1234 sub +------------ + +To get details about the exact path in a subtree, add option `--recursive`: + +------------ +$ git last-modified --recursive -- sub/file + +5678abca5678abca5678abca5678abca5678abca sub/file +------------ + +This comes with a downside. When the path provided is a tree itself, with +option `--recursive` all paths in that subtree are printed too: + +------------ +$ git last-modified --recursive -- sub/subsub + +1234cdef1234cdef1234cdef1234cdef1234cdef sub/subsub/a +3456cdef3456cdef3456cdef3456cdef3456cdef sub/subsub/b +5678abcd5678abcd5678abcd5678abcd5678abcd sub/subsub/c +------------ + +To stop this command from traversing deeper into trees, add option +`--max-depth=0`: + +------------ +$ git last-modified --recursive --max-depth=0 -- sub/subsub + +3456def3456def3456def3456def3456def3456b sub/subsub +------------ + SEE ALSO -------- linkgit:git-blame[1], -- GitLab