clone: --dissociate option to mark that reference is only temporary
While use of the --reference option to borrow objects from an existing local repository of the same project is an effective way to reduce traffic when cloning a project over the network, it makes the resulting "borrowing" repository dependent on the "borrowed" repository. After running git clone --reference=P $URL Q the resulting repository Q will be broken if the borrowed repository P disappears. The way to allow the borrowed repository to be removed is to repack the borrowing repository (i.e. run "git repack -a -d" in Q); while power users may know it very well, it is not easily discoverable. Teach a new "--dissociate" option to "git clone" to run this repacking for the user. Helped-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
3c2dc76f01
commit
fb1d6dabce
@ -12,7 +12,7 @@ SYNOPSIS
|
|||||||
'git clone' [--template=<template_directory>]
|
'git clone' [--template=<template_directory>]
|
||||||
[-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
|
[-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
|
||||||
[-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]
|
[-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]
|
||||||
[--separate-git-dir <git dir>]
|
[--dissociate] [--separate-git-dir <git dir>]
|
||||||
[--depth <depth>] [--[no-]single-branch]
|
[--depth <depth>] [--[no-]single-branch]
|
||||||
[--recursive | --recurse-submodules] [--] <repository>
|
[--recursive | --recurse-submodules] [--] <repository>
|
||||||
[<directory>]
|
[<directory>]
|
||||||
@ -98,7 +98,14 @@ objects from the source repository into a pack in the cloned repository.
|
|||||||
require fewer objects to be copied from the repository
|
require fewer objects to be copied from the repository
|
||||||
being cloned, reducing network and local storage costs.
|
being cloned, reducing network and local storage costs.
|
||||||
+
|
+
|
||||||
*NOTE*: see the NOTE for the `--shared` option.
|
*NOTE*: see the NOTE for the `--shared` option, and also the
|
||||||
|
`--dissociate` option.
|
||||||
|
|
||||||
|
--dissociate::
|
||||||
|
Borrow the objects from reference repositories specified
|
||||||
|
with the `--reference` options only to reduce network
|
||||||
|
transfer and stop borrowing from them after a clone is made
|
||||||
|
by making necessary local copies of borrowed objects.
|
||||||
|
|
||||||
--quiet::
|
--quiet::
|
||||||
-q::
|
-q::
|
||||||
|
@ -48,6 +48,7 @@ static int option_verbosity;
|
|||||||
static int option_progress = -1;
|
static int option_progress = -1;
|
||||||
static struct string_list option_config;
|
static struct string_list option_config;
|
||||||
static struct string_list option_reference;
|
static struct string_list option_reference;
|
||||||
|
static int option_dissociate;
|
||||||
|
|
||||||
static int opt_parse_reference(const struct option *opt, const char *arg, int unset)
|
static int opt_parse_reference(const struct option *opt, const char *arg, int unset)
|
||||||
{
|
{
|
||||||
@ -93,6 +94,8 @@ static struct option builtin_clone_options[] = {
|
|||||||
N_("create a shallow clone of that depth")),
|
N_("create a shallow clone of that depth")),
|
||||||
OPT_BOOL(0, "single-branch", &option_single_branch,
|
OPT_BOOL(0, "single-branch", &option_single_branch,
|
||||||
N_("clone only one branch, HEAD or --branch")),
|
N_("clone only one branch, HEAD or --branch")),
|
||||||
|
OPT_BOOL(0, "dissociate", &option_dissociate,
|
||||||
|
N_("use --reference only while cloning")),
|
||||||
OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
|
OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
|
||||||
N_("separate git dir from working tree")),
|
N_("separate git dir from working tree")),
|
||||||
OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
|
OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
|
||||||
@ -736,6 +739,16 @@ static void write_refspec_config(const char* src_ref_prefix,
|
|||||||
strbuf_release(&value);
|
strbuf_release(&value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dissociate_from_references(void)
|
||||||
|
{
|
||||||
|
static const char* argv[] = { "repack", "-a", "-d", NULL };
|
||||||
|
|
||||||
|
if (run_command_v_opt(argv, RUN_GIT_CMD|RUN_COMMAND_NO_STDIN))
|
||||||
|
die(_("cannot repack to clean up"));
|
||||||
|
if (unlink(git_path("objects/info/alternates")) && errno != ENOENT)
|
||||||
|
die_errno(_("cannot unlink temporary alternates file"));
|
||||||
|
}
|
||||||
|
|
||||||
int cmd_clone(int argc, const char **argv, const char *prefix)
|
int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int is_bundle = 0, is_local;
|
int is_bundle = 0, is_local;
|
||||||
@ -883,6 +896,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
if (option_reference.nr)
|
if (option_reference.nr)
|
||||||
setup_reference();
|
setup_reference();
|
||||||
|
else if (option_dissociate) {
|
||||||
|
warning(_("--dissociate given, but there is no --reference"));
|
||||||
|
option_dissociate = 0;
|
||||||
|
}
|
||||||
|
|
||||||
fetch_pattern = value.buf;
|
fetch_pattern = value.buf;
|
||||||
refspec = parse_fetch_refspec(1, &fetch_pattern);
|
refspec = parse_fetch_refspec(1, &fetch_pattern);
|
||||||
@ -996,6 +1013,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
|||||||
transport_unlock_pack(transport);
|
transport_unlock_pack(transport);
|
||||||
transport_disconnect(transport);
|
transport_disconnect(transport);
|
||||||
|
|
||||||
|
if (option_dissociate)
|
||||||
|
dissociate_from_references();
|
||||||
|
|
||||||
junk_mode = JUNK_LEAVE_REPO;
|
junk_mode = JUNK_LEAVE_REPO;
|
||||||
err = checkout();
|
err = checkout();
|
||||||
|
|
||||||
|
@ -198,4 +198,21 @@ test_expect_success 'clone using repo pointed at by gitfile as reference' '
|
|||||||
test_cmp expected "$base_dir/O/.git/objects/info/alternates"
|
test_cmp expected "$base_dir/O/.git/objects/info/alternates"
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'clone and dissociate from reference' '
|
||||||
|
git init P &&
|
||||||
|
(
|
||||||
|
cd P && test_commit one
|
||||||
|
) &&
|
||||||
|
git clone P Q &&
|
||||||
|
(
|
||||||
|
cd Q && test_commit two
|
||||||
|
) &&
|
||||||
|
git clone --no-local --reference=P Q R &&
|
||||||
|
git clone --no-local --reference=P --dissociate Q S &&
|
||||||
|
# removing the reference P would corrupt R but not S
|
||||||
|
rm -fr P &&
|
||||||
|
test_must_fail git -C R fsck &&
|
||||||
|
git -C S fsck
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user