{"thread":{"id":"45697","subject":"Is there a way to get 'git fetch --no-tags' semantics with 'git clone'?","startedAt":"2017-04-14T21:29:21Z","lastAt":"2017-04-26T08:56:58Z","messageCount":11,"participants":["Ævar Arnfjörð Bjarmason","Brandon Williams","Junio C Hamano","Jonathan Nieder"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"316861","messageId":"CACBZZX584QwjphGfEgTn2V9P0yVkYSxfE1_Gp96bno8186SDyA@mail.gmail.com","threadId":"45697","inReplyTo":null,"subject":"Is there a way to get 'git fetch --no-tags' semantics with 'git clone'?","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2017-04-14T21:28:55Z","receivedAt":"2017-04-14T21:29:21Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"As far as I can tell the only way to clone a given upstream repo,\nwhich has an unknown main branch name without any tags is:\n\n    git clone --single-branch <url> <repo> &&\n    cd <repo> &&\n    git tag -d $(git tag -l) &&\n    git config remote.origin.tagOpt --no-tags\n\nIs there really nothing like:\n\n    git clone --single-branch --no-tags <url> <repo>\n\n?\n\nI suppose this can be done with the usual 'git init`, set the config &\nthen fetch dance, but in that case what part of 'git remote' or\nfriends exposes finding the remote \"main\" ref as --single-branch does?\n"},{"id":"317130","messageId":"20170418191553.15464-1-avarab@gmail.com","threadId":"45697","inReplyTo":"CACBZZX584QwjphGfEgTn2V9P0yVkYSxfE1_Gp96bno8186SDyA@mail.gmail.com","subject":"[PATCH] clone: add a --no-tags option to clone without tags","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2017-04-18T19:15:53Z","receivedAt":"2017-04-18T19:16:16Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Add a --no-tags option to \"git clone\" to clone without tags. Currently\nthere's no easy way to clone a repository and end up with just a\n\"master\" branch via --single-branch, or track all branches and no\ntags. Now --no-tags can be added to \"git clone\" with or without\n--single-branch to clone a repository without tags.\n\nBefore this the only way of doing this was either by manually tweaking\nthe config in a fresh repository:\n\n    git init git &&\n    cat >git/.git/config <<EOF &&\n    [remote \"origin\"]\n        url = git@github.com:git/git.git\n        tagOpt = --no-tags\n        fetch = +refs/heads/master:refs/remotes/origin/master\n    [branch \"master\"]\n        remote = origin\n        merge = refs/heads/master\n    EOF\n    cd git &&\n    git pull\n\nWhich requires hardcoding the \"master\" name, which may not be the same\nbranch, or alternatively by setting tagOpt=--no-tags right after\ncloning & deleting any existing tags:\n\n    git clone --single-branch git@github.com:git/git.git &&\n    cd git &&\n    git config remote.origin.tagOpt --no-tags &&\n    git tag -l | xargs git tag -d\n\nWhich of course was also subtly buggy if --branch was pointed at a\ntag, leaving the user in a detached head:\n\n    git clone --single-branch --branch v2.12.0 git@github.com:git/git.git &&\n    cd git &&\n    git config remote.origin.tagOpt --no-tags &&\n    git tag -l | xargs git tag -d\n\nNow all this complexity becomes the much simpler:\n\n    git clone --single-branch --no-tags git@github.com:git/git.git\n\nOr in the case of cloning a single tag \"branch\":\n\n    git clone --single-branch --branch v2.12.0 --no-tags git@github.com:git/git.git\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n\nOn Fri, Apr 14, 2017 at 11:28 PM, Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:\n> As far as I can tell the only way to clone a given upstream repo,\n> which has an unknown main branch name without any tags is:\n>\n>     git clone --single-branch <url> <repo> &&\n>     cd <repo> &&\n>     git tag -d $(git tag -l) &&\n>     git config remote.origin.tagOpt --no-tags\n>\n> Is there really nothing like:\n>\n>     git clone --single-branch --no-tags <url> <repo>\n>\n> ?\n>\n> I suppose this can be done with the usual 'git init`, set the config &\n> then fetch dance, but in that case what part of 'git remote' or\n> friends exposes finding the remote \"main\" ref as --single-branch does?\n\nHere's a patch which implements this. It works, and I think it makes\nsense for inclusion. It would be logical to follow this up with a\n--no-tags-submodules similar to --no-shallow-submodules, but I ran out\nof time.\n\n Documentation/git-clone.txt | 12 +++++++-\n builtin/clone.c             | 13 ++++++--\n t/t5612-clone-refspec.sh    | 73 +++++++++++++++++++++++++++++++++++++++++++--\n 3 files changed, 93 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt\nindex 30052cce49..ef78e6dcc6 100644\n--- a/Documentation/git-clone.txt\n+++ b/Documentation/git-clone.txt\n@@ -13,7 +13,7 @@ SYNOPSIS\n \t  [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]\n \t  [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]\n \t  [--dissociate] [--separate-git-dir <git dir>]\n-\t  [--depth <depth>] [--[no-]single-branch]\n+\t  [--depth <depth>] [--[no-]single-branch] [--no-tags]\n \t  [--recurse-submodules] [--[no-]shallow-submodules]\n \t  [--jobs <n>] [--] <repository> [<directory>]\n \n@@ -215,6 +215,16 @@ objects from the source repository into a pack in the cloned repository.\n \tbranch when `--single-branch` clone was made, no remote-tracking\n \tbranch is created.\n \n+--no-tags::\n+\tDon't clone any tags, and set `remote.origin.tagOpt=--no-tags`\n+\tin the config, ensuring that future `git pull` and `git fetch`\n+\toperations won't fetch any tags.\n++\n+Can be used in conjunction with `--single-branch` to clone & maintain\n+a branch with no references other than a single cloned branch. This is\n+useful e.g. to maintain minimal clones of the default branch of some\n+repository for search indexing.\n+\n --recurse-submodules[=<pathspec]::\n \tAfter the clone is created, initialize and clone submodules\n \twithin based on the provided pathspec.  If no pathspec is\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex 32c5843563..96908a4cd7 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -40,6 +40,7 @@ static const char * const builtin_clone_usage[] = {\n \n static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1;\n static int option_local = -1, option_no_hardlinks, option_shared;\n+static int option_no_tags;\n static int option_shallow_submodules;\n static int deepen;\n static char *option_template, *option_depth, *option_since;\n@@ -120,6 +121,8 @@ static struct option builtin_clone_options[] = {\n \t\t\tN_(\"deepen history of shallow clone, excluding rev\")),\n \tOPT_BOOL(0, \"single-branch\", &option_single_branch,\n \t\t    N_(\"clone only one branch, HEAD or --branch\")),\n+\tOPT_BOOL_NONEG(0, \"no-tags\", &option_no_tags,\n+\t\t       N_(\"don't clone any tags, and set remote.<name>.tagOpt=--no-tags\")),\n \tOPT_BOOL(0, \"shallow-submodules\", &option_shallow_submodules,\n \t\t    N_(\"any cloned submodules will be shallow\")),\n \tOPT_STRING(0, \"separate-git-dir\", &real_git_dir, N_(\"gitdir\"),\n@@ -563,7 +566,7 @@ static struct ref *wanted_peer_refs(const struct ref *refs,\n \t} else\n \t\tget_fetch_map(refs, refspec, &tail, 0);\n \n-\tif (!option_mirror && !option_single_branch)\n+\tif (!option_mirror && !option_single_branch && !option_no_tags)\n \t\tget_fetch_map(refs, tag_refspec, &tail, 0);\n \n \treturn local_refs;\n@@ -652,7 +655,7 @@ static void update_remote_refs(const struct ref *refs,\n \n \tif (refs) {\n \t\twrite_remote_refs(mapped_refs);\n-\t\tif (option_single_branch)\n+\t\tif (option_single_branch && !option_no_tags)\n \t\t\twrite_followtags(refs, msg);\n \t}\n \n@@ -1035,6 +1038,12 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \tgit_config_set(key.buf, repo);\n \tstrbuf_reset(&key);\n \n+\tif (option_no_tags) {\n+\t\tstrbuf_addf(&key, \"remote.%s.tagOpt\", option_origin);\n+\t\tgit_config_set(key.buf, \"--no-tags\");\n+\t\tstrbuf_reset(&key);\n+\t}\n+\n \tif (option_required_reference.nr || option_optional_reference.nr)\n \t\tsetup_reference();\n \ndiff --git a/t/t5612-clone-refspec.sh b/t/t5612-clone-refspec.sh\nindex 7ace2535c8..83317805a8 100755\n--- a/t/t5612-clone-refspec.sh\n+++ b/t/t5612-clone-refspec.sh\n@@ -17,13 +17,20 @@ test_expect_success 'setup' '\n \techo four >file &&\n \tgit commit -a -m four &&\n \tgit checkout master &&\n+\tgit tag five &&\n \n \t# default clone\n \tgit clone . dir_all &&\n \n+\t# default clone --no-tags\n+\tgit clone --no-tags . dir_all_no_tags &&\n+\n \t# default --single that follows HEAD=master\n \tgit clone --single-branch . dir_master &&\n \n+\t# default --single that follows HEAD=master with no tags\n+\tgit clone --single-branch --no-tags . dir_master_no_tags &&\n+\n \t# default --single that follows HEAD=side\n \tgit checkout side &&\n \tgit clone --single-branch . dir_side &&\n@@ -45,6 +52,9 @@ test_expect_success 'setup' '\n \t# explicit --single with tag\n \tgit clone --single-branch --branch two . dir_tag &&\n \n+\t# explicit --single with tag and --no-tags\n+\tgit clone --single-branch --no-tags --branch two . dir_tag_no_tags &&\n+\n \t# advance both \"master\" and \"side\" branches\n \tgit checkout side &&\n \techo five >file &&\n@@ -75,7 +85,17 @@ test_expect_success 'by default no tags will be kept updated' '\n \t\tgit for-each-ref refs/tags >../actual\n \t) &&\n \tgit for-each-ref refs/tags >expect &&\n-\ttest_must_fail test_cmp expect actual\n+\ttest_must_fail test_cmp expect actual &&\n+\ttest_line_count = 2 actual\n+'\n+\n+test_expect_success 'clone with --no-tags' '\n+\t(\n+\t\tcd dir_all_no_tags && git fetch &&\n+\t\tgit for-each-ref refs/tags >../actual\n+\t) &&\n+\t>expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success '--single-branch while HEAD pointing at master' '\n@@ -87,7 +107,46 @@ test_expect_success '--single-branch while HEAD pointing at master' '\n \t) &&\n \t# only follow master\n \tgit for-each-ref refs/heads/master >expect &&\n-\ttest_cmp expect actual\n+\t# get & check latest tags\n+\ttest_cmp expect actual &&\n+\t(\n+\t\tcd dir_master &&\n+\t\tgit fetch --tags &&\n+\t\tgit for-each-ref refs/tags >../actual\n+\t) &&\n+\tgit for-each-ref refs/tags >expect &&\n+\ttest_cmp expect actual &&\n+\ttest_line_count = 2 actual\n+'\n+\n+test_expect_success '--single-branch while HEAD pointing at master and --no-tags' '\n+\t(\n+\t\tcd dir_master_no_tags && git fetch &&\n+\t\tgit for-each-ref refs/remotes/origin |\n+\t\tsed -e \"/HEAD$/d\" \\\n+\t\t    -e \"s|/remotes/origin/|/heads/|\" >../actual\n+\t) &&\n+\t# only follow master\n+\tgit for-each-ref refs/heads/master >expect &&\n+\ttest_cmp expect actual &&\n+\t# get tags (noop)\n+\t(\n+\t\tcd dir_master_no_tags &&\n+\t\tgit fetch &&\n+\t\tgit for-each-ref refs/tags >../actual\n+\t) &&\n+\t>expect &&\n+\ttest_cmp expect actual &&\n+\ttest_line_count = 0 actual &&\n+\t# get tags with --tags overrides tagOpt\n+\t(\n+\t\tcd dir_master_no_tags &&\n+\t\tgit fetch --tags &&\n+\t\tgit for-each-ref refs/tags >../actual\n+\t) &&\n+\tgit for-each-ref refs/tags >expect &&\n+\ttest_cmp expect actual &&\n+\ttest_line_count = 2 actual\n '\n \n test_expect_success '--single-branch while HEAD pointing at side' '\n@@ -123,6 +182,16 @@ test_expect_success '--single-branch with explicit --branch with tag fetches upd\n \ttest_cmp expect actual\n '\n \n+test_expect_success '--single-branch with explicit --branch with tag fetches updated tag despite --no-tags' '\n+\t(\n+\t\tcd dir_tag_no_tags && git fetch &&\n+\t\tgit for-each-ref refs/tags >../actual\n+\t) &&\n+\tgit for-each-ref refs/tags/two >expect &&\n+\ttest_cmp expect actual &&\n+\ttest_line_count = 1 actual\n+'\n+\n test_expect_success '--single-branch with --mirror' '\n \t(\n \t\tcd dir_mirror && git fetch &&\n-- \n2.11.0\n\n"},{"id":"317136","messageId":"CACBZZX4CD52j=fz_DPmVpsMLa-Dxu-iJ=GB8YQ6QFKOh1RWQ_g@mail.gmail.com","threadId":"45697","inReplyTo":"20170418191553.15464-1-avarab@gmail.com","subject":"Re: [PATCH] clone: add a --no-tags option to clone without tags","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2017-04-18T21:06:47Z","receivedAt":"2017-04-18T21:07:14Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Tue, Apr 18, 2017 at 9:15 PM, Ævar Arnfjörð Bjarmason\n<avarab@gmail.com> wrote:\n\n>                     N_(\"clone only one branch, HEAD or --branch\")),\n> +       OPT_BOOL_NONEG(0, \"no-tags\", &option_no_tags,\n> +                      N_(\"don't clone any tags, and set remote.<name>.tagOpt=--no-tags\")),\n>         OPT_BOOL(0, \"shallow-submodules\", &option_shallow_submodules,\n\nI forgot to note that this is on top of my earlier patch which adds\nOPT_BOOL_NONEG, see <20170418170914.9701-1-avarab@gmail.com>, but\notherwise applies on top of master, and will work just fine by\namending that to say OPT_BOOL (although --no-no-tags will then exist,\nas noted in the other patch).\n"},{"id":"317159","messageId":"20170418233030.GA41018@google.com","threadId":"45697","inReplyTo":"20170418191553.15464-1-avarab@gmail.com","subject":"Re: [PATCH] clone: add a --no-tags option to clone without tags","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-04-18T23:30:30Z","receivedAt":"2017-04-18T23:31:28Z","isPatch":true,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 04/18, Ævar Arnfjörð Bjarmason wrote:\n> Add a --no-tags option to \"git clone\" to clone without tags. Currently\n> there's no easy way to clone a repository and end up with just a\n> \"master\" branch via --single-branch, or track all branches and no\n> tags. Now --no-tags can be added to \"git clone\" with or without\n> --single-branch to clone a repository without tags.\n> \n> Before this the only way of doing this was either by manually tweaking\n> the config in a fresh repository:\n> \n>     git init git &&\n>     cat >git/.git/config <<EOF &&\n>     [remote \"origin\"]\n>         url = git@github.com:git/git.git\n>         tagOpt = --no-tags\n>         fetch = +refs/heads/master:refs/remotes/origin/master\n>     [branch \"master\"]\n>         remote = origin\n>         merge = refs/heads/master\n>     EOF\n>     cd git &&\n>     git pull\n> \n> Which requires hardcoding the \"master\" name, which may not be the same\n> branch, or alternatively by setting tagOpt=--no-tags right after\n> cloning & deleting any existing tags:\n> \n>     git clone --single-branch git@github.com:git/git.git &&\n>     cd git &&\n>     git config remote.origin.tagOpt --no-tags &&\n>     git tag -l | xargs git tag -d\n> \n> Which of course was also subtly buggy if --branch was pointed at a\n> tag, leaving the user in a detached head:\n> \n>     git clone --single-branch --branch v2.12.0 git@github.com:git/git.git &&\n>     cd git &&\n>     git config remote.origin.tagOpt --no-tags &&\n>     git tag -l | xargs git tag -d\n> \n> Now all this complexity becomes the much simpler:\n> \n>     git clone --single-branch --no-tags git@github.com:git/git.git\n> \n> Or in the case of cloning a single tag \"branch\":\n> \n>     git clone --single-branch --branch v2.12.0 --no-tags git@github.com:git/git.git\n> \n> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n> ---\n\nPatch seems sane to me.\n\n-- \nBrandon Williams\n"},{"id":"317169","messageId":"xmqq60i1dvnk.fsf@gitster.mtv.corp.google.com","threadId":"45697","inReplyTo":"20170418191553.15464-1-avarab@gmail.com","subject":"Re: [PATCH] clone: add a --no-tags option to clone without tags","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-04-19T01:38:07Z","receivedAt":"2017-04-19T01:38:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> Add a --no-tags option to \"git clone\" to clone without tags. Currently\n> there's no easy way to clone a repository and end up with just a\n> \"master\" branch via --single-branch, or track all branches and no\n> tags. Now --no-tags can be added to \"git clone\" with or without\n> --single-branch to clone a repository without tags.\n\nMakes sense.\n\n> +--no-tags::\n> +\tDon't clone any tags, and set `remote.origin.tagOpt=--no-tags`\n> +\tin the config, ensuring that future `git pull` and `git fetch`\n> +\toperations won't fetch any tags.\n\nOK.  Not just we ignore tags during the initial cloning, we set\nthings up so that we do not _follow_ tags in subsequent fetches.\n\ns/won't fetch/won't follow/ is probably needed, as we still allow\nusers to fetch tags by explicitly naming them on the command line.\nThe only thing we are doing is to refrain from auto-following.\n\nAs an end-user facing help, exact configuration name and value is\nmuch less helpful than telling them the effect of the setting in the\nwords they understand, i.e. \"make later fetches not to follow tags\"\nor something.  Hardcoded 'origin' in `remote.origin.tagOpt` is not\ncorrect anyway, so I'd suggest redoing this part of the doc.\n\n> @@ -120,6 +121,8 @@ static struct option builtin_clone_options[] = {\n>  \t\t\tN_(\"deepen history of shallow clone, excluding rev\")),\n>  \tOPT_BOOL(0, \"single-branch\", &option_single_branch,\n>  \t\t    N_(\"clone only one branch, HEAD or --branch\")),\n> +\tOPT_BOOL_NONEG(0, \"no-tags\", &option_no_tags,\n> +\t\t       N_(\"don't clone any tags, and set remote.<name>.tagOpt=--no-tags\")),\n\nLikewise.  As an end-user facing help, exact configuration name and\nvalue is much less helpful than telling them the effect of the\nsetting in the words they understand, i.e. \"make later fetches not\nto follow tags\" or something.\n\n> +\tif (option_no_tags) {\n> +\t\tstrbuf_addf(&key, \"remote.%s.tagOpt\", option_origin);\n\nGood to use option_origin.  \n\n> +\t\tgit_config_set(key.buf, \"--no-tags\");\n> +\t\tstrbuf_reset(&key);\n> +\t}\n> +\n\nThanks.\n"},{"id":"317187","messageId":"xmqq1ssparom.fsf@gitster.mtv.corp.google.com","threadId":"45697","inReplyTo":"xmqq60i1dvnk.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH] clone: add a --no-tags option to clone without tags","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-04-19T05:32:09Z","receivedAt":"2017-04-19T05:32:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n>\n>> Add a --no-tags option to \"git clone\" to clone without tags. Currently\n>> there's no easy way to clone a repository and end up with just a\n>> \"master\" branch via --single-branch, or track all branches and no\n>> tags. Now --no-tags can be added to \"git clone\" with or without\n>> --single-branch to clone a repository without tags.\n>\n> Makes sense.\n>\n>> +--no-tags::\n>> +\tDon't clone any tags, and set `remote.origin.tagOpt=--no-tags`\n>> +\tin the config, ensuring that future `git pull` and `git fetch`\n>> +\toperations won't fetch any tags.\n>\n> OK.  Not just we ignore tags during the initial cloning, we set\n> things up so that we do not _follow_ tags in subsequent fetches.\n\nI somewhat doubt the utility of this change.  \"--single-branch\"\nalready refrains from grabbing all the tags, and the tags it grabs\nwhen \"clone\" runs and also in subsequent \"fetch\" are only the ones\nrelevant to that branch.  When a user is fetching say 'maint', it is\nvery likely that the user wants tags that are reachable from the tip\nof 'maint' (if only to make the tip of that branch describable),\neven though the user would not care about the tags on the other\nbranches that are ahead of 'maint'.\n\nIt is not that much code, and carrying it is not that much burden,\nbut I am reasonably sure that I won't use it myself.\n\n\n\n"},{"id":"317239","messageId":"20170419143831.6868-1-avarab@gmail.com","threadId":"45697","inReplyTo":"xmqq60i1dvnk.fsf@gitster.mtv.corp.google.com","subject":"[PATCH v2] clone: add a --no-tags option to clone without tags","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2017-04-19T14:38:31Z","receivedAt":"2017-04-19T14:39:10Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Add a --no-tags option to \"git clone\" to clone without tags. Currently\nthere's no easy way to clone a repository and end up with just a\n\"master\" branch via --single-branch, or track all branches and no\ntags. Now --no-tags can be added to \"git clone\" with or without\n--single-branch to clone a repository without tags.\n\nBefore this the only way of doing this was either by manually tweaking\nthe config in a fresh repository:\n\n    git init git &&\n    cat >git/.git/config <<EOF &&\n    [remote \"origin\"]\n        url = git@github.com:git/git.git\n        tagOpt = --no-tags\n        fetch = +refs/heads/master:refs/remotes/origin/master\n    [branch \"master\"]\n        remote = origin\n        merge = refs/heads/master\n    EOF\n    cd git &&\n    git pull\n\nWhich requires hardcoding the \"master\" name, which may not be the same\nbranch, or alternatively by setting tagOpt=--no-tags right after\ncloning & deleting any existing tags:\n\n    git clone --single-branch git@github.com:git/git.git &&\n    cd git &&\n    git config remote.origin.tagOpt --no-tags &&\n    git tag -l | xargs git tag -d\n\nWhich of course was also subtly buggy if --branch was pointed at a\ntag, leaving the user in a detached head:\n\n    git clone --single-branch --branch v2.12.0 git@github.com:git/git.git &&\n    cd git &&\n    git config remote.origin.tagOpt --no-tags &&\n    git tag -l | xargs git tag -d\n\nNow all this complexity becomes the much simpler:\n\n    git clone --single-branch --no-tags git@github.com:git/git.git\n\nOr in the case of cloning a single tag \"branch\":\n\n    git clone --single-branch --branch v2.12.0 --no-tags git@github.com:git/git.git\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n\nOn Wed, Apr 19, 2017 at 3:38 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n>\n>> Add a --no-tags option to \"git clone\" to clone without tags. Currently\n>> there's no easy way to clone a repository and end up with just a\n>> \"master\" branch via --single-branch, or track all branches and no\n>> tags. Now --no-tags can be added to \"git clone\" with or without\n>> --single-branch to clone a repository without tags.\n>\n> Makes sense.\n>\n>> +--no-tags::\n>> +     Don't clone any tags, and set `remote.origin.tagOpt=--no-tags`\n>> +     in the config, ensuring that future `git pull` and `git fetch`\n>> +     operations won't fetch any tags.\n>\n> OK.  Not just we ignore tags during the initial cloning, we set\n> things up so that we do not _follow_ tags in subsequent fetches.\n>\n> s/won't fetch/won't follow/ is probably needed, as we still allow\n> users to fetch tags by explicitly naming them on the command line.\n> The only thing we are doing is to refrain from auto-following.\n>\n> As an end-user facing help, exact configuration name and value is\n> much less helpful than telling them the effect of the setting in the\n> words they understand, i.e. \"make later fetches not to follow tags\"\n> or something.  \n\nI reworded all of this to hopefully be more helpful.\n\n> Hardcoded 'origin' in `remote.origin.tagOpt` is not correct anyway,\n> so I'd suggest redoing this part of the doc.\n\nChanged, FWIW various parts of the existing clone docs do the same\nthing, so a follow-up change to that would make sense...\n\n>> @@ -120,6 +121,8 @@ static struct option builtin_clone_options[] = {\n>>                       N_(\"deepen history of shallow clone, excluding rev\")),\n>>       OPT_BOOL(0, \"single-branch\", &option_single_branch,\n>>                   N_(\"clone only one branch, HEAD or --branch\")),\n>> +     OPT_BOOL_NONEG(0, \"no-tags\", &option_no_tags,\n>> +                    N_(\"don't clone any tags, and set remote.<name>.tagOpt=--no-tags\")),\n>\n> Likewise.  As an end-user facing help, exact configuration name and\n> value is much less helpful than telling them the effect of the\n> setting in the words they understand, i.e. \"make later fetches not\n> to follow tags\" or something.\n\n*Nod* changed.\n\n>> +     if (option_no_tags) {\n>> +             strbuf_addf(&key, \"remote.%s.tagOpt\", option_origin);\n>\n> Good to use option_origin.\n>\n>> +             git_config_set(key.buf, \"--no-tags\");\n>> +             strbuf_reset(&key);\n>> +     }\n>> +\n>\n> Thanks.\n\n Documentation/git-clone.txt | 14 ++++++++-\n builtin/clone.c             | 13 ++++++--\n t/t5612-clone-refspec.sh    | 73 +++++++++++++++++++++++++++++++++++++++++++--\n 3 files changed, 95 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt\nindex 30052cce49..57b3f478ed 100644\n--- a/Documentation/git-clone.txt\n+++ b/Documentation/git-clone.txt\n@@ -13,7 +13,7 @@ SYNOPSIS\n \t  [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]\n \t  [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]\n \t  [--dissociate] [--separate-git-dir <git dir>]\n-\t  [--depth <depth>] [--[no-]single-branch]\n+\t  [--depth <depth>] [--[no-]single-branch] [--no-tags]\n \t  [--recurse-submodules] [--[no-]shallow-submodules]\n \t  [--jobs <n>] [--] <repository> [<directory>]\n \n@@ -215,6 +215,18 @@ objects from the source repository into a pack in the cloned repository.\n \tbranch when `--single-branch` clone was made, no remote-tracking\n \tbranch is created.\n \n+--no-tags::\n+\tDon't clone any tags, and set\n+\t`remote.<remote>.tagOpt=--no-tags` in the config, ensuring\n+\tthat future `git pull` and `git fetch` operations won't follow\n+\tany tags. Subsequent explicit tag fetches will still work,\n+\t(see linkgit:git-fetch[1]).\n++\n+Can be used in conjunction with `--single-branch` to clone & maintain\n+a branch with no references other than a single cloned branch. This is\n+useful e.g. to maintain minimal clones of the default branch of some\n+repository for search indexing.\n+\n --recurse-submodules[=<pathspec]::\n \tAfter the clone is created, initialize and clone submodules\n \twithin based on the provided pathspec.  If no pathspec is\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex de85b85254..05f52d6f2b 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -40,6 +40,7 @@ static const char * const builtin_clone_usage[] = {\n \n static int option_no_checkout, option_bare, option_mirror, option_single_branch = -1;\n static int option_local = -1, option_no_hardlinks, option_shared;\n+static int option_no_tags;\n static int option_shallow_submodules;\n static int deepen;\n static char *option_template, *option_depth, *option_since;\n@@ -120,6 +121,8 @@ static struct option builtin_clone_options[] = {\n \t\t\tN_(\"deepen history of shallow clone, excluding rev\")),\n \tOPT_BOOL(0, \"single-branch\", &option_single_branch,\n \t\t    N_(\"clone only one branch, HEAD or --branch\")),\n+\tOPT_BOOL(0, \"no-tags\", &option_no_tags,\n+\t\t N_(\"don't clone any tags, and make later fetches not to follow them\")),\n \tOPT_BOOL(0, \"shallow-submodules\", &option_shallow_submodules,\n \t\t    N_(\"any cloned submodules will be shallow\")),\n \tOPT_STRING(0, \"separate-git-dir\", &real_git_dir, N_(\"gitdir\"),\n@@ -563,7 +566,7 @@ static struct ref *wanted_peer_refs(const struct ref *refs,\n \t} else\n \t\tget_fetch_map(refs, refspec, &tail, 0);\n \n-\tif (!option_mirror && !option_single_branch)\n+\tif (!option_mirror && !option_single_branch && !option_no_tags)\n \t\tget_fetch_map(refs, tag_refspec, &tail, 0);\n \n \treturn local_refs;\n@@ -652,7 +655,7 @@ static void update_remote_refs(const struct ref *refs,\n \n \tif (refs) {\n \t\twrite_remote_refs(mapped_refs);\n-\t\tif (option_single_branch)\n+\t\tif (option_single_branch && !option_no_tags)\n \t\t\twrite_followtags(refs, msg);\n \t}\n \n@@ -1035,6 +1038,12 @@ int cmd_clone(int argc, const char **argv, const char *prefix)\n \tgit_config_set(key.buf, repo);\n \tstrbuf_reset(&key);\n \n+\tif (option_no_tags) {\n+\t\tstrbuf_addf(&key, \"remote.%s.tagOpt\", option_origin);\n+\t\tgit_config_set(key.buf, \"--no-tags\");\n+\t\tstrbuf_reset(&key);\n+\t}\n+\n \tif (option_required_reference.nr || option_optional_reference.nr)\n \t\tsetup_reference();\n \ndiff --git a/t/t5612-clone-refspec.sh b/t/t5612-clone-refspec.sh\nindex 7ace2535c8..83317805a8 100755\n--- a/t/t5612-clone-refspec.sh\n+++ b/t/t5612-clone-refspec.sh\n@@ -17,13 +17,20 @@ test_expect_success 'setup' '\n \techo four >file &&\n \tgit commit -a -m four &&\n \tgit checkout master &&\n+\tgit tag five &&\n \n \t# default clone\n \tgit clone . dir_all &&\n \n+\t# default clone --no-tags\n+\tgit clone --no-tags . dir_all_no_tags &&\n+\n \t# default --single that follows HEAD=master\n \tgit clone --single-branch . dir_master &&\n \n+\t# default --single that follows HEAD=master with no tags\n+\tgit clone --single-branch --no-tags . dir_master_no_tags &&\n+\n \t# default --single that follows HEAD=side\n \tgit checkout side &&\n \tgit clone --single-branch . dir_side &&\n@@ -45,6 +52,9 @@ test_expect_success 'setup' '\n \t# explicit --single with tag\n \tgit clone --single-branch --branch two . dir_tag &&\n \n+\t# explicit --single with tag and --no-tags\n+\tgit clone --single-branch --no-tags --branch two . dir_tag_no_tags &&\n+\n \t# advance both \"master\" and \"side\" branches\n \tgit checkout side &&\n \techo five >file &&\n@@ -75,7 +85,17 @@ test_expect_success 'by default no tags will be kept updated' '\n \t\tgit for-each-ref refs/tags >../actual\n \t) &&\n \tgit for-each-ref refs/tags >expect &&\n-\ttest_must_fail test_cmp expect actual\n+\ttest_must_fail test_cmp expect actual &&\n+\ttest_line_count = 2 actual\n+'\n+\n+test_expect_success 'clone with --no-tags' '\n+\t(\n+\t\tcd dir_all_no_tags && git fetch &&\n+\t\tgit for-each-ref refs/tags >../actual\n+\t) &&\n+\t>expect &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success '--single-branch while HEAD pointing at master' '\n@@ -87,7 +107,46 @@ test_expect_success '--single-branch while HEAD pointing at master' '\n \t) &&\n \t# only follow master\n \tgit for-each-ref refs/heads/master >expect &&\n-\ttest_cmp expect actual\n+\t# get & check latest tags\n+\ttest_cmp expect actual &&\n+\t(\n+\t\tcd dir_master &&\n+\t\tgit fetch --tags &&\n+\t\tgit for-each-ref refs/tags >../actual\n+\t) &&\n+\tgit for-each-ref refs/tags >expect &&\n+\ttest_cmp expect actual &&\n+\ttest_line_count = 2 actual\n+'\n+\n+test_expect_success '--single-branch while HEAD pointing at master and --no-tags' '\n+\t(\n+\t\tcd dir_master_no_tags && git fetch &&\n+\t\tgit for-each-ref refs/remotes/origin |\n+\t\tsed -e \"/HEAD$/d\" \\\n+\t\t    -e \"s|/remotes/origin/|/heads/|\" >../actual\n+\t) &&\n+\t# only follow master\n+\tgit for-each-ref refs/heads/master >expect &&\n+\ttest_cmp expect actual &&\n+\t# get tags (noop)\n+\t(\n+\t\tcd dir_master_no_tags &&\n+\t\tgit fetch &&\n+\t\tgit for-each-ref refs/tags >../actual\n+\t) &&\n+\t>expect &&\n+\ttest_cmp expect actual &&\n+\ttest_line_count = 0 actual &&\n+\t# get tags with --tags overrides tagOpt\n+\t(\n+\t\tcd dir_master_no_tags &&\n+\t\tgit fetch --tags &&\n+\t\tgit for-each-ref refs/tags >../actual\n+\t) &&\n+\tgit for-each-ref refs/tags >expect &&\n+\ttest_cmp expect actual &&\n+\ttest_line_count = 2 actual\n '\n \n test_expect_success '--single-branch while HEAD pointing at side' '\n@@ -123,6 +182,16 @@ test_expect_success '--single-branch with explicit --branch with tag fetches upd\n \ttest_cmp expect actual\n '\n \n+test_expect_success '--single-branch with explicit --branch with tag fetches updated tag despite --no-tags' '\n+\t(\n+\t\tcd dir_tag_no_tags && git fetch &&\n+\t\tgit for-each-ref refs/tags >../actual\n+\t) &&\n+\tgit for-each-ref refs/tags/two >expect &&\n+\ttest_cmp expect actual &&\n+\ttest_line_count = 1 actual\n+'\n+\n test_expect_success '--single-branch with --mirror' '\n \t(\n \t\tcd dir_mirror && git fetch &&\n-- \n2.11.0\n\n"},{"id":"317870","messageId":"20170425223533.GL28740@aiede.svl.corp.google.com","threadId":"45697","inReplyTo":"20170418191553.15464-1-avarab@gmail.com","subject":"Re: [PATCH] clone: add a --no-tags option to clone without tags","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2017-04-25T22:35:33Z","receivedAt":"2017-04-25T22:35:43Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Hi,\n\nÆvar Arnfjörð Bjarmason wrote:\n\n> Add a --no-tags option to \"git clone\" to clone without tags. Currently\n> there's no easy way to clone a repository and end up with just a\n> \"master\" branch via --single-branch, or track all branches and no\n> tags. Now --no-tags can be added to \"git clone\" with or without\n> --single-branch to clone a repository without tags.\n\nCould --single-branch be made to imply --no-tags, like --depth implies\n--single-branch?  After all, all I wanted is that one branch, not some\ntags.\n\nCallers who really want the tags could still pass --tags to request\nthat.\n\nJust thinking out loud,\nJonathan\n"},{"id":"317871","messageId":"20170425224521.GM28740@aiede.svl.corp.google.com","threadId":"45697","inReplyTo":"20170419143831.6868-1-avarab@gmail.com","subject":"Re: [PATCH v2] clone: add a --no-tags option to clone without tags","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2017-04-25T22:45:22Z","receivedAt":"2017-04-25T22:45:36Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Hi,\n\nÆvar Arnfjörð Bjarmason wrote:\n\n> Add a --no-tags option to \"git clone\" to clone without tags. Currently\n> there's no easy way to clone a repository and end up with just a\n> \"master\" branch via --single-branch, or track all branches and no\n> tags. Now --no-tags can be added to \"git clone\" with or without\n> --single-branch to clone a repository without tags.\n\nNow I've read the discussion from v1, so you can see my thoughts\nevolving in real time. :)\n\nThe above feels a bit misleading when it says \"there's no easy way to\nclone a repository and end up with just a 'master' branch\".\n--single-branch does exactly that.  Some annotated tags *pointing to\nits history* come along for the ride, but what harm are they doing?\n\nIn other words, I think the commit message needs a bit more detail about\nthe use case, to say why omitting those tags is useful.  The use case\nis probably sane but it is not explained.  A side effect (and my main\nmotivation) is that this would make it crystal clear to people looking\nat the patch in history that it is talking about tags that are part of\n\"master\"'s history, not tags pointing elsewhere.\n\n> Before this the only way of doing this was either by manually tweaking\n> the config in a fresh repository:\n\nUsually commit messages refer to the state of things without some\npatch using the present tense --- e.g. \"Without this patch, this\n--no-tags option can be emulated by (1) manually tweaking the config\nin a fresh repository, or (2) by setting tagOpt=--no-tags after\ncloning and deleting any existing tags\".\n\n[...]\n> Which of course was also subtly buggy if --branch was pointed at a\n> tag, leaving the user in a detached head:\n>\n>     git clone --single-branch --branch v2.12.0 git@github.com:git/git.git &&\n>     cd git &&\n>     git config remote.origin.tagOpt --no-tags &&\n>     git tag -l | xargs git tag -d\n\nAt this point I lose the trail of thought.  I don't think it's\nimportant to understanding the patch.\n\n> Now all this complexity becomes the much simpler:\n>\n>     git clone --single-branch --no-tags git@github.com:git/git.git\n>\n> Or in the case of cloning a single tag \"branch\":\n>\n>     git clone --single-branch --branch v2.12.0 --no-tags git@github.com:git/git.git\n\nNice.\n\n[...]\n>  Documentation/git-clone.txt | 14 ++++++++-\n>  builtin/clone.c             | 13 ++++++--\n>  t/t5612-clone-refspec.sh    | 73 +++++++++++++++++++++++++++++++++++++++++++--\n>  3 files changed, 95 insertions(+), 5 deletions(-)\n> \n> diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt\n> index 30052cce49..57b3f478ed 100644\n> --- a/Documentation/git-clone.txt\n> +++ b/Documentation/git-clone.txt\n> @@ -13,7 +13,7 @@ SYNOPSIS\n>  \t  [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]\n>  \t  [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]\n>  \t  [--dissociate] [--separate-git-dir <git dir>]\n> -\t  [--depth <depth>] [--[no-]single-branch]\n> +\t  [--depth <depth>] [--[no-]single-branch] [--no-tags]\n\nCan I pass --tags to negate a previous --no-tags?\n\n[...]\n> +--no-tags::\n> +\tDon't clone any tags, and set\n> +\t`remote.<remote>.tagOpt=--no-tags` in the config, ensuring\n> +\tthat future `git pull` and `git fetch` operations won't follow\n> +\tany tags. Subsequent explicit tag fetches will still work,\n> +\t(see linkgit:git-fetch[1]).\n> ++\n> +Can be used in conjunction with `--single-branch` to clone & maintain\n\nnit: s/&/and/\n\n[...]\n> +test_expect_success 'clone with --no-tags' '\n> +\t(\n> +\t\tcd dir_all_no_tags && git fetch &&\n> +\t\tgit for-each-ref refs/tags >../actual\n\nnit: this would be easier to read with the 'cd' and 'git fetch' on\nseparate lines.\n\n[...]\n> +test_expect_success '--single-branch while HEAD pointing at master and --no-tags' '\n> +\t(\n> +\t\tcd dir_master_no_tags && git fetch &&\n\nLikewise.\n\n> +\t\tgit for-each-ref refs/remotes/origin |\n> +\t\tsed -e \"/HEAD$/d\" \\\n> +\t\t    -e \"s|/remotes/origin/|/heads/|\" >../actual\n\nCan $/ be expanded by the shell?\n\nThe rest looks sensible.\n\nThanks and hope that helps,\nJonathan\n"},{"id":"317885","messageId":"xmqq60hsufgv.fsf@gitster.mtv.corp.google.com","threadId":"45697","inReplyTo":"20170425224521.GM28740@aiede.svl.corp.google.com","subject":"Re: [PATCH v2] clone: add a --no-tags option to clone without tags","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2017-04-26T01:26:08Z","receivedAt":"2017-04-26T01:26:18Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jonathan Nieder <jrnieder@gmail.com> writes:\n\n> In other words, I think the commit message needs a bit more detail about\n> the use case, to say why omitting those tags is useful.  The use case\n> is probably sane but it is not explained.  A side effect (and my main\n> motivation) is that this would make it crystal clear to people looking\n> at the patch in history that it is talking about tags that are part of\n> \"master\"'s history, not tags pointing elsewhere.\n\nI agree that it is unclear \"having no tags, not even the harmless\nand usually useful ones that point at the history of the branch of\ninterest\" is the point of this new feature from the documentation\nand log message.  \n\nResponding to your other message, I do not think this new feature\nshould be tied to --single-branch; I think having the tags to mark\ncommits in the branch's history (while not fetching other tags\nirrelevant to the branch's history) is usually what users would\nwant.\n\n>> Before this the only way of doing this was either by manually tweaking\n>> the config in a fresh repository:\n>\n> Usually commit messages refer to the state of things without some\n> patch using the present tense --- e.g. \"Without this patch, this\n> --no-tags option can be emulated by (1) manually tweaking the config\n> in a fresh repository, or (2) by setting tagOpt=--no-tags after\n> cloning and deleting any existing tags\".\n\nThanks--I'll use this myself when responding to patches from other\npeople.  I recall getting irritated while reading some patches and\ncouldn't pinpoint why they were irritating, and now I realize that\nit was because they said \"Previously Git did X.\" and somesuch.\n\n"},{"id":"317907","messageId":"CACBZZX7u_1hifAHxNJU+WCkdk2+s63PV5F5dSx=M5azPE4Ra0A@mail.gmail.com","threadId":"45697","inReplyTo":"20170425224521.GM28740@aiede.svl.corp.google.com","subject":"Re: [PATCH v2] clone: add a --no-tags option to clone without tags","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2017-04-26T08:56:28Z","receivedAt":"2017-04-26T08:56:58Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Wed, Apr 26, 2017 at 12:45 AM, Jonathan Nieder <jrnieder@gmail.com> wrote:\n> Hi,\n>\n> Ęvar Arnfjörš Bjarmason wrote:\n>\n>> Add a --no-tags option to \"git clone\" to clone without tags. Currently\n>> there's no easy way to clone a repository and end up with just a\n>> \"master\" branch via --single-branch, or track all branches and no\n>> tags. Now --no-tags can be added to \"git clone\" with or without\n>> --single-branch to clone a repository without tags.\n>\n> Now I've read the discussion from v1, so you can see my thoughts\n> evolving in real time. :)\n>\n> The above feels a bit misleading when it says \"there's no easy way to\n> clone a repository and end up with just a 'master' branch\".\n> --single-branch does exactly that.\n\nI'll reword this, what I meant is \"just a master branch [and no other\nreferences]\". Not \"just the master branch [and no other branches]\".\n\n> Some annotated tags *pointing to\n> its history* come along for the ride, but what harm are they doing?\n\nI'll explain this in a bit more detail in the commit message & docs,\nboth you & Junio (in <xmqq1ssparom.fsf@gitster.mtv.corp.google.com>)\nseem to be making the assumption that only getting & maintaining the\ntags for the branch you're cloning is cheap.\n\nThis assumes a repo that while large, doesn't get a lot of releases on\nits main branch. E.g. linux.git has ~650k commits, and ~500 v* tags,\nthat's a tag every 1300 commits or so.\n\nNow if you run this on linux.git:\n\n    $ git rev-list origin/master | parallel -j6 --progress 'test\n\"$(echo {} | cut -b1)\" = 0 && git tag -a -m\"msg\" test-tag-{}'\n\nYou'll get a tag a bit more than every 16 commits, and now a lot of\neveryday commands become slow, because a lot of them need to look at\nevery ref before they start:\n\n    $ (time (git log -1 >/dev/null)) 2>&1|grep ^real\n    real    0m1.304s\n\nWhereas on a linux.git without all those tags:\n\n    $ (time (git log -1 >/dev/null)) 2>&1|grep ^real\n    real    0m0.027s\n\nAnd you can imagine what this does to some other commands, e.g. bash completion:\n\n    $ git log <TAB>\n    Display all 512 possibilities? (y or n)\n\nv.s.:\n\n    $ git log <TAB>\n    Display all 42129 possibilities? (y or n)\n\nFurthermore, if upstream has a high tag churn, i.e. creates lots of\ntags but prunes them regularly even if you set tagOpts=--prune you'll\nstill end up with an every slower local repository as you slowly\naccumulate every tag upstream has created every, you'd need to fetch\nwith:\n\n    $ git fetch origin --prune 'refs/tags/*:refs/tags/*'\n\nSimply never fetching the tags in the first place & making sure they\naren't fetched avoids all of this, and is perfect e.g. for the use\ncase of something that runs an automated \"pull\" on the repo to index\nits code (I initially wrote this for a https://github.com/etsy/hound/\nsetup), or if you'd just like to run the likes of \"git log\" on the\nmaster branch without starting that up taking a second longer.\n\n> In other words, I think the commit message needs a bit more detail about\n> the use case, to say why omitting those tags is useful.  The use case\n> is probably sane but it is not explained.  A side effect (and my main\n> motivation) is that this would make it crystal clear to people looking\n> at the patch in history that it is talking about tags that are part of\n> \"master\"'s history, not tags pointing elsewhere.\n\nI'll add that.\n\n>> Before this the only way of doing this was either by manually tweaking\n>> the config in a fresh repository:\n>\n> Usually commit messages refer to the state of things without some\n> patch using the present tense --- e.g. \"Without this patch, this\n> --no-tags option can be emulated by (1) manually tweaking the config\n> in a fresh repository, or (2) by setting tagOpt=--no-tags after\n> cloning and deleting any existing tags\".\n>\n> [...]\n>> Which of course was also subtly buggy if --branch was pointed at a\n>> tag, leaving the user in a detached head:\n>>\n>>     git clone --single-branch --branch v2.12.0 git@github.com:git/git.git &&\n>>     cd git &&\n>>     git config remote.origin.tagOpt --no-tags &&\n>>     git tag -l | xargs git tag -d\n>\n> At this point I lose the trail of thought.  I don't think it's\n> important to understanding the patch.\n\nI'm going to leave that in because anyone who needs this feature for a\nsimilar use-case (which I'll explain in more detail), would need to do\nexactly that to get a bug-compatible version of the same behavior if\nthey need to run on an older git version for whatever reason.\n\n>> Now all this complexity becomes the much simpler:\n>>\n>>     git clone --single-branch --no-tags git@github.com:git/git.git\n>>\n>> Or in the case of cloning a single tag \"branch\":\n>>\n>>     git clone --single-branch --branch v2.12.0 --no-tags git@github.com:git/git.git\n>\n> Nice.\n>\n> [...]\n>>  Documentation/git-clone.txt | 14 ++++++++-\n>>  builtin/clone.c             | 13 ++++++--\n>>  t/t5612-clone-refspec.sh    | 73 +++++++++++++++++++++++++++++++++++++++++++--\n>>  3 files changed, 95 insertions(+), 5 deletions(-)\n>>\n>> diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt\n>> index 30052cce49..57b3f478ed 100644\n>> --- a/Documentation/git-clone.txt\n>> +++ b/Documentation/git-clone.txt\n>> @@ -13,7 +13,7 @@ SYNOPSIS\n>>         [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]\n>>         [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]\n>>         [--dissociate] [--separate-git-dir <git dir>]\n>> -       [--depth <depth>] [--[no-]single-branch]\n>> +       [--depth <depth>] [--[no-]single-branch] [--no-tags]\n>\n> Can I pass --tags to negate a previous --no-tags?\n\nYeah both --tags and --no-no-tags work as with every other OPT_BOOL\noption. See \"[RFC PATCH] parse-options: disallow double-negations of\noptions starting with no-\".\n\n> [...]\n>> +--no-tags::\n>> +     Don't clone any tags, and set\n>> +     `remote.<remote>.tagOpt=--no-tags` in the config, ensuring\n>> +     that future `git pull` and `git fetch` operations won't follow\n>> +     any tags. Subsequent explicit tag fetches will still work,\n>> +     (see linkgit:git-fetch[1]).\n>> ++\n>> +Can be used in conjunction with `--single-branch` to clone & maintain\n>\n> nit: s/&/and/\n\nWill fix.\n\n> [...]\n>> +test_expect_success 'clone with --no-tags' '\n>> +     (\n>> +             cd dir_all_no_tags && git fetch &&\n>> +             git for-each-ref refs/tags >../actual\n>\n> nit: this would be easier to read with the 'cd' and 'git fetch' on\n> separate lines.\n>\n> [...]\n>> +test_expect_success '--single-branch while HEAD pointing at master and --no-tags' '\n>> +     (\n>> +             cd dir_master_no_tags && git fetch &&\n>\n> Likewise.\n\nThis was following the existing style in the file, but sure, I'll\nprepend a patch to this series to fix all of that before building this\npatch on top.\n\n>> +             git for-each-ref refs/remotes/origin |\n>> +             sed -e \"/HEAD$/d\" \\\n>> +                 -e \"s|/remotes/origin/|/heads/|\" >../actual\n>\n> Can $/ be expanded by the shell?\n\nI think not, and if there's some issue with it it's obscure enough to\nnot have caused issues since 31b808a032 (\"clone --single: limit the\nfetch refspec to fetched branch\", 2012-09-20) which introduced this\npattern earlier in the test file, I'm just copy/pasting similar setup\nfrom elsewhere in the file.\n"}]}