Merge branch 'ab/clone-no-tags'

"git clone" learned the "--no-tags" option not to fetch all tags
initially, and also set up the tagopt not to follow any tags in
subsequent fetches.

* ab/clone-no-tags:
  tests: rename a test having to do with shallow submodules
  clone: add a --no-tags option to clone without tags
  tests: change "cd ... && git fetch" to "cd &&\n\tgit fetch"
This commit is contained in:
Junio C Hamano 2017-05-16 11:51:54 +09:00
commit a1fdc85f41
5 changed files with 117 additions and 14 deletions

View File

@ -13,7 +13,7 @@ SYNOPSIS
[-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>]
[--dissociate] [--separate-git-dir <git dir>] [--dissociate] [--separate-git-dir <git dir>]
[--depth <depth>] [--[no-]single-branch] [--depth <depth>] [--[no-]single-branch] [--no-tags]
[--recurse-submodules] [--[no-]shallow-submodules] [--recurse-submodules] [--[no-]shallow-submodules]
[--jobs <n>] [--] <repository> [<directory>] [--jobs <n>] [--] <repository> [<directory>]
@ -215,6 +215,18 @@ objects from the source repository into a pack in the cloned repository.
branch when `--single-branch` clone was made, no remote-tracking branch when `--single-branch` clone was made, no remote-tracking
branch is created. branch is created.
--no-tags::
Don't clone any tags, and set
`remote.<remote>.tagOpt=--no-tags` in the config, ensuring
that future `git pull` and `git fetch` operations won't follow
any tags. Subsequent explicit tag fetches will still work,
(see linkgit:git-fetch[1]).
+
Can be used in conjunction with `--single-branch` to clone and
maintain a branch with no references other than a single cloned
branch. This is useful e.g. to maintain minimal clones of the default
branch of some repository for search indexing.
--recurse-submodules[=<pathspec]:: --recurse-submodules[=<pathspec]::
After the clone is created, initialize and clone submodules After the clone is created, initialize and clone submodules
within based on the provided pathspec. If no pathspec is within based on the provided pathspec. If no pathspec is

View File

@ -40,6 +40,7 @@ static const char * const builtin_clone_usage[] = {
static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1; static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1;
static int option_local = -1, option_no_hardlinks, option_shared; static int option_local = -1, option_no_hardlinks, option_shared;
static int option_no_tags;
static int option_shallow_submodules; static int option_shallow_submodules;
static int deepen; static int deepen;
static char *option_template, *option_depth, *option_since; static char *option_template, *option_depth, *option_since;
@ -120,6 +121,8 @@ static struct option builtin_clone_options[] = {
N_("deepen history of shallow clone, excluding rev")), N_("deepen history of shallow clone, excluding rev")),
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, "no-tags", &option_no_tags,
N_("don't clone any tags, and make later fetches not to follow them")),
OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules, OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules,
N_("any cloned submodules will be shallow")), N_("any cloned submodules will be shallow")),
OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"), OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
@ -563,7 +566,7 @@ static struct ref *wanted_peer_refs(const struct ref *refs,
} else } else
get_fetch_map(refs, refspec, &tail, 0); get_fetch_map(refs, refspec, &tail, 0);
if (!option_mirror && !option_single_branch) if (!option_mirror && !option_single_branch && !option_no_tags)
get_fetch_map(refs, tag_refspec, &tail, 0); get_fetch_map(refs, tag_refspec, &tail, 0);
return local_refs; return local_refs;
@ -652,7 +655,7 @@ static void update_remote_refs(const struct ref *refs,
if (refs) { if (refs) {
write_remote_refs(mapped_refs); write_remote_refs(mapped_refs);
if (option_single_branch) if (option_single_branch && !option_no_tags)
write_followtags(refs, msg); write_followtags(refs, msg);
} }
@ -1035,6 +1038,12 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
git_config_set(key.buf, repo); git_config_set(key.buf, repo);
strbuf_reset(&key); strbuf_reset(&key);
if (option_no_tags) {
strbuf_addf(&key, "remote.%s.tagOpt", option_origin);
git_config_set(key.buf, "--no-tags");
strbuf_reset(&key);
}
if (option_required_reference.nr || option_optional_reference.nr) if (option_required_reference.nr || option_optional_reference.nr)
setup_reference(); setup_reference();

View File

@ -1319,6 +1319,7 @@ _git_clone ()
--template= --template=
--depth --depth
--single-branch --single-branch
--no-tags
--branch --branch
--recurse-submodules --recurse-submodules
--no-single-branch --no-single-branch

View File

@ -17,13 +17,20 @@ test_expect_success 'setup' '
echo four >file && echo four >file &&
git commit -a -m four && git commit -a -m four &&
git checkout master && git checkout master &&
git tag five &&
# default clone # default clone
git clone . dir_all && git clone . dir_all &&
# default clone --no-tags
git clone --no-tags . dir_all_no_tags &&
# default --single that follows HEAD=master # default --single that follows HEAD=master
git clone --single-branch . dir_master && git clone --single-branch . dir_master &&
# default --single that follows HEAD=master with no tags
git clone --single-branch --no-tags . dir_master_no_tags &&
# default --single that follows HEAD=side # default --single that follows HEAD=side
git checkout side && git checkout side &&
git clone --single-branch . dir_side && git clone --single-branch . dir_side &&
@ -45,6 +52,9 @@ test_expect_success 'setup' '
# explicit --single with tag # explicit --single with tag
git clone --single-branch --branch two . dir_tag && git clone --single-branch --branch two . dir_tag &&
# explicit --single with tag and --no-tags
git clone --single-branch --no-tags --branch two . dir_tag_no_tags &&
# advance both "master" and "side" branches # advance both "master" and "side" branches
git checkout side && git checkout side &&
echo five >file && echo five >file &&
@ -59,7 +69,8 @@ test_expect_success 'setup' '
test_expect_success 'by default all branches will be kept updated' ' test_expect_success 'by default all branches will be kept updated' '
( (
cd dir_all && git fetch && cd dir_all &&
git fetch &&
git for-each-ref refs/remotes/origin | git for-each-ref refs/remotes/origin |
sed -e "/HEAD$/d" \ sed -e "/HEAD$/d" \
-e "s|/remotes/origin/|/heads/|" >../actual -e "s|/remotes/origin/|/heads/|" >../actual
@ -71,28 +82,82 @@ test_expect_success 'by default all branches will be kept updated' '
test_expect_success 'by default no tags will be kept updated' ' test_expect_success 'by default no tags will be kept updated' '
( (
cd dir_all && git fetch && cd dir_all &&
git fetch &&
git for-each-ref refs/tags >../actual git for-each-ref refs/tags >../actual
) && ) &&
git for-each-ref refs/tags >expect && git for-each-ref refs/tags >expect &&
test_must_fail test_cmp expect actual test_must_fail test_cmp expect actual &&
test_line_count = 2 actual
'
test_expect_success 'clone with --no-tags' '
(
cd dir_all_no_tags &&
git fetch &&
git for-each-ref refs/tags >../actual
) &&
>expect &&
test_cmp expect actual
' '
test_expect_success '--single-branch while HEAD pointing at master' ' test_expect_success '--single-branch while HEAD pointing at master' '
( (
cd dir_master && git fetch && cd dir_master &&
git fetch &&
git for-each-ref refs/remotes/origin | git for-each-ref refs/remotes/origin |
sed -e "/HEAD$/d" \ sed -e "/HEAD$/d" \
-e "s|/remotes/origin/|/heads/|" >../actual -e "s|/remotes/origin/|/heads/|" >../actual
) && ) &&
# only follow master # only follow master
git for-each-ref refs/heads/master >expect && git for-each-ref refs/heads/master >expect &&
test_cmp expect actual # get & check latest tags
test_cmp expect actual &&
(
cd dir_master &&
git fetch --tags &&
git for-each-ref refs/tags >../actual
) &&
git for-each-ref refs/tags >expect &&
test_cmp expect actual &&
test_line_count = 2 actual
'
test_expect_success '--single-branch while HEAD pointing at master and --no-tags' '
(
cd dir_master_no_tags &&
git fetch &&
git for-each-ref refs/remotes/origin |
sed -e "/HEAD$/d" \
-e "s|/remotes/origin/|/heads/|" >../actual
) &&
# only follow master
git for-each-ref refs/heads/master >expect &&
test_cmp expect actual &&
# get tags (noop)
(
cd dir_master_no_tags &&
git fetch &&
git for-each-ref refs/tags >../actual
) &&
>expect &&
test_cmp expect actual &&
test_line_count = 0 actual &&
# get tags with --tags overrides tagOpt
(
cd dir_master_no_tags &&
git fetch --tags &&
git for-each-ref refs/tags >../actual
) &&
git for-each-ref refs/tags >expect &&
test_cmp expect actual &&
test_line_count = 2 actual
' '
test_expect_success '--single-branch while HEAD pointing at side' ' test_expect_success '--single-branch while HEAD pointing at side' '
( (
cd dir_side && git fetch && cd dir_side &&
git fetch &&
git for-each-ref refs/remotes/origin | git for-each-ref refs/remotes/origin |
sed -e "/HEAD$/d" \ sed -e "/HEAD$/d" \
-e "s|/remotes/origin/|/heads/|" >../actual -e "s|/remotes/origin/|/heads/|" >../actual
@ -104,7 +169,8 @@ test_expect_success '--single-branch while HEAD pointing at side' '
test_expect_success '--single-branch with explicit --branch side' ' test_expect_success '--single-branch with explicit --branch side' '
( (
cd dir_side2 && git fetch && cd dir_side2 &&
git fetch &&
git for-each-ref refs/remotes/origin | git for-each-ref refs/remotes/origin |
sed -e "/HEAD$/d" \ sed -e "/HEAD$/d" \
-e "s|/remotes/origin/|/heads/|" >../actual -e "s|/remotes/origin/|/heads/|" >../actual
@ -116,16 +182,29 @@ test_expect_success '--single-branch with explicit --branch side' '
test_expect_success '--single-branch with explicit --branch with tag fetches updated tag' ' test_expect_success '--single-branch with explicit --branch with tag fetches updated tag' '
( (
cd dir_tag && git fetch && cd dir_tag &&
git fetch &&
git for-each-ref refs/tags >../actual git for-each-ref refs/tags >../actual
) && ) &&
git for-each-ref refs/tags >expect && git for-each-ref refs/tags >expect &&
test_cmp expect actual test_cmp expect actual
' '
test_expect_success '--single-branch with explicit --branch with tag fetches updated tag despite --no-tags' '
(
cd dir_tag_no_tags &&
git fetch &&
git for-each-ref refs/tags >../actual
) &&
git for-each-ref refs/tags/two >expect &&
test_cmp expect actual &&
test_line_count = 1 actual
'
test_expect_success '--single-branch with --mirror' ' test_expect_success '--single-branch with --mirror' '
( (
cd dir_mirror && git fetch && cd dir_mirror &&
git fetch &&
git for-each-ref refs > ../actual git for-each-ref refs > ../actual
) && ) &&
git for-each-ref refs >expect && git for-each-ref refs >expect &&
@ -134,7 +213,8 @@ test_expect_success '--single-branch with --mirror' '
test_expect_success '--single-branch with explicit --branch and --mirror' ' test_expect_success '--single-branch with explicit --branch and --mirror' '
( (
cd dir_mirror_side && git fetch && cd dir_mirror_side &&
git fetch &&
git for-each-ref refs > ../actual git for-each-ref refs > ../actual
) && ) &&
git for-each-ref refs >expect && git for-each-ref refs >expect &&
@ -143,7 +223,8 @@ test_expect_success '--single-branch with explicit --branch and --mirror' '
test_expect_success '--single-branch with detached' ' test_expect_success '--single-branch with detached' '
( (
cd dir_detached && git fetch && cd dir_detached &&
git fetch &&
git for-each-ref refs/remotes/origin | git for-each-ref refs/remotes/origin |
sed -e "/HEAD$/d" \ sed -e "/HEAD$/d" \
-e "s|/remotes/origin/|/heads/|" >../actual -e "s|/remotes/origin/|/heads/|" >../actual