fetch: add fetch.writeCommitGraph config setting

The commit-graph feature is now on by default, and is being written during 'git gc' by default. Typically, Git only writes a commit-graph when a 'git gc --auto' command passes the gc.auto setting to actualy do work. This means that a commit-graph will typically fall behind the commits that are being used every day. To stay updated with the latest commits, add a step to 'git fetch' to write a commit-graph after fetching new objects. The fetch.writeCommitGraph config setting enables writing a split commit-graph, so on average the cost of writing this file is very small. Occasionally, the commit-graph chain will collapse to a single level, and this could be slow for very large repos. For additional use, adjust the default to be true when feature.experimental is enabled. Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Derrick Stolee committed Sep 2, 2019 at 19:22 UTC 50f26bd035816c2bb79582b834d59b49292502a9
6 files changed +51
Documentation/config/feature.txt
+8
@@ -17,6 +17,14 @@ which can improve `git push` performance in repos with many files.
17 +
18 * `fetch.negotiationAlgorithm=skipping` may improve fetch negotiation times by
19 skipping more commits at a time, reducing the number of round trips.
20 ++
21 +* `fetch.writeCommitGraph=true` writes a commit-graph after every `git fetch`
22 +command that downloads a pack-file from a remote. Using the `--split` option,
23 +most executions will create a very small commit-graph file on top of the
24 +existing commit-graph file(s). Occasionally, these files will merge and the
25 +write may take longer. Having an updated commit-graph file helps performance
26 +of many Git commands, including `git merge-base`, `git push -f`, and
27 +`git log --graph`.
28
29 feature.manyFiles::
30 Enable config options that optimize for repos with many files in the
Documentation/config/fetch.txt
+10
@@ -69,3 +69,13 @@ fetch.showForcedUpdates::
69 Set to false to enable `--no-show-forced-updates` in
70 linkgit:git-fetch[1] and linkgit:git-pull[1] commands.
71 Defaults to true.
72 +
73 +fetch.writeCommitGraph::
74 + Set to true to write a commit-graph after every `git fetch` command
75 + that downloads a pack-file from a remote. Using the `--split` option,
76 + most executions will create a very small commit-graph file on top of
77 + the existing commit-graph file(s). Occasionally, these files will
78 + merge and the write may take longer. Having an updated commit-graph
79 + file helps performance of many Git commands, including `git merge-base`,
80 + `git push -f`, and `git log --graph`. Defaults to false, unless
81 + `feature.experimental` is true.
builtin/fetch.c
+15
@@ -23,6 +23,7 @@
23 #include "packfile.h"
24 #include "list-objects-filter-options.h"
25 #include "commit-reach.h"
26 +#include "commit-graph.h"
27
28 #define FORCED_UPDATES_DELAY_WARNING_IN_MS (10 * 1000)
29
@@ -1715,6 +1716,20 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
1716
1717 string_list_clear(&list, 0);
1718
1719 + prepare_repo_settings(the_repository);
1720 + if (the_repository->settings.fetch_write_commit_graph) {
1721 + int commit_graph_flags = COMMIT_GRAPH_SPLIT;
1722 + struct split_commit_graph_opts split_opts;
1723 + memset(&split_opts, 0, sizeof(struct split_commit_graph_opts));
1724 +
1725 + if (progress)
1726 + commit_graph_flags |= COMMIT_GRAPH_PROGRESS;
1727 +
1728 + write_commit_graph_reachable(get_object_directory(),
1729 + commit_graph_flags,
1730 + &split_opts);
1731 + }
1732 +
1733 close_object_store(the_repository->objects);
1734
1735 if (enable_auto_gc) {
repo-settings.c
+4
@@ -49,10 +49,14 @@ void prepare_repo_settings(struct repository *r)
49 UPDATE_DEFAULT_BOOL(r->settings.index_version, 4);
50 UPDATE_DEFAULT_BOOL(r->settings.core_untracked_cache, UNTRACKED_CACHE_WRITE);
51 }
52 + if (!repo_config_get_bool(r, "fetch.writecommitgraph", &value))
53 + r->settings.fetch_write_commit_graph = value;
54 if (!repo_config_get_bool(r, "feature.experimental", &value) && value) {
55 UPDATE_DEFAULT_BOOL(r->settings.pack_use_sparse, 1);
56 UPDATE_DEFAULT_BOOL(r->settings.fetch_negotiation_algorithm, FETCH_NEGOTIATION_SKIPPING);
57 + UPDATE_DEFAULT_BOOL(r->settings.fetch_write_commit_graph, 1);
58 }
59 + UPDATE_DEFAULT_BOOL(r->settings.fetch_write_commit_graph, 0);
60
61 /* Hack for test programs like test-dump-untracked-cache */
62 if (ignore_untracked_cache_config)
repository.h
+1
@@ -30,6 +30,7 @@ struct repo_settings {
30
31 int core_commit_graph;
32 int gc_write_commit_graph;
33 + int fetch_write_commit_graph;
34
35 int index_version;
36 enum untracked_cache_setting core_untracked_cache;
t/t5510-fetch.sh
+13
@@ -570,6 +570,19 @@ test_expect_success 'LHS of refspec follows ref disambiguation rules' '
570 )
571 '
572
573 +test_expect_success 'fetch.writeCommitGraph' '
574 + git clone three write &&
575 + (
576 + cd three &&
577 + test_commit new
578 + ) &&
579 + (
580 + cd write &&
581 + git -c fetch.writeCommitGraph fetch origin &&
582 + test_path_is_file .git/objects/info/commit-graphs/commit-graph-chain
583 + )
584 +'
585 +
586 # configured prune tests
587
588 set_config_tristate () {