From 7f3140cd23f126e578ccaaea8c2cebe36824a7ac Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 23 Jul 2009 17:33:49 +0200 Subject: [PATCH] git repack: keep commits hidden by a graft When you have grafts that pretend that a given commit has different parents than the ones recorded in the commit object, it is dangerous to let 'git repack' remove those hidden parents, as you can easily remove the graft and end up with a broken repository. So let's play it safe and keep those parent objects and everything that is reachable by them, in addition to the grafted parents. As this behavior can only be triggered by git pack-objects, and as that command handles duplicate parents gracefully, we do not bother to cull duplicated parents that may result by using both true and grafted parents. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/git-pack-objects.txt | 7 ++++++- builtin-pack-objects.c | 4 ++++ cache.h | 2 ++ commit.c | 6 +++++- environment.c | 1 + git-repack.sh | 2 +- t/t7700-repack.sh | 2 +- 7 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt index 7d4c1a7556..2e4992970e 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.txt @@ -11,7 +11,8 @@ SYNOPSIS [verse] 'git pack-objects' [-q] [--no-reuse-delta] [--delta-base-offset] [--non-empty] [--local] [--incremental] [--window=N] [--depth=N] [--all-progress] - [--revs [--unpacked | --all]*] [--stdout | base-name] < object-list + [--revs [--unpacked | --all]*] [--stdout | base-name] + [--keep-true-parents] < object-list DESCRIPTION @@ -197,6 +198,10 @@ base-name:: to force the version for the generated pack index, and to force 64-bit index entries on objects located above the given offset. +--keep-true-parents:: + With this option, parents that are hidden by grafts are packed + nevertheless. + Author ------ diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 941cc2d73c..527638168b 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -2259,6 +2259,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) die("bad %s", arg); continue; } + if (!strcmp(arg, "--keep-true-parents")) { + grafts_replace_parents = 0; + continue; + } usage(pack_usage); } diff --git a/cache.h b/cache.h index b8503ad91c..e902008297 100644 --- a/cache.h +++ b/cache.h @@ -561,6 +561,8 @@ enum object_creation_mode { extern enum object_creation_mode object_creation_mode; +extern int grafts_replace_parents; + #define GIT_REPO_VERSION 0 extern int repository_format_version; extern int check_repository_format(void); diff --git a/commit.c b/commit.c index aa3b35b6a8..f69525a089 100644 --- a/commit.c +++ b/commit.c @@ -266,7 +266,11 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size) bufptr[47] != '\n') return error("bad parents in commit %s", sha1_to_hex(item->object.sha1)); bufptr += 48; - if (graft) + /* + * The clone is shallow if nr_parent < 0, and we must + * not traverse its real parents even when we unhide them. + */ + if (graft && (graft->nr_parent < 0 || grafts_replace_parents)) continue; new_parent = lookup_commit(parent); if (new_parent) diff --git a/environment.c b/environment.c index 801a005ef1..477d2e4da8 100644 --- a/environment.c +++ b/environment.c @@ -47,6 +47,7 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED; #define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS #endif enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE; +int grafts_replace_parents = 1; /* Parallel index stat data preload? */ int core_preload_index = 0; diff --git a/git-repack.sh b/git-repack.sh index 0868734723..be0c8435dc 100755 --- a/git-repack.sh +++ b/git-repack.sh @@ -81,7 +81,7 @@ case ",$all_into_one," in esac args="$args $local $quiet $no_reuse$extra" -names=$(git pack-objects --honor-pack-keep --non-empty --all --reflog $args