From 4ed930cab1b7f5e9738e73c7b9374d927a8acd94 Mon Sep 17 00:00:00 2001 From: Abhijeetsingh Meena Date: Mon, 7 Oct 2024 21:58:19 +0530 Subject: [PATCH 1/2] blame: respect .git-blame-ignore-revs automatically MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-blame(1) can ignore a list of commits with `--ignore-revs-file`. This is useful for marking uninteresting commits like formatting changes, refactors and whatever else should not be “blamed”. Some projects even version control this file so that all contributors can use it; the conventional name is `.git-blame-ignore-revs`. But each user still has to opt-in to the standard ignore list, either with this option or with the config `blame.ignoreRevsFile`. Let’s teach git-blame(1) to respect this conventional file in order to streamline the process. Signed-off-by: Abhijeetsingh Meena --- builtin/blame.c | 8 ++++++++ t/t8015-blame-default-ignore-revs.sh | 26 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100755 t/t8015-blame-default-ignore-revs.sh diff --git a/builtin/blame.c b/builtin/blame.c index e407a22da3bacf..1eddabaf60f4ea 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -1105,6 +1105,14 @@ int cmd_blame(int argc, add_pending_object(&revs, &head_commit->object, "HEAD"); } + /* + * By default, add .git-blame-ignore-revs to the list of files + * containing revisions to ignore if it exists. + */ + if (access(".git-blame-ignore-revs", F_OK) == 0) { + string_list_append(&ignore_revs_file_list, ".git-blame-ignore-revs"); + } + init_scoreboard(&sb); sb.revs = &revs; sb.contents_from = contents_from; diff --git a/t/t8015-blame-default-ignore-revs.sh b/t/t8015-blame-default-ignore-revs.sh new file mode 100755 index 00000000000000..d4ab686f14d2ad --- /dev/null +++ b/t/t8015-blame-default-ignore-revs.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +test_description='default revisions to ignore when blaming' + +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh + +test_expect_success 'blame: default-ignore-revs-file' ' + test_commit first-commit hello.txt hello && + + echo world >>hello.txt && + test_commit second-commit hello.txt && + + sed "1s/hello/hi/" hello.txt.tmp && + mv hello.txt.tmp hello.txt && + test_commit third-commit hello.txt && + + git rev-parse HEAD >ignored-file && + git blame --ignore-revs-file=ignored-file hello.txt >expect && + git rev-parse HEAD >.git-blame-ignore-revs && + git blame hello.txt >actual && + + test_cmp expect actual +' + +test_done From 8d2fa3af7964dacd09d454de4325b1d5eb7a5c3d Mon Sep 17 00:00:00 2001 From: Abhijeetsingh Meena Date: Fri, 11 Oct 2024 14:09:30 +0530 Subject: [PATCH 2/2] blame: introduce --override-ignore-revs to bypass ignore revisions list The git blame command can ignore a list of revisions specified either through the --ignore-revs-file option or the blame.ignoreRevsFile configuration. This feature is useful for excluding irrelevant commits, such as formatting changes or large refactors, from blame annotations. However, users may encounter cases where they need to temporarily override these configurations to inspect all commits, even those excluded by the ignore list. Currently, there is no simple way to bypass all ignore revisions settings in one go. This patch introduces the --override-ignore-revs option (or -O), which allows users to easily bypass the --ignore-revs-file option, --ignore-rev option and the blame.ignoreRevsFile configuration. When this option is used, git blame will completely disregard all configured ignore revisions lists. The motivation behind this feature is to provide users with more flexibility when dealing with large codebases that rely on .git-blame-ignore-revs files for shared configurations, while still allowing them to disable the ignore list when necessary for troubleshooting or deeper inspections. Signed-off-by: Abhijeetsingh Meena --- builtin/blame.c | 8 +++++++- t/t8016-blame-override-ignore-revs.sh | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100755 t/t8016-blame-override-ignore-revs.sh diff --git a/builtin/blame.c b/builtin/blame.c index 1eddabaf60f4ea..956520edcd9a13 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -69,6 +69,7 @@ static int coloring_mode; static struct string_list ignore_revs_file_list = STRING_LIST_INIT_DUP; static int mark_unblamable_lines; static int mark_ignored_lines; +static int override_ignore_revs = 0; static struct date_mode blame_date_mode = { DATE_ISO8601 }; static size_t blame_date_width; @@ -901,6 +902,7 @@ int cmd_blame(int argc, OPT_BIT('w', NULL, &xdl_opts, N_("ignore whitespace differences"), XDF_IGNORE_WHITESPACE), OPT_STRING_LIST(0, "ignore-rev", &ignore_rev_list, N_("rev"), N_("ignore when blaming")), OPT_STRING_LIST(0, "ignore-revs-file", &ignore_revs_file_list, N_("file"), N_("ignore revisions from ")), + OPT_BOOL('O', "override-ignore-revs", &override_ignore_revs, N_("override all configurations that exclude revisions")), OPT_BIT(0, "color-lines", &output_option, N_("color redundant metadata from previous line differently"), OUTPUT_COLOR_LINE), OPT_BIT(0, "color-by-age", &output_option, N_("color lines by age"), OUTPUT_SHOW_AGE_WITH_COLOR), OPT_BIT(0, "minimal", &xdl_opts, N_("spend extra cycles to find better match"), XDF_NEED_MINIMAL), @@ -1119,7 +1121,11 @@ int cmd_blame(int argc, sb.reverse = reverse; sb.repo = the_repository; sb.path = path; - build_ignorelist(&sb, &ignore_revs_file_list, &ignore_rev_list); + + if (!override_ignore_revs) { + build_ignorelist(&sb, &ignore_revs_file_list, &ignore_rev_list); + } + string_list_clear(&ignore_revs_file_list, 0); string_list_clear(&ignore_rev_list, 0); setup_scoreboard(&sb, &o); diff --git a/t/t8016-blame-override-ignore-revs.sh b/t/t8016-blame-override-ignore-revs.sh new file mode 100755 index 00000000000000..b5899729f8e08d --- /dev/null +++ b/t/t8016-blame-override-ignore-revs.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +test_description='default revisions to ignore when blaming' + +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh + +test_expect_success 'blame: override-ignore-revs' ' + test_commit first-commit hello.txt hello && + + echo world >>hello.txt && + test_commit second-commit hello.txt && + + sed "1s/hello/hi/" hello.txt.tmp && + mv hello.txt.tmp hello.txt && + test_commit third-commit hello.txt && + + git blame hello.txt >expect && + git rev-parse HEAD >.git-blame-ignore-revs && + git blame -O hello.txt >actual && + + test_cmp expect actual +' + +test_done