gc: automatically write commit-graph files

The commit-graph file is a very helpful feature for speeding up git
operations. In order to make it more useful, make it possible to
write the commit-graph file during standard garbage collection
operations.

Add a 'gc.commitGraph' config setting that triggers writing a
commit-graph file after any non-trivial 'git gc' command. Defaults to
false while the commit-graph feature matures. We specifically do not
want to have this on by default until the commit-graph feature is fully
integrated with history-modifying features like shallow clones.

Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Derrick Stolee 2018-06-27 09:24:46 -04:00 committed by Junio C Hamano
parent 59fb87701f
commit d5d5d7b641
4 changed files with 30 additions and 3 deletions

View File

@ -904,9 +904,12 @@ core.notesRef::
This setting defaults to "refs/notes/commits", and it can be overridden by This setting defaults to "refs/notes/commits", and it can be overridden by
the `GIT_NOTES_REF` environment variable. See linkgit:git-notes[1]. the `GIT_NOTES_REF` environment variable. See linkgit:git-notes[1].
core.commitGraph:: gc.commitGraph::
Enable git commit graph feature. Allows reading from the If true, then gc will rewrite the commit-graph file when
commit-graph file. linkgit:git-gc[1] is run. When using linkgit:git-gc[1]
'--auto' the commit-graph will be updated if housekeeping is
required. Default is false. See linkgit:git-commit-graph[1]
for details.
core.sparseCheckout:: core.sparseCheckout::
Enable "sparse checkout" feature. See section "Sparse checkout" in Enable "sparse checkout" feature. See section "Sparse checkout" in

View File

@ -136,6 +136,10 @@ The optional configuration variable `gc.packRefs` determines if
it within all non-bare repos or it can be set to a boolean value. it within all non-bare repos or it can be set to a boolean value.
This defaults to true. This defaults to true.
The optional configuration variable `gc.commitGraph` determines if
'git gc' should run 'git commit-graph write'. This can be set to a
boolean value. This defaults to false.
The optional configuration variable `gc.aggressiveWindow` controls how The optional configuration variable `gc.aggressiveWindow` controls how
much time is spent optimizing the delta compression of the objects in much time is spent optimizing the delta compression of the objects in
the repository when the --aggressive option is specified. The larger the repository when the --aggressive option is specified. The larger

View File

@ -20,6 +20,7 @@
#include "sigchain.h" #include "sigchain.h"
#include "argv-array.h" #include "argv-array.h"
#include "commit.h" #include "commit.h"
#include "commit-graph.h"
#include "packfile.h" #include "packfile.h"
#include "object-store.h" #include "object-store.h"
#include "pack.h" #include "pack.h"
@ -40,6 +41,7 @@ static int aggressive_depth = 50;
static int aggressive_window = 250; static int aggressive_window = 250;
static int gc_auto_threshold = 6700; static int gc_auto_threshold = 6700;
static int gc_auto_pack_limit = 50; static int gc_auto_pack_limit = 50;
static int gc_write_commit_graph;
static int detach_auto = 1; static int detach_auto = 1;
static timestamp_t gc_log_expire_time; static timestamp_t gc_log_expire_time;
static const char *gc_log_expire = "1.day.ago"; static const char *gc_log_expire = "1.day.ago";
@ -129,6 +131,7 @@ static void gc_config(void)
git_config_get_int("gc.aggressivedepth", &aggressive_depth); git_config_get_int("gc.aggressivedepth", &aggressive_depth);
git_config_get_int("gc.auto", &gc_auto_threshold); git_config_get_int("gc.auto", &gc_auto_threshold);
git_config_get_int("gc.autopacklimit", &gc_auto_pack_limit); git_config_get_int("gc.autopacklimit", &gc_auto_pack_limit);
git_config_get_bool("gc.writecommitgraph", &gc_write_commit_graph);
git_config_get_bool("gc.autodetach", &detach_auto); git_config_get_bool("gc.autodetach", &detach_auto);
git_config_get_expiry("gc.pruneexpire", &prune_expire); git_config_get_expiry("gc.pruneexpire", &prune_expire);
git_config_get_expiry("gc.worktreepruneexpire", &prune_worktrees_expire); git_config_get_expiry("gc.worktreepruneexpire", &prune_worktrees_expire);
@ -641,6 +644,9 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
if (pack_garbage.nr > 0) if (pack_garbage.nr > 0)
clean_pack_garbage(); clean_pack_garbage();
if (gc_write_commit_graph)
write_commit_graph_reachable(get_object_directory(), 0);
if (auto_gc && too_many_loose_objects()) if (auto_gc && too_many_loose_objects())
warning(_("There are too many unreachable loose objects; " warning(_("There are too many unreachable loose objects; "
"run 'git prune' to remove them.")); "run 'git prune' to remove them."));

View File

@ -245,6 +245,20 @@ test_expect_success 'perform fast-forward merge in full repo' '
test_cmp expect output test_cmp expect output
' '
test_expect_success 'check that gc computes commit-graph' '
cd "$TRASH_DIRECTORY/full" &&
git commit --allow-empty -m "blank" &&
git commit-graph write --reachable &&
cp $objdir/info/commit-graph commit-graph-before-gc &&
git reset --hard HEAD~1 &&
git config gc.writeCommitGraph true &&
git gc &&
cp $objdir/info/commit-graph commit-graph-after-gc &&
! test_cmp commit-graph-before-gc commit-graph-after-gc &&
git commit-graph write --reachable &&
test_cmp commit-graph-after-gc $objdir/info/commit-graph
'
# the verify tests below expect the commit-graph to contain # the verify tests below expect the commit-graph to contain
# exactly the commits reachable from the commits/8 branch. # exactly the commits reachable from the commits/8 branch.
# If the file changes the set of commits in the list, then the # If the file changes the set of commits in the list, then the