@matheusbsbs / matheus-bagliano / commits / 7f3140cd23
Fork 0

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 <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Schindelin committed Jul 23, 2009 at 17:33 UTC 7f3140cd23f126e578ccaaea8c2cebe36824a7ac
7 files changed +20 -4
Documentation/git-pack-objects.txt
+6 -1
@@ -11,7 +11,8 @@ SYNOPSIS
11 [verse]
12 'git pack-objects' [-q] [--no-reuse-delta] [--delta-base-offset] [--non-empty]
13 [--local] [--incremental] [--window=N] [--depth=N] [--all-progress]
14 - [--revs [--unpacked | --all]*] [--stdout | base-name] < object-list
14 + [--revs [--unpacked | --all]*] [--stdout | base-name]
15 + [--keep-true-parents] < object-list
16
17
18 DESCRIPTION
@@ -197,6 +198,10 @@ base-name::
198 to force the version for the generated pack index, and to force
199 64-bit index entries on objects located above the given offset.
200
201 +--keep-true-parents::
202 + With this option, parents that are hidden by grafts are packed
203 + nevertheless.
204 +
205
206 Author
207 ------
builtin-pack-objects.c
+4
@@ -2259,6 +2259,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
2259 die("bad %s", arg);
2260 continue;
2261 }
2262 + if (!strcmp(arg, "--keep-true-parents")) {
2263 + grafts_replace_parents = 0;
2264 + continue;
2265 + }
2266 usage(pack_usage);
2267 }
2268
cache.h
+2
@@ -561,6 +561,8 @@ enum object_creation_mode {
561
562 extern enum object_creation_mode object_creation_mode;
563
564 +extern int grafts_replace_parents;
565 +
566 #define GIT_REPO_VERSION 0
567 extern int repository_format_version;
568 extern int check_repository_format(void);
commit.c
+5 -1
@@ -266,7 +266,11 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
266 bufptr[47] != '\n')
267 return error("bad parents in commit %s", sha1_to_hex(item->object.sha1));
268 bufptr += 48;
269 - if (graft)
269 + /*
270 + * The clone is shallow if nr_parent < 0, and we must
271 + * not traverse its real parents even when we unhide them.
272 + */
273 + if (graft && (graft->nr_parent < 0 || grafts_replace_parents))
274 continue;
275 new_parent = lookup_commit(parent);
276 if (new_parent)
environment.c
+1
@@ -47,6 +47,7 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
47 #define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS
48 #endif
49 enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
50 +int grafts_replace_parents = 1;
51
52 /* Parallel index stat data preload? */
53 int core_preload_index = 0;
git-repack.sh
+1 -1
@@ -81,7 +81,7 @@ case ",$all_into_one," in
81 esac
82
83 args="$args $local $quiet $no_reuse$extra"
84 -names=$(git pack-objects --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
84 +names=$(git pack-objects --keep-true-parents --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
85 exit 1
86 if [ -z "$names" ]; then
87 if test -z "$quiet"; then
t/t7700-repack.sh
+1 -1
@@ -149,7 +149,7 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar
149 test_must_fail git show $csha1
150 '
151
152 -test_expect_failure 'objects made unreachable by grafts only are kept' '
152 +test_expect_success 'objects made unreachable by grafts only are kept' '
153 test_tick &&
154 git commit --allow-empty -m "commit 4" &&
155 H0=$(git rev-parse HEAD) &&