Skip to content

Commit 7f3140c

Browse files
dschogitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1ec6482 commit 7f3140c

File tree

7 files changed

+20
-4
lines changed

7 files changed

+20
-4
lines changed

Documentation/git-pack-objects.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ SYNOPSIS
1111
[verse]
1212
'git pack-objects' [-q] [--no-reuse-delta] [--delta-base-offset] [--non-empty]
1313
[--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
1516

1617

1718
DESCRIPTION
@@ -197,6 +198,10 @@ base-name::
197198
to force the version for the generated pack index, and to force
198199
64-bit index entries on objects located above the given offset.
199200

201+
--keep-true-parents::
202+
With this option, parents that are hidden by grafts are packed
203+
nevertheless.
204+
200205

201206
Author
202207
------

builtin-pack-objects.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2259,6 +2259,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
22592259
die("bad %s", arg);
22602260
continue;
22612261
}
2262+
if (!strcmp(arg, "--keep-true-parents")) {
2263+
grafts_replace_parents = 0;
2264+
continue;
2265+
}
22622266
usage(pack_usage);
22632267
}
22642268

cache.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,8 @@ enum object_creation_mode {
561561

562562
extern enum object_creation_mode object_creation_mode;
563563

564+
extern int grafts_replace_parents;
565+
564566
#define GIT_REPO_VERSION 0
565567
extern int repository_format_version;
566568
extern int check_repository_format(void);

commit.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,11 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
266266
bufptr[47] != '\n')
267267
return error("bad parents in commit %s", sha1_to_hex(item->object.sha1));
268268
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))
270274
continue;
271275
new_parent = lookup_commit(parent);
272276
if (new_parent)

environment.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
4747
#define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS
4848
#endif
4949
enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
50+
int grafts_replace_parents = 1;
5051

5152
/* Parallel index stat data preload? */
5253
int core_preload_index = 0;

git-repack.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ case ",$all_into_one," in
8181
esac
8282

8383
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") ||
8585
exit 1
8686
if [ -z "$names" ]; then
8787
if test -z "$quiet"; then

t/t7700-repack.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar
149149
test_must_fail git show $csha1
150150
'
151151

152-
test_expect_failure 'objects made unreachable by grafts only are kept' '
152+
test_expect_success 'objects made unreachable by grafts only are kept' '
153153
test_tick &&
154154
git commit --allow-empty -m "commit 4" &&
155155
H0=$(git rev-parse HEAD) &&

0 commit comments

Comments
 (0)