Skip to content

Commit d35c802

Browse files
committed
Merge branch 'jc/clone-borrow'
Allow "git clone --reference" to be used more safely. * jc/clone-borrow: clone: --dissociate option to mark that reference is only temporary
2 parents da178ac + fb1d6da commit d35c802

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

‎Documentation/git-clone.txt‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ SYNOPSIS
1212
'git clone' [--template=<template_directory>]
1313
[-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
1414
[-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]
15-
[--separate-git-dir <git dir>]
15+
[--dissociate] [--separate-git-dir <git dir>]
1616
[--depth <depth>] [--[no-]single-branch]
1717
[--recursive | --recurse-submodules] [--] <repository>
1818
[<directory>]
@@ -98,7 +98,14 @@ objects from the source repository into a pack in the cloned repository.
9898
require fewer objects to be copied from the repository
9999
being cloned, reducing network and local storage costs.
100100
+
101-
*NOTE*: see the NOTE for the `--shared` option.
101+
*NOTE*: see the NOTE for the `--shared` option, and also the
102+
`--dissociate` option.
103+
104+
--dissociate::
105+
Borrow the objects from reference repositories specified
106+
with the `--reference` options only to reduce network
107+
transfer and stop borrowing from them after a clone is made
108+
by making necessary local copies of borrowed objects.
102109

103110
--quiet::
104111
-q::

‎builtin/clone.c‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ static int option_verbosity;
4949
static int option_progress = -1;
5050
static struct string_list option_config;
5151
static struct string_list option_reference;
52+
static int option_dissociate;
5253

5354
static int opt_parse_reference(const struct option *opt, const char *arg, int unset)
5455
{
@@ -94,6 +95,8 @@ static struct option builtin_clone_options[] = {
9495
N_("create a shallow clone of that depth")),
9596
OPT_BOOL(0, "single-branch", &option_single_branch,
9697
N_("clone only one branch, HEAD or --branch")),
98+
OPT_BOOL(0, "dissociate", &option_dissociate,
99+
N_("use --reference only while cloning")),
97100
OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
98101
N_("separate git dir from working tree")),
99102
OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
@@ -735,6 +738,16 @@ static void write_refspec_config(const char *src_ref_prefix,
735738
strbuf_release(&value);
736739
}
737740

741+
static void dissociate_from_references(void)
742+
{
743+
static const char* argv[] = { "repack", "-a", "-d", NULL };
744+
745+
if (run_command_v_opt(argv, RUN_GIT_CMD|RUN_COMMAND_NO_STDIN))
746+
die(_("cannot repack to clean up"));
747+
if (unlink(git_path("objects/info/alternates")) && errno != ENOENT)
748+
die_errno(_("cannot unlink temporary alternates file"));
749+
}
750+
738751
int cmd_clone(int argc, const char **argv, const char *prefix)
739752
{
740753
int is_bundle = 0, is_local;
@@ -880,6 +893,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
880893

881894
if (option_reference.nr)
882895
setup_reference();
896+
else if (option_dissociate) {
897+
warning(_("--dissociate given, but there is no --reference"));
898+
option_dissociate = 0;
899+
}
883900

884901
fetch_pattern = value.buf;
885902
refspec = parse_fetch_refspec(1, &fetch_pattern);
@@ -993,6 +1010,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
9931010
transport_unlock_pack(transport);
9941011
transport_disconnect(transport);
9951012

1013+
if (option_dissociate)
1014+
dissociate_from_references();
1015+
9961016
junk_mode = JUNK_LEAVE_REPO;
9971017
err = checkout();
9981018

‎t/t5700-clone-reference.sh‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,4 +198,21 @@ test_expect_success 'clone using repo pointed at by gitfile as reference' '
198198
test_cmp expected "$base_dir/O/.git/objects/info/alternates"
199199
'
200200

201+
test_expect_success 'clone and dissociate from reference' '
202+
git init P &&
203+
(
204+
cd P && test_commit one
205+
) &&
206+
git clone P Q &&
207+
(
208+
cd Q && test_commit two
209+
) &&
210+
git clone --no-local --reference=P Q R &&
211+
git clone --no-local --reference=P --dissociate Q S &&
212+
# removing the reference P would corrupt R but not S
213+
rm -fr P &&
214+
test_must_fail git -C R fsck &&
215+
git -C S fsck
216+
'
217+
201218
test_done

0 commit comments

Comments
 (0)