From: "Ravi Mistry via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Junio C Hamano <gitster@pobox.com>,
Abhijeetsingh Meena <abhijeet040403@gmail.com>,
Kristoffer Haugsbakk <code@khaugsbakk.name>,
Phillip Wood <phillip.wood@dunelm.org.uk>,
Eric Sunshine <sunshine@sunshineco.com>,
Phillip Wood <phillip.wood123@gmail.com>,
Ravi Mistry <rmistry@google.com>
Subject: [PATCH v6 0/2] blame: ignore revs in .git-blame-ignore-revs by default
Date: Tue, 13 Oct 2026 20:22:06 +0000 [thread overview]
Message-ID: <pull.2224.v6.git.1791922928.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.2224.git.1789169384240.gitgitgadget@gmail.com>
This series teaches git-blame(1) and git-annotate(1) to automatically use
.git-blame-ignore-revs at the root of the working tree (or
HEAD:.git-blame-ignore-revs in bare repositories) by default if it exists,
without requiring manual blame.ignoreRevsFile configuration in every clone.
This restarts the stalled attempt in PR
https://github.com/gitgitgadget/git/pull/1809
(https://lore.kernel.org/git/pull.1809.v2.git.1728707867.gitgitgadget@gmail.com/)
and addresses https://github.com/gitgitgadget/git/issues/1494.
Changes since v5:
* Passed i->string from build_ignorelist() into parse_default_ignore_revs()
so the item string is used for both the working-tree path and "HEAD:" in
bare repositories, and changed cmd_blame() to set ->util = (void *)1 with
an explanatory comment instead of passing the scoreboard.
* Doc update: Changed "config option" / "configuration option" to
"configuration variable" in Documentation/blame-options.adoc and the
commit message.
Changes since v4:
* In non-bare repositories, Patch 2/2 now reads .git-blame-ignore-revs from
the root of the working tree (using open_nofollow(), S_ISREG(), and
IGNORE_REVS_MAX_FILE_SIZE) instead of HEAD:.git-blame-ignore-revs, while
continuing to use HEAD:.git-blame-ignore-revs in bare repositories
(matching the .mailmap model in read_mailmap()). This makes it ergonomic
to test uncommitted or untracked changes to .git-blame-ignore-revs
locally before committing.
* Updated the commit messages and documentation to justify the default
lookup and working-tree behavior on ergonomic grounds.
Changes since v3:
* Patch 2/2 caps the size of the default HEAD:.git-blame-ignore-revs blob
at IGNORE_REVS_MAX_FILE_SIZE (100MB, matching ATTR_MAX_FILE_SIZE from
3c50032ff5 ("attr: ignore overly large gitattributes files", 2022-12-01))
via odb_read_object_info() before calling odb_read_object(), skipping
oversized blobs with a warning without loading them into memory.
Changes since v2:
* Patch 2/2 uses sb->repo instead of the_repository in
parse_default_ignore_revs_blob().
Changes since v1:
* Split the series into two commits.
* Patch 1/2 hardens oidset_parse_file_carefully() in oidset.c and
peel_to_commit_oid() in builtin/blame.c before exposing them to
upstream-controlled content at a well-known path:
* Reject lines containing embedded NUL bytes via memchr() so trailing
bytes after a NUL cannot be silently ignored.
* Pass OBJECT_INFO_LOOKUP_REPLACE | OBJECT_INFO_SKIP_FETCH_OBJECT |
OBJECT_INFO_QUICK to odb_read_object_info_extended() and peel tags one
layer per iteration so missing OIDs or tag targets do not trigger lazy
promisor fetches or pack directory rescans in partial clones, and
verify that each peeled target matches the tag's declared type.
* Patch 2/2 reads the committed HEAD:.git-blame-ignore-revs blob (in both
bare and non-bare repositories) instead of reading a file from the
working tree, matching hosting platforms even when an untracked file is
present or a tracked one has local modifications. The tree entry is
checked with S_ISREG() so non-regular entries (such as committed
symlinks) are skipped, parsed in memory via
oidset_parse_buffer_carefully(), and bypassed without reading if cleared
via blame.ignoreRevsFile="" or --no-ignore-revs-file.
Ravi Mistry (2):
blame: harden ignore-revs parser and tag peeling
blame: ignore revs in .git-blame-ignore-revs by default
Documentation/blame-options.adoc | 9 +-
Documentation/config/blame.adoc | 10 +-
builtin/blame.c | 122 +++++++++++++-
oidset.c | 81 ++++++---
oidset.h | 9 +
t/t8013-blame-ignore-revs.sh | 271 +++++++++++++++++++++++++++++++
6 files changed, 467 insertions(+), 35 deletions(-)
base-commit: fa7f9290efe2bd22dd736689597b474b93798e11
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2224%2Frmistry%2Fblame-default-ignore-revs-v6
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2224/rmistry/blame-default-ignore-revs-v6
Pull-Request: https://github.com/gitgitgadget/git/pull/2224
Range-diff vs v5:
1: e9b2c1dae2 = 1: e9b2c1dae2 blame: harden ignore-revs parser and tag peeling
2: 605eb049a1 ! 2: 6039d4bc2d blame: ignore revs in .git-blame-ignore-revs by default
@@ Commit message
blame: ignore revs in .git-blame-ignore-revs by default
git-blame(1) can ignore a list of commits specified via
- --ignore-revs-file or the blame.ignoreRevsFile configuration option.
+ --ignore-revs-file or the blame.ignoreRevsFile configuration variable.
This is useful for skipping uninteresting revisions such as tree-wide
formatting changes, large-scale refactors, and code modernizations that
would otherwise obscure genuine historical authorship.
@@ Commit message
.git-blame-ignore-revs, if it exists, as the initial element in the
list of ignore-revs files. Similar to how read_mailmap() handles
.mailmap, consult .git-blame-ignore-revs at the root of the working
- tree when a working tree is available and fall back to the
- HEAD:.git-blame-ignore-revs blob in bare repositories. Reading from the
- working tree in non-bare repositories makes it ergonomic to prepare a
- new .git-blame-ignore-revs file or add revisions to an existing one and
- immediately test the effect with git-blame(1) before committing, while
- falling back to HEAD:.git-blame-ignore-revs allows bare repositories to
+ tree when a working tree is available, and otherwise consult the
+ HEAD:.git-blame-ignore-revs blob in bare repositories. Reading only
+ from the working tree in non-bare repositories makes it ergonomic to
+ prepare a new .git-blame-ignore-revs file, edit an existing one, or
+ remove a committed one and immediately test the effect with
+ git-blame(1) before committing, while consulting
+ HEAD:.git-blame-ignore-revs in bare repositories allows them to
respect the committed ignore list as well.
To ensure consistent precedence, override semantics, and safety when
@@ Documentation/blame-options.adoc: take effect.
+ processed after the default `.git-blame-ignore-revs` file at the root of
+ the working tree (or `HEAD:.git-blame-ignore-revs` in a bare repository),
+ if it exists, and any files specified with the `blame.ignoreRevsFile`
-+ config option. An empty file name, `""`, or `--no-ignore-revs-file` will
-+ clear the list of revs from previously processed files, including the
-+ default ignore-revs file.
++ configuration variable. An empty file name, `""`, or
++ `--no-ignore-revs-file` will clear the list of revs from previously
++ processed files, including the default ignore-revs file.
`--color-lines`::
Color line annotations in the default format differently if they come from
@@ builtin/blame.c: static int peel_to_commit_oid(struct object_id *oid_ret, void *
+#define IGNORE_REVS_MAX_FILE_SIZE (100 * 1024 * 1024)
+
+static void parse_default_ignore_revs_blob(struct blame_scoreboard *sb,
-+ const char *name)
++ const char *path)
+{
++ char *name = xstrfmt("HEAD:%s", path);
+ struct object_context oc;
+ struct object_id oid;
+ enum object_type type;
@@ builtin/blame.c: static int peel_to_commit_oid(struct object_id *oid_ret, void *
+
+out:
+ object_context_release(&oc);
++ free(name);
+}
+
+static void parse_default_ignore_revs_file(struct blame_scoreboard *sb,
@@ builtin/blame.c: static int peel_to_commit_oid(struct object_id *oid_ret, void *
+ free(path);
+}
+
-+static void parse_default_ignore_revs(struct blame_scoreboard *sb)
++static void parse_default_ignore_revs(struct blame_scoreboard *sb,
++ const char *name)
+{
+ if (repo_get_work_tree(sb->repo))
-+ parse_default_ignore_revs_file(sb, ".git-blame-ignore-revs");
++ parse_default_ignore_revs_file(sb, name);
+ else
-+ parse_default_ignore_revs_blob(sb, "HEAD:.git-blame-ignore-revs");
++ parse_default_ignore_revs_blob(sb, name);
+}
+
static void build_ignorelist(struct blame_scoreboard *sb,
@@ builtin/blame.c: static int peel_to_commit_oid(struct object_id *oid_ret, void *
+ for (idx = start_idx; idx < ignore_revs_file_list->nr; idx++) {
+ i = &ignore_revs_file_list->items[idx];
+ if (i->util)
-+ parse_default_ignore_revs(sb);
++ parse_default_ignore_revs(sb, i->string);
else
oidset_parse_file_carefully(&sb->ignore_list, i->string,
the_repository->hash_algo,
@@ builtin/blame.c: int cmd_blame(int argc,
const char *const *opt_usage = cmd_is_annotate ? annotate_opt_usage : blame_opt_usage;
setup_default_color_by_age();
++ /*
++ * An entry with a non-NULL .util member names the default
++ * ignore-revs file at the project root; see build_ignorelist().
++ */
+ string_list_append(&ignore_revs_file_list,
-+ ".git-blame-ignore-revs")->util = &sb;
++ ".git-blame-ignore-revs")->util = (void *)1;
repo_config(the_repository, git_blame_config, &output_option);
repo_init_revisions(the_repository, &revs, NULL);
revs.date_mode = blame_date_mode;
--
gitgitgadget
next prev parent reply other threads:[~2026-10-13 20:22 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-11 23:29 [PATCH] blame: default to ignoring revisions in .git-blame-ignore-revs Ravi Mistry via GitGitGadget
2026-09-30 14:59 ` Ravi Mistry
2026-10-05 15:37 ` Junio C Hamano
2026-10-05 21:12 ` Ravi Mistry
2026-10-07 17:43 ` Junio C Hamano
2026-10-07 18:07 ` Ravi Mistry
2026-10-08 21:07 ` [PATCH v2 0/2] blame: ignore revs in HEAD:.git-blame-ignore-revs by default Ravi Mistry via GitGitGadget
2026-10-08 21:07 ` [PATCH v2 1/2] blame: harden ignore-revs parser and tag peeling Ravi Mistry via GitGitGadget
2026-10-09 5:07 ` Junio C Hamano
2026-10-10 19:25 ` Ravi Mistry
2026-10-08 21:07 ` [PATCH v2 2/2] blame: ignore revs in HEAD:.git-blame-ignore-revs Ravi Mistry via GitGitGadget
2026-10-09 20:17 ` Junio C Hamano
2026-10-10 6:12 ` Eric Sunshine
2026-10-10 18:40 ` Ravi Mistry
2026-10-11 18:58 ` Junio C Hamano
2026-10-11 22:29 ` Ravi Mistry
2026-10-11 23:07 ` Junio C Hamano
2026-10-12 9:13 ` Phillip Wood
2026-10-12 16:38 ` Junio C Hamano
2026-10-12 19:21 ` Ravi Mistry
2026-10-12 21:13 ` Junio C Hamano
2026-10-13 14:48 ` Ravi Mistry
2026-10-11 22:21 ` [PATCH v3 0/2] blame: ignore revs in HEAD:.git-blame-ignore-revs by default Ravi Mistry via GitGitGadget
2026-10-11 22:21 ` [PATCH v3 1/2] blame: harden ignore-revs parser and tag peeling Ravi Mistry via GitGitGadget
2026-10-11 22:21 ` [PATCH v3 2/2] blame: ignore revs in HEAD:.git-blame-ignore-revs Ravi Mistry via GitGitGadget
2026-10-12 9:10 ` Phillip Wood
2026-10-12 15:48 ` Ravi Mistry
2026-10-12 19:17 ` [PATCH v4 0/2] blame: ignore revs in HEAD:.git-blame-ignore-revs by default Ravi Mistry via GitGitGadget
2026-10-12 19:17 ` [PATCH v4 1/2] blame: harden ignore-revs parser and tag peeling Ravi Mistry via GitGitGadget
2026-10-12 19:17 ` [PATCH v4 2/2] blame: ignore revs in HEAD:.git-blame-ignore-revs Ravi Mistry via GitGitGadget
2026-10-13 14:36 ` [PATCH v5 0/2] blame: ignore revs in .git-blame-ignore-revs by default Ravi Mistry via GitGitGadget
2026-10-13 14:36 ` [PATCH v5 1/2] blame: harden ignore-revs parser and tag peeling Ravi Mistry via GitGitGadget
2026-10-13 14:36 ` [PATCH v5 2/2] blame: ignore revs in .git-blame-ignore-revs by default Ravi Mistry via GitGitGadget
2026-10-13 17:30 ` [PATCH v5 0/2] " Junio C Hamano
2026-10-13 20:24 ` Ravi Mistry
2026-10-13 20:22 ` Ravi Mistry via GitGitGadget [this message]
2026-10-13 20:22 ` [PATCH v6 1/2] blame: harden ignore-revs parser and tag peeling Ravi Mistry via GitGitGadget
2026-10-13 20:22 ` [PATCH v6 2/2] blame: ignore revs in .git-blame-ignore-revs by default Ravi Mistry via GitGitGadget
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=pull.2224.v6.git.1791922928.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=abhijeet040403@gmail.com \
--cc=code@khaugsbakk.name \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=phillip.wood123@gmail.com \
--cc=phillip.wood@dunelm.org.uk \
--cc=rmistry@google.com \
--cc=sunshine@sunshineco.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
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