commit-graph: add new config for changed-paths & recommend it in scalar

The changed-path Bloom filters feature has proven stable and reliable over several years of use, delivering significant performance improvement for file history computation in large monorepos. Currently a user can opt-in to writing the changed-path Bloom filters using the "--changed-paths" option to "git commit-graph write". The filters will be persisted until the user drops the filters using the "--no-changed-paths" option. For this functionality, refer to 0087a87ba8 (commit-graph: persist existence of changed-paths, 2020-07-01). Large monorepos using Git's background maintenance to build and update commit-graph files could use an easy switch to enable this feature without a foreground computation. In this commit, we're proposing a new config option "commitGraph.changedPaths": * If "true", "git commit-graph write" will write Bloom filters, equivalent to passing "--changed-paths"; * If "false" or "unset", Bloom filters will be written during "git commit-graph write" only if the filters already exist in the current commit-graph file. This matches the default behaviour of "git commit-graph write" without any "--[no-]changed-paths" option. Note "false" can disable a previous "true" config value but doesn't imply "--no-changed-paths". This config will always respect the precedence of command line option "--[no-]changed-paths". We also set this new config as optional recommended config in scalar to turn on this feature for large repos. Helped-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Emily Yang <emilyyang.git@gmail.com> Acked-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Emily Yang committed Oct 17, 2025 at 20:58 UTC fafdf23b2f57bdf6a74513b3cc03902f0a8e954d
5 files changed +59 -1
Documentation/config/commitgraph.adoc
+11
@@ -8,6 +8,17 @@ commitGraph.maxNewFilters::
8 Specifies the default value for the `--max-new-filters` option of `git
9 commit-graph write` (c.f., linkgit:git-commit-graph[1]).
10
11 +commitGraph.changedPaths::
12 + If true, then `git commit-graph write` will compute and write
13 + changed-path Bloom filters by default, equivalent to passing
14 + `--changed-paths`. If false or unset, changed-paths Bloom filters will
15 + be written during `git commit-graph write` only if the filters already
16 + exist in the current commit-graph file. This matches the default
17 + behavior of `git commit-graph write` without any `--[no-]changed-paths`
18 + option. To rewrite a commit-graph file without any filters, use the
19 + `--no-changed-paths` option. Command-line option `--[no-]changed-paths`
20 + always takes precedence over this configuration. Defaults to unset.
21 +
22 commitGraph.readChangedPaths::
23 Deprecated. Equivalent to commitGraph.changedPathsVersion=-1 if true, and
24 commitGraph.changedPathsVersion=0 if false. (If commitGraph.changedPathVersion
Documentation/git-commit-graph.adoc
+1 -1
@@ -71,7 +71,7 @@ take a while on large repositories. It provides significant performance gains
71 for getting history of a directory or a file with `git log -- <path>`. If
72 this option is given, future commit-graph writes will automatically assume
73 that this option was intended. Use `--no-changed-paths` to stop storing this
74 -data.
74 +data. `--changed-paths` is implied by config `commitGraph.changedPaths=true`.
75 +
76 With the `--max-new-filters=<n>` option, generate at most `n` new Bloom
77 filters (if `--changed-paths` is specified). If `n` is `-1`, no limit is
builtin/commit-graph.c
+2
@@ -210,6 +210,8 @@ static int git_commit_graph_write_config(const char *var, const char *value,
210 {
211 if (!strcmp(var, "commitgraph.maxnewfilters"))
212 write_opts.max_new_filters = git_config_int(var, value, ctx->kvi);
213 + else if (!strcmp(var, "commitgraph.changedpaths"))
214 + opts.enable_changed_paths = git_config_bool(var, value) ? 1 : -1;
215 /*
216 * No need to fall-back to 'git_default_config', since this was already
217 * called in 'cmd_commit_graph()'.
scalar.c
+1
@@ -166,6 +166,7 @@ static int set_recommended_config(int reconfigure)
166 #endif
167 /* Optional */
168 { "status.aheadBehind", "false" },
169 + { "commitGraph.changedPaths", "true" },
170 { "commitGraph.generationVersion", "1" },
171 { "core.autoCRLF", "false" },
172 { "core.safeCRLF", "false" },
t/t5318-commit-graph.sh
+44
@@ -946,4 +946,48 @@ test_expect_success 'stale commit cannot be parsed when traversing graph' '
946 )
947 '
948
949 +test_expect_success 'config commitGraph.changedPaths acts like --changed-paths' '
950 + git init config-changed-paths &&
951 + (
952 + cd config-changed-paths &&
953 +
954 + # commitGraph.changedPaths is not set and it should not write Bloom filters
955 + test_commit first &&
956 + GIT_PROGRESS_DELAY=0 git commit-graph write --reachable --progress 2>error &&
957 + test_grep ! "Bloom filters" error &&
958 +
959 + # Set commitGraph.changedPaths to true and it should write Bloom filters
960 + test_commit second &&
961 + git config commitGraph.changedPaths true &&
962 + GIT_PROGRESS_DELAY=0 git commit-graph write --reachable --progress 2>error &&
963 + test_grep "Bloom filters" error &&
964 +
965 + # Add one more config commitGraph.changedPaths as false to disable the previous true config value
966 + # It should still write Bloom filters due to existing filters
967 + test_commit third &&
968 + git config --add commitGraph.changedPaths false &&
969 + GIT_PROGRESS_DELAY=0 git commit-graph write --reachable --progress 2>error &&
970 + test_grep "Bloom filters" error &&
971 +
972 + # commitGraph.changedPaths is still false and command line options should take precedence
973 + test_commit fourth &&
974 + GIT_PROGRESS_DELAY=0 git commit-graph write --no-changed-paths --reachable --progress 2>error &&
975 + test_grep ! "Bloom filters" error &&
976 + GIT_PROGRESS_DELAY=0 git commit-graph write --reachable --progress 2>error &&
977 + test_grep ! "Bloom filters" error &&
978 +
979 + # commitGraph.changedPaths is all cleared and then set to false again, command line options should take precedence
980 + test_commit fifth &&
981 + git config --unset-all commitGraph.changedPaths &&
982 + git config commitGraph.changedPaths false &&
983 + GIT_PROGRESS_DELAY=0 git commit-graph write --changed-paths --reachable --progress 2>error &&
984 + test_grep "Bloom filters" error &&
985 +
986 + # commitGraph.changedPaths is still false and it should write Bloom filters due to existing filters
987 + test_commit sixth &&
988 + GIT_PROGRESS_DELAY=0 git commit-graph write --reachable --progress 2>error &&
989 + test_grep "Bloom filters" error
990 + )
991 +'
992 +
993 test_done