Is there a way to get 'git fetch --no-tags' semantics with 'git clone'?
As far as I can tell the only way to clone a given upstream repo, which has an unknown main branch name without any tags is:
git clone --single-branch <url> <repo> &&
cd <repo> &&
git tag -d $(git tag -l) &&
git config remote.origin.tagOpt --no-tagsIs there really nothing like:
git clone --single-branch --no-tags <url> <repo>
?
I suppose this can be done with the usual 'git init`, set the config & then fetch dance, but in that case what part of 'git remote' or friends exposes finding the remote "main" ref as --single-branch does?
PATCH 1/1 clone: add a --no-tags option to clone without tags
Add a --no-tags option to "git clone" to clone without tags. Currently there's no easy way to clone a repository and end up with just a "master" branch via --single-branch, or track all branches and no tags. Now --no-tags can be added to "git clone" with or without --single-branch to clone a repository without tags.
Before this the only way of doing this was either by manually tweaking the config in a fresh repository:
git init git &&
cat >git/.git/config <<EOF &&
[remote "origin"]
url = [email protected]:git/git.git
tagOpt = --no-tags
fetch = +refs/heads/master:refs/remotes/origin/master
[branch "master"]
remote = origin
merge = refs/heads/master
EOF
cd git &&
git pull
Which requires hardcoding the "master" name, which may not be the same branch, or alternatively by setting tagOpt=--no-tags right after cloning & deleting any existing tags:
git clone --single-branch [email protected]:git/git.git && cd git && git config remote.origin.tagOpt --no-tags && git tag -l | xargs git tag -d
Which of course was also subtly buggy if --branch was pointed at a tag, leaving the user in a detached head:
git clone --single-branch --branch v2.12.0 [email protected]:git/git.git && cd git && git config remote.origin.tagOpt --no-tags && git tag -l | xargs git tag -d
Now all this complexity becomes the much simpler:
git clone --single-branch --no-tags [email protected]:git/git.git
Or in the case of cloning a single tag "branch":
git clone --single-branch --branch v2.12.0 --no-tags [email protected]:git/git.git
---
Quoted 10 lines · Ævar Arnfjörð Bjarmason
As far as I can tell the only way to clone a given upstream repo, which has an unknown main branch name without any tags is:
git clone --single-branch <url> <repo> && cd <repo> && git tag -d $(git tag -l) && git config remote.origin.tagOpt --no-tagsIs there really nothing like:
Quoted 7 lines
git clone --single-branch --no-tags <url> <repo>?
I suppose this can be done with the usual 'git init`, set the config & then fetch dance, but in that case what part of 'git remote' or friends exposes finding the remote "main" ref as --single-branch does?
Here's a patch which implements this. It works, and I think it makes sense for inclusion. It would be logical to follow this up with a --no-tags-submodules similar to --no-shallow-submodules, but I ran out of time.
Documentation/git-clone.txt | 12 +++++++- builtin/clone.c | 13 ++++++-- t/t5612-clone-refspec.sh | 73 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 93 insertions(+), 5 deletions(-)
Documentation/git-clone.txt +11 -1
@@ -13,7 +13,7 @@ SYNOPSIS [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror] [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>] [--dissociate] [--separate-git-dir <git dir>] - [--depth <depth>] [--[no-]single-branch] + [--depth <depth>] [--[no-]single-branch] [--no-tags] [--recurse-submodules] [--[no-]shallow-submodules] [--jobs <n>] [--] <repository> [<directory>]
@@ -215,6 +215,16 @@ objects from the source repository into a pack in the cloned repository. branch when `--single-branch` clone was made, no remote-tracking branch is created. +--no-tags:: + Don't clone any tags, and set `remote.origin.tagOpt=--no-tags` + in the config, ensuring that future `git pull` and `git fetch` + operations won't fetch any tags. ++ +Can be used in conjunction with `--single-branch` to clone & 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]:: After the clone is created, initialize and clone submodules within based on the provided pathspec. If no pathspec is
builtin/clone.c +11 -2
@@ -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_local =-1 , option_no_hardlinks, option_shared; +static int option_no_tags;static int option_shallow_submodules;static int deepen;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")),OPT_BOOL (0 ,"single-branch" , &option_single_branch,N_ ("clone only one branch, HEAD or --branch" )), +OPT_BOOL_NONEG (0 ,"no-tags" , &option_no_tags, +N_ ("don't clone any tags, and set remote.<name>.tagOpt=--no-tags" )),OPT_BOOL (0 ,"shallow-submodules" , &option_shallow_submodules,N_ ("any cloned submodules will be shallow" )), 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 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 );return local_refs;
@@ -652,7 +655,7 @@ static void update_remote_refs(const struct ref *refs,if (refs) {write_remote_refs (mapped_refs); -if (option_single_branch) +if (option_single_branch && !option_no_tags)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);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)setup_reference ();
t/t5612-clone-refspec.sh +71 -2
110 lines not on this page · raw message
Signature · 1 line
2.11.0
Re: [PATCH] clone: add a --no-tags option to clone without tags
builtin/clone.c static struct option builtin_clone_options[] = { · line 126
Quoted 4 lines · Ævar Arnfjörð Bjarmason
N_("clone only one branch, HEAD or --branch")),builtin/clone.c +2
-0+OPT_BOOL_NONEG (0 ,"no-tags" , &option_no_tags, +N_ ("don't clone any tags, and set remote.<name>.tagOpt=--no-tags" )), OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules,
I forgot to note that this is on top of my earlier patch which adds OPT_BOOL_NONEG, see <[email protected]>, but otherwise applies on top of master, and will work just fine by amending that to say OPT_BOOL (although --no-no-tags will then exist, as noted in the other patch).
Re: [PATCH] clone: add a --no-tags option to clone without tags
In reply to Ævar Arnfjörð BjarmasonQuoted 41 lines · Ævar Arnfjörð Bjarmason
Add a --no-tags option to "git clone" to clone without tags. Currently there's no easy way to clone a repository and end up with just a "master" branch via --single-branch, or track all branches and no tags. Now --no-tags can be added to "git clone" with or without --single-branch to clone a repository without tags.
Before this the only way of doing this was either by manually tweaking the config in a fresh repository:
git init git &&
cat >git/.git/config <<EOF &&
[remote "origin"]
url = [email protected]:git/git.git
tagOpt = --no-tags
fetch = +refs/heads/master:refs/remotes/origin/master
[branch "master"]
remote = origin
merge = refs/heads/master
EOF
cd git &&
git pullWhich requires hardcoding the "master" name, which may not be the same branch, or alternatively by setting tagOpt=--no-tags right after cloning & deleting any existing tags:
git clone --single-branch [email protected]:git/git.git && cd git && git config remote.origin.tagOpt --no-tags && git tag -l | xargs git tag -dWhich of course was also subtly buggy if --branch was pointed at a tag, leaving the user in a detached head:
git clone --single-branch --branch v2.12.0 [email protected]:git/git.git && cd git && git config remote.origin.tagOpt --no-tags && git tag -l | xargs git tag -dNow all this complexity becomes the much simpler:
Quoted 8 lines
git clone --single-branch --no-tags [email protected]:git/git.gitOr in the case of cloning a single tag "branch":
git clone --single-branch --branch v2.12.0 --no-tags [email protected]:git/git.gitSigned-off-by Ævar Arnfjörð Bjarmason <[email protected]>---
Patch seems sane to me.
Signature · 1 line
Brandon Williams
Re: [PATCH] clone: add a --no-tags option to clone without tags
In reply to Ævar Arnfjörð BjarmasonQuoted 5 lines · Ævar Arnfjörð Bjarmason
Add a --no-tags option to "git clone" to clone without tags. Currently there's no easy way to clone a repository and end up with just a "master" branch via --single-branch, or track all branches and no tags. Now --no-tags can be added to "git clone" with or without --single-branch to clone a repository without tags.
Makes sense.
Documentation/git-clone.txt objects from the source repository into a pack in the cloned repository. · line 221
Quoted 4 lines
+--no-tags::
Documentation/git-clone.txt +3
-0+ Don't clone any tags, and set `remote.origin.tagOpt=--no-tags` + in the config, ensuring that future `git pull` and `git fetch` + operations won't fetch any tags.
OK. Not just we ignore tags during the initial cloning, we set things up so that we do not _follow_ tags in subsequent fetches.
s/won't fetch/won't follow/ is probably needed, as we still allow users to fetch tags by explicitly naming them on the command line. The only thing we are doing is to refrain from auto-following.
As an end-user facing help, exact configuration name and value is much less helpful than telling them the effect of the setting in the words they understand, i.e. "make later fetches not to follow tags" or something. Hardcoded 'origin' in remote.origin.tagOpt is not correct anyway, so I'd suggest redoing this part of the doc.
builtin/clone.c static struct option builtin_clone_options[] = { · line 125
Quoted 6 lines
builtin/clone.c +2
-0@@ -120,6 +121,8 @@ static struct option builtin_clone_options[] = { N_("deepen history of shallow clone, excluding rev")),OPT_BOOL (0 ,"single-branch" , &option_single_branch,N_ ("clone only one branch, HEAD or --branch" )), +OPT_BOOL_NONEG (0 ,"no-tags" , &option_no_tags, + N_("don't clone any tags, and set remote.<name>.tagOpt=--no-tags")),
Likewise. As an end-user facing help, exact configuration name and value is much less helpful than telling them the effect of the setting in the words they understand, i.e. "make later fetches not to follow tags" or something.
builtin/clone.c int cmd_clone(int argc, const char **argv, const char *prefix) · line 1042
Quoted 2 lines
builtin/clone.c +2
-0+if (option_no_tags) { +strbuf_addf (&key,"remote.%s.tagOpt" , option_origin);
Good to use option_origin.
builtin/clone.c int cmd_clone(int argc, const char **argv, const char *prefix) · line 1046
Quoted 4 lines
builtin/clone.c +4
-0+git_config_set (key.buf,"--no-tags" ); +strbuf_reset (&key); + } +
Thanks.
Re: [PATCH] clone: add a --no-tags option to clone without tags
Quoted 10 lines · Junio C Hamano
Quoted 5 lines · Ævar Arnfjörð Bjarmason
Add a --no-tags option to "git clone" to clone without tags. Currently there's no easy way to clone a repository and end up with just a "master" branch via --single-branch, or track all branches and no tags. Now --no-tags can be added to "git clone" with or without --single-branch to clone a repository without tags.
Makes sense.
Quoted 7 lines
Documentation/git-clone.txt objects from the source repository into a pack in the cloned repository. · line 221
Quoted 4 lines
+--no-tags::
Documentation/git-clone.txt +3
-0+ Don't clone any tags, and set `remote.origin.tagOpt=--no-tags` + in the config, ensuring that future `git pull` and `git fetch` + operations won't fetch any tags.OK. Not just we ignore tags during the initial cloning, we set things up so that we do not _follow_ tags in subsequent fetches.
I somewhat doubt the utility of this change. "--single-branch" already refrains from grabbing all the tags, and the tags it grabs when "clone" runs and also in subsequent "fetch" are only the ones relevant to that branch. When a user is fetching say 'maint', it is very likely that the user wants tags that are reachable from the tip of 'maint' (if only to make the tip of that branch describable), even though the user would not care about the tags on the other branches that are ahead of 'maint'.
It is not that much code, and carrying it is not that much burden, but I am reasonably sure that I won't use it myself.
PATCH v2 1/1 clone: add a --no-tags option to clone without tags
In reply to Junio C HamanoAdd a --no-tags option to "git clone" to clone without tags. Currently there's no easy way to clone a repository and end up with just a "master" branch via --single-branch, or track all branches and no tags. Now --no-tags can be added to "git clone" with or without --single-branch to clone a repository without tags.
Before this the only way of doing this was either by manually tweaking the config in a fresh repository:
git init git &&
cat >git/.git/config <<EOF &&
[remote "origin"]
url = [email protected]:git/git.git
tagOpt = --no-tags
fetch = +refs/heads/master:refs/remotes/origin/master
[branch "master"]
remote = origin
merge = refs/heads/master
EOF
cd git &&
git pull
Which requires hardcoding the "master" name, which may not be the same branch, or alternatively by setting tagOpt=--no-tags right after cloning & deleting any existing tags:
git clone --single-branch [email protected]:git/git.git && cd git && git config remote.origin.tagOpt --no-tags && git tag -l | xargs git tag -d
Which of course was also subtly buggy if --branch was pointed at a tag, leaving the user in a detached head:
git clone --single-branch --branch v2.12.0 [email protected]:git/git.git && cd git && git config remote.origin.tagOpt --no-tags && git tag -l | xargs git tag -d
Now all this complexity becomes the much simpler:
git clone --single-branch --no-tags [email protected]:git/git.git
Or in the case of cloning a single tag "branch":
git clone --single-branch --branch v2.12.0 --no-tags [email protected]:git/git.git
---
Quoted 18 lines · Junio C Hamano
Quoted 5 lines · Ævar Arnfjörð Bjarmason
Add a --no-tags option to "git clone" to clone without tags. Currently there's no easy way to clone a repository and end up with just a "master" branch via --single-branch, or track all branches and no tags. Now --no-tags can be added to "git clone" with or without --single-branch to clone a repository without tags.
Makes sense.
Review
Quoted 4 lines
+--no-tags::
(quoted diff) +3
-0+ Don't clone any tags, and set `remote.origin.tagOpt=--no-tags` + in the config, ensuring that future `git pull` and `git fetch` + operations won't fetch any tags.OK. Not just we ignore tags during the initial cloning, we set things up so that we do not _follow_ tags in subsequent fetches.
Quoted 8 lines
s/won't fetch/won't follow/ is probably needed, as we still allow users to fetch tags by explicitly naming them on the command line. The only thing we are doing is to refrain from auto-following.
As an end-user facing help, exact configuration name and value is much less helpful than telling them the effect of the setting in the words they understand, i.e. "make later fetches not to follow tags" or something.
I reworded all of this to hopefully be more helpful.
Quoted 2 lines
Hardcoded 'origin' in
remote.origin.tagOptis not correct anyway, so I'd suggest redoing this part of the doc.
Changed, FWIW various parts of the existing clone docs do the same thing, so a follow-up change to that would make sense...
Quoted 11 lines
Review static struct option builtin_clone_options[] = { · line 125
Quoted 6 lines
(quoted diff) +2
-0@@ -120,6 +121,8 @@ static struct option builtin_clone_options[] = { N_("deepen history of shallow clone, excluding rev")), OPT_BOOL(0, "single-branch", &option_single_branch, N_("clone only one branch, HEAD or --branch")), + OPT_BOOL_NONEG(0, "no-tags", &option_no_tags, + N_("don't clone any tags, and set remote.<name>.tagOpt=--no-tags")),Likewise. As an end-user facing help, exact configuration name and value is much less helpful than telling them the effect of the setting in the words they understand, i.e. "make later fetches not to follow tags" or something.
*Nod* changed.
Quoted 11 lines
Review static struct option builtin_clone_options[] = { · line 127
Quoted 2 lines
(quoted diff) +2
-0+ if (option_no_tags) { + strbuf_addf(&key, "remote.%s.tagOpt", option_origin);Good to use
option_origin.Review static struct option builtin_clone_options[] = {
Quoted 4 lines
(quoted diff) +4
-0+ git_config_set(key.buf, "--no-tags"); + strbuf_reset(&key); + } +Thanks.
Documentation/git-clone.txt | 14 ++++++++- builtin/clone.c | 13 ++++++-- t/t5612-clone-refspec.sh | 73 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 95 insertions(+), 5 deletions(-)
Documentation/git-clone.txt +13 -1
@@ -13,7 +13,7 @@ SYNOPSIS [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror] [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>] [--dissociate] [--separate-git-dir <git dir>] - [--depth <depth>] [--[no-]single-branch] + [--depth <depth>] [--[no-]single-branch] [--no-tags] [--recurse-submodules] [--[no-]shallow-submodules] [--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 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 & 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]:: After the clone is created, initialize and clone submodules within based on the provided pathspec. If no pathspec is
builtin/clone.c +11 -2
@@ -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_local =-1 , option_no_hardlinks, option_shared; +static int option_no_tags;static int option_shallow_submodules;static int deepen;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")),OPT_BOOL (0 ,"single-branch" , &option_single_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,N_ ("any cloned submodules will be shallow" )), 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 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 );return local_refs;
@@ -652,7 +655,7 @@ static void update_remote_refs(const struct ref *refs,if (refs) {write_remote_refs (mapped_refs); -if (option_single_branch) +if (option_single_branch && !option_no_tags)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);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)setup_reference ();
t/t5612-clone-refspec.sh +71 -2
110 lines not on this page · raw message
Signature · 1 line
2.11.0
Re: [PATCH v2] clone: add a --no-tags option to clone without tags
Hi,
Quoted 5 lines · Ævar Arnfjörð Bjarmason
Add a --no-tags option to "git clone" to clone without tags. Currently there's no easy way to clone a repository and end up with just a "master" branch via --single-branch, or track all branches and no tags. Now --no-tags can be added to "git clone" with or without --single-branch to clone a repository without tags.
Now I've read the discussion from v1, so you can see my thoughts evolving in real time. :)
The above feels a bit misleading when it says "there's no easy way to clone a repository and end up with just a 'master' branch". --single-branch does exactly that. Some annotated tags *pointing to its history* come along for the ride, but what harm are they doing?
In other words, I think the commit message needs a bit more detail about the use case, to say why omitting those tags is useful. The use case is probably sane but it is not explained. A side effect (and my main motivation) is that this would make it crystal clear to people looking at the patch in history that it is talking about tags that are part of "master"'s history, not tags pointing elsewhere.
Quoted 2 lines
Before this the only way of doing this was either by manually tweaking the config in a fresh repository:
Usually commit messages refer to the state of things without some patch using the present tense --- e.g. "Without this patch, this --no-tags option can be emulated by (1) manually tweaking the config in a fresh repository, or (2) by setting tagOpt=--no-tags after cloning and deleting any existing tags".
[...]
Quoted 7 lines
Which of course was also subtly buggy if --branch was pointed at a tag, leaving the user in a detached head:
git clone --single-branch --branch v2.12.0 [email protected]:git/git.git && cd git && git config remote.origin.tagOpt --no-tags && git tag -l | xargs git tag -d
At this point I lose the trail of thought. I don't think it's important to understanding the patch.
Quoted 7 lines
Now all this complexity becomes the much simpler:
git clone --single-branch --no-tags [email protected]:git/git.gitOr in the case of cloning a single tag "branch":
git clone --single-branch --branch v2.12.0 --no-tags [email protected]:git/git.git
Nice.
[...]
Quoted 10 lines
Documentation/git-clone.txt | 14 ++++++++- builtin/clone.c | 13 ++++++-- t/t5612-clone-refspec.sh | 73 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 95 insertions(+), 5 deletions(-)Documentation/git-clone.txt +0
-0
Documentation/git-clone.txt SYNOPSIS · line 16
Quoted 5 lines
Documentation/git-clone.txt +1
-1@@ -13,7 +13,7 @@ SYNOPSIS [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror] [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>] [--dissociate] [--separate-git-dir <git dir>] - [--depth <depth>] [--[no-]single-branch] + [--depth <depth>] [--[no-]single-branch] [--no-tags]
Can I pass --tags to negate a previous --no-tags?
[...]
Documentation/git-clone.txt objects from the source repository into a pack in the cloned repository. · line 225
Quoted 8 lines
Documentation/git-clone.txt +8
-0+--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 & maintain
nit: s/&/and/
[...]
Documentation/git-clone.txt
Quoted 4 lines
Documentation/git-clone.txt +4
-0+test_expect_success 'clone with --no-tags' ' + ( + cd dir_all_no_tags && git fetch && + git for-each-ref refs/tags >../actual
nit: this would be easier to read with the 'cd' and 'git fetch' on separate lines.
[...]
Documentation/git-clone.txt
Quoted 3 lines
Documentation/git-clone.txt +3
-0+test_expect_success '--single-branch while HEAD pointing at master and --no-tags' ' + ( + cd dir_master_no_tags && git fetch &&
Likewise.
Documentation/git-clone.txt
Quoted 3 lines
Documentation/git-clone.txt +3
-0+ git for-each-ref refs/remotes/origin | + sed -e "/HEAD$/d" \ + -e "s|/remotes/origin/|/heads/|" >../actual
Can $/ be expanded by the shell?
The rest looks sensible.
Thanks and hope that helps,
Jonathan
Re: [PATCH v2] clone: add a --no-tags option to clone without tags
Quoted 6 lines · Jonathan Nieder
In other words, I think the commit message needs a bit more detail about the use case, to say why omitting those tags is useful. The use case is probably sane but it is not explained. A side effect (and my main motivation) is that this would make it crystal clear to people looking at the patch in history that it is talking about tags that are part of "master"'s history, not tags pointing elsewhere.
I agree that it is unclear "having no tags, not even the harmless and usually useful ones that point at the history of the branch of interest" is the point of this new feature from the documentation and log message.
Responding to your other message, I do not think this new feature should be tied to --single-branch; I think having the tags to mark commits in the branch's history (while not fetching other tags irrelevant to the branch's history) is usually what users would want.
Quoted 8 lines
Quoted 2 lines
Before this the only way of doing this was either by manually tweaking the config in a fresh repository:
Usually commit messages refer to the state of things without some patch using the present tense --- e.g. "Without this patch, this --no-tags option can be emulated by (1) manually tweaking the config in a fresh repository, or (2) by setting tagOpt=--no-tags after cloning and deleting any existing tags".
Thanks--I'll use this myself when responding to patches from other people. I recall getting irritated while reading some patches and couldn't pinpoint why they were irritating, and now I realize that it was because they said "Previously Git did X." and somesuch.
Re: [PATCH v2] clone: add a --no-tags option to clone without tags
In reply to Jonathan NiederQuoted 10 lines · Jonathan Nieder
Hi,
Quoted 5 lines · Ęvar Arnfjörš Bjarmason
Add a --no-tags option to "git clone" to clone without tags. Currently there's no easy way to clone a repository and end up with just a "master" branch via --single-branch, or track all branches and no tags. Now --no-tags can be added to "git clone" with or without --single-branch to clone a repository without tags.
Quoted 6 lines
Now I've read the discussion from v1, so you can see my thoughts evolving in real time. :)
The above feels a bit misleading when it says "there's no easy way to clone a repository and end up with just a 'master' branch". --single-branch does exactly that.
I'll reword this, what I meant is "just a master branch [and no other references]". Not "just the master branch [and no other branches]".
Quoted 2 lines
Some annotated tags *pointing to
its history* come along for the ride, but what harm are they doing?
I'll explain this in a bit more detail in the commit message & docs, both you & Junio (in <[email protected]>) seem to be making the assumption that only getting & maintaining the tags for the branch you're cloning is cheap.
This assumes a repo that while large, doesn't get a lot of releases on its main branch. E.g. linux.git has ~650k commits, and ~500 v* tags, that's a tag every 1300 commits or so.
Now if you run this on linux.git:
$ git rev-list origin/master | parallel -j6 --progress 'test
"$(echo {} | cut -b1)" = 0 && git tag -a -m"msg" test-tag-{}'You'll get a tag a bit more than every 16 commits, and now a lot of everyday commands become slow, because a lot of them need to look at every ref before they start:
$ (time (git log -1 >/dev/null)) 2>&1|grep ^real
real 0m1.304sWhereas on a linux.git without all those tags:
$ (time (git log -1 >/dev/null)) 2>&1|grep ^real
real 0m0.027sAnd you can imagine what this does to some other commands, e.g. bash completion:
$ git log <TAB>
Display all 512 possibilities? (y or n)v.s.:
$ git log <TAB>
Display all 42129 possibilities? (y or n)Furthermore, if upstream has a high tag churn, i.e. creates lots of tags but prunes them regularly even if you set tagOpts=--prune you'll still end up with an every slower local repository as you slowly accumulate every tag upstream has created every, you'd need to fetch with:
$ git fetch origin --prune 'refs/tags/*:refs/tags/*'
Simply never fetching the tags in the first place & making sure they aren't fetched avoids all of this, and is perfect e.g. for the use case of something that runs an automated "pull" on the repo to index its code (I initially wrote this for a https://github.com/etsy/hound/
setup), or if you'd just like to run the likes of "git log" on the master branch without starting that up taking a second longer.
Quoted 6 lines
In other words, I think the commit message needs a bit more detail about the use case, to say why omitting those tags is useful. The use case is probably sane but it is not explained. A side effect (and my main motivation) is that this would make it crystal clear to people looking at the patch in history that it is talking about tags that are part of "master"'s history, not tags pointing elsewhere.
I'll add that.
Quoted 13 lines
Quoted 2 lines
Before this the only way of doing this was either by manually tweaking the config in a fresh repository:
Usually commit messages refer to the state of things without some patch using the present tense --- e.g. "Without this patch, this --no-tags option can be emulated by (1) manually tweaking the config in a fresh repository, or (2) by setting tagOpt=--no-tags after cloning and deleting any existing tags".
[...]
Quoted 3 lines
Which of course was also subtly buggy if --branch was pointed at a tag, leaving the user in a detached head:
Quoted 7 lines
Quoted 4 lines
git clone --single-branch --branch v2.12.0 [email protected]:git/git.git && cd git && git config remote.origin.tagOpt --no-tags && git tag -l | xargs git tag -dAt this point I lose the trail of thought. I don't think it's important to understanding the patch.
I'm going to leave that in because anyone who needs this feature for a similar use-case (which I'll explain in more detail), would need to do exactly that to get a bug-compatible version of the same behavior if they need to run on an older git version for whatever reason.
Quoted 16 lines
Quoted 7 lines
Now all this complexity becomes the much simpler:
git clone --single-branch --no-tags [email protected]:git/git.gitOr in the case of cloning a single tag "branch":
git clone --single-branch --branch v2.12.0 --no-tags [email protected]:git/git.gitNice.
[...]
Quoted 5 lines
Documentation/git-clone.txt | 14 ++++++++- builtin/clone.c | 13 ++++++-- t/t5612-clone-refspec.sh | 73 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 95 insertions(+), 5 deletions(-)
Quoted 12 lines
Documentation/git-clone.txt SYNOPSIS · line 16
Quoted 10 lines
Documentation/git-clone.txt +1
-1@@ -13,7 +13,7 @@ SYNOPSIS [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror] [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>] [--dissociate] [--separate-git-dir <git dir>] - [--depth <depth>] [--[no-]single-branch] + [--depth <depth>] [--[no-]single-branch] [--no-tags]Can I pass --tags to negate a previous --no-tags?
Yeah both --tags and --no-no-tags work as with every other OPT_BOOL option. See "[RFC PATCH] parse-options: disallow double-negations of options starting with no-".
Quoted 11 lines
[...]
Documentation/git-clone.txt objects from the source repository into a pack in the cloned repository. · line 225
Quoted 8 lines
+--no-tags::
Documentation/git-clone.txt +7
-0+ 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 & maintainnit: s/&/and/
Will fix.
Quoted 9 lines
[...]
Documentation/git-clone.txt
Quoted 4 lines
Documentation/git-clone.txt +4
-0+test_expect_success 'clone with --no-tags' ' + ( + cd dir_all_no_tags && git fetch && + git for-each-ref refs/tags >../actualnit: this would be easier to read with the 'cd' and 'git fetch' on separate lines.
Quoted 6 lines
[...]
Documentation/git-clone.txt
Quoted 3 lines
Documentation/git-clone.txt +3
-0+test_expect_success '--single-branch while HEAD pointing at master and --no-tags' ' + ( + cd dir_master_no_tags && git fetch &&Likewise.
This was following the existing style in the file, but sure, I'll prepend a patch to this series to fix all of that before building this patch on top.
Quoted 5 lines
Documentation/git-clone.txt
Quoted 3 lines
Documentation/git-clone.txt +3
-0+ git for-each-ref refs/remotes/origin | + sed -e "/HEAD$/d" \ + -e "s|/remotes/origin/|/heads/|" >../actualCan $/ be expanded by the shell?
I think not, and if there's some issue with it it's obscure enough to not have caused issues since 31b808a032 ("clone --single: limit the fetch refspec to fetched branch", 2012-09-20) which introduced this pattern earlier in the test file, I'm just copy/pasting similar setup from elsewhere in the file.
Re: [PATCH] clone: add a --no-tags option to clone without tags
In reply to Ævar Arnfjörð BjarmasonHi,
Quoted 5 lines · Ævar Arnfjörð Bjarmason
Add a --no-tags option to "git clone" to clone without tags. Currently there's no easy way to clone a repository and end up with just a "master" branch via --single-branch, or track all branches and no tags. Now --no-tags can be added to "git clone" with or without --single-branch to clone a repository without tags.
Could --single-branch be made to imply --no-tags, like --depth implies --single-branch? After all, all I wanted is that one branch, not some tags.
Callers who really want the tags could still pass --tags to request that.
Just thinking out loud,
Jonathan