From: Junio C Hamano <hidden> Date: 2016-06-15 22:54:45
Ralf Thielow [off-list ref] writes:
+ if (option_mirror || !option_bare) {
+ strbuf_reset(&value);
+ if (option_single_branch) {
+ if (option_branch)
+ strbuf_addf(&value, "+%s%s:%s%s",
+ src_ref_prefix, option_branch,
+ branch_top.buf, option_branch);
+ else if (remote_head_points_at)
+ strbuf_addf(&value, "+%s:%s%s",
+ remote_head_points_at->name, branch_top.buf,
+ skip_prefix(remote_head_points_at->name, "refs/heads/"));
We have already set "remote.origin.url" to this repository, so the
next "git fetch" would simply fetch from "HEAD" per default.
Perhaps worth commenting that here?
Other than that, looks good. Perhaps we would want a test or two,
too?
Thanks.
After running "git clone --single", the resulting repository has the
usual default "+refs/heads/*:refs/remotes/origin/*" wildcard fetch
refspec installed, which means that a subsequent "git fetch" will
end up grabbing all the other branches.
Update the fetch refspec to cover only the singly cloned ref instead
to correct this.
Signed-off-by: Ralf Thielow <redacted>
---
Changes to v3:
- use commit message from Junio's topic branch
- add comment for the 'detached HEAD' case (also from Junio's topic branch)
(thanks for that)
- add tests for the refspec installed by the clone command
builtin/clone.c | 49 ++++++++++++++++++++++++++++------------
t/t5709-clone-refspec.sh | 59 ++++++++++++++++++++++++++++++++++++++++++++++++
2 Dateien geändert, 94 Zeilen hinzugefügt(+), 14 Zeilen entfernt(-)
create mode 100755 t/t5709-clone-refspec.sh
@@ -0,0 +1,59 @@+#!/bin/sh++test_description='test refspec written by clone-command'+../test-lib.sh++test_expect_success'setup''+echoone>file&&+gitaddfile&&+gitcommit-mone&&+echotwo>file&&+gitcommit-a-mtwo&&+gittagtwo&&+echothree>file&&+gitcommit-a-mthree&&+gitcheckout-bfoo&&+echofour>file&&+gitcommit-a-mfour&&+gitcheckoutmaster+'++test_expect_success'refspec contains all branches by default''+gitclone"file://$PWD"dir_all&&+echo"+refs/heads/*:refs/remotes/origin/*">expected&&+git--git-dir=dir_all/.gitconfig--getremote.origin.fetch>actual&&+test_cmpexpectedactual+'++test_expect_success'refspec contains only master with option --single-branch and remotes HEAD point to master''+gitclone--single-branch"file://$PWD"dir_master&&+echo"+refs/heads/master:refs/remotes/origin/master">expected&&+git--git-dir=dir_master/.gitconfig--getremote.origin.fetch>actual&&+test_cmpexpectedactual+'++test_expect_success'refspec contains only foo with option --single-branch and remotes HEAD point to foo''+gitcheckoutfoo&&+gitclone--single-branch"file://$PWD"dir_foo&&+echo"+refs/heads/foo:refs/remotes/origin/foo">expected&&+git--git-dir=dir_foo/.gitconfig--getremote.origin.fetch>actual&&+test_cmpexpectedactual+'++test_expect_success'refspec contains one branch after using option --single-branch with --branch''+gitcheckoutmaster&&+gitclone--single-branch--branchfoo"file://$PWD"dir_foo2&&+echo"+refs/heads/foo:refs/remotes/origin/foo">expected&&+git--git-dir=dir_foo2/.gitconfig--getremote.origin.fetch>actual&&+test_cmpexpectedactual+'++test_expect_success'no refspec is written if remotes HEAD is detached''+gitcheckouttwo^&&+gitclone--single-branch"file://$PWD"dir_detached&&+rmexpected&&touchexpected&&+git--git-dir=dir_detached/.gitconfig--getremote.origin.fetch>actual+test_cmpexpectedactual+'++test_done
On Sun, Sep 16, 2012 at 3:13 PM, Ralf Thielow [off-list ref] wrote:
+ if (option_mirror || !option_bare) {
+ strbuf_reset(&value);
I think we should use a new strbuf local variable here to avoid
resetting this. At least reviewers don't have to check if this
statememt causes any effect later on because "value"'s value is gone.
+ if (option_single_branch) {
+ if (option_branch)
+ strbuf_addf(&value, "+%s%s:%s%s",
+ src_ref_prefix, option_branch,
+ branch_top.buf, option_branch);
+ else if (remote_head_points_at)
+ strbuf_addf(&value, "+%s:%s%s",
+ remote_head_points_at->name, branch_top.buf,
+ skip_prefix(remote_head_points_at->name, "refs/heads/"));
+ /*
+ * otherwise, the next "git fetch" will
+ * simply fetch from HEAD without updating
+ * any remote tracking branch, which is what
+ * we want.
+ */
Maybe document updates too? Though if it's obvious that
--single-branch should prepare refspec so that only one branch is
fetched later on, then maybe not.
On Mon, Sep 17, 2012 at 7:06 PM, Nguyen Thai Ngoc Duy [off-list ref] wrote:
--mirror --single-branch combination does not look right. The "heads/"
part is missing..
It also does not look right for cloning a tag:
$ LANG=C ./git clone --single-branch --branch=v1.7.0 .git abc
Cloning into 'abc'...
done.
Note: checking out 'e923eaeb901ff056421b9007adcbbce271caa7b6'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b new_branch_name
$ grep fetch abc/.git/config
fetch = +refs/heads/v1.7.0:refs/remotes/origin/v1.7.0
--
Duy
On Mon, Sep 17, 2012 at 2:06 PM, Nguyen Thai Ngoc Duy [off-list ref] wrote:
On Sun, Sep 16, 2012 at 3:13 PM, Ralf Thielow [off-list ref] wrote:
quoted
+ if (option_mirror || !option_bare) {
+ strbuf_reset(&value);
I think we should use a new strbuf local variable here to avoid
resetting this. At least reviewers don't have to check if this
statememt causes any effect later on because "value"'s value is gone.
It seems that we don't need this reset here because it's already
done earlier in this function. The variable "key" is also used multiple
times so I wouldn't use a new variable.
quoted
+ if (option_single_branch) {
+ if (option_branch)
+ strbuf_addf(&value, "+%s%s:%s%s",
+ src_ref_prefix, option_branch,
+ branch_top.buf, option_branch);
+ else if (remote_head_points_at)
+ strbuf_addf(&value, "+%s:%s%s",
+ remote_head_points_at->name, branch_top.buf,
+ skip_prefix(remote_head_points_at->name, "refs/heads/"));
+ /*
+ * otherwise, the next "git fetch" will
+ * simply fetch from HEAD without updating
+ * any remote tracking branch, which is what
+ * we want.
+ */
Maybe document updates too? Though if it's obvious that
--single-branch should prepare refspec so that only one branch is
fetched later on, then maybe not.
After running "git clone --single", the resulting repository has the
usual default "+refs/heads/*:refs/remotes/origin/*" wildcard fetch
refspec installed, which means that a subsequent "git fetch" will
end up grabbing all the other branches.
Update the fetch refspec to cover only the singly cloned ref instead
to correct this.
Signed-off-by: Ralf Thielow <redacted>
---
changes in v5:
- extract a function to write refspec config
- handle --mirror option (test added)
- install correct refspec if the value of --branch is a tag (test added)
Thanks to Junio for:
- refactor tests
- add tests for created refs
I'm not happy about using "our_head_points_to" for the remote
part of the refspec. Junio already complaint about that. As far
as I can see it's the only way of getting the information that
it's a tag. Also the condition "is this a tag" might not be the
best way.
builtin/clone.c | 66 +++++++++++++++-----
t/t5709-clone-refspec.sh | 156 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 208 insertions(+), 14 deletions(-)
create mode 100755 t/t5709-clone-refspec.sh
@@ -0,0 +1,156 @@+#!/bin/sh++test_description='test refspec written by clone-command'+../test-lib.sh++test_expect_success'setup''+# Make two branches, "master" and "side"+echoone>file&&+gitaddfile&&+gitcommit-mone&&+echotwo>file&&+gitcommit-a-mtwo&&+gittagtwo&&+echothree>file&&+gitcommit-a-mthree&&+gitcheckout-bside&&+echofour>file&&+gitcommit-a-mfour&&+gitcheckoutmaster&&++# default clone+gitclone.dir_all&&++# default --single that follows HEAD=master+gitclone--single-branch.dir_master&&++# default --single that follows HEAD=side+gitcheckoutside&&+gitclone--single-branch.dir_side&&++# explicit --single that follows side+gitcheckoutmaster&&+gitclone--single-branch--branchside.dir_side2&&++# default --single with --mirror+gitclone--single-branch--mirror.dir_mirror&&++# --single that does not know what branch to follow+gitcheckouttwo^&&+gitclone--single-branch.dir_detached&&++# explicit --single with tag+gitclone--single-branch--branchtwo.dir_tag&&++# advance both "master" and "side" branches+gitcheckoutside&&+echofive>file&&+gitcommit-a-mfive&&+gitcheckoutmaster&&+echosix>file&&+gitcommit-a-msix+'++test_expect_success'refspec contains all branches by default''+echo"+refs/heads/*:refs/remotes/origin/*">expect&&+git--git-dir=dir_all/.gitconfig--getremote.origin.fetch>actual&&+test_cmpexpectactual+'++test_expect_success'refspec contains all refs with option --mirror''+echo"+refs/*:refs/*">expect&&+git--git-dir=dir_mirrorconfig--getremote.origin.fetch>actual&&+test_cmpexpectactual+'++test_expect_success'refspec contains tag ref''+echo"+refs/tags/two:refs/tags/two">expect&&+git--git-dir=dir_tag/.gitconfig--getremote.origin.fetch>actual&&+test_cmpexpectactual+'++test_expect_success'refspec contains only master with option --single-branch and remotes HEAD point to master''+echo"+refs/heads/master:refs/remotes/origin/master">expect&&+git--git-dir=dir_master/.gitconfig--getremote.origin.fetch>actual&&+test_cmpexpectactual+'++test_expect_success'refspec contains only foo with option --single-branch and remotes HEAD point to side''+echo"+refs/heads/side:refs/remotes/origin/side">expect&&+git--git-dir=dir_side/.gitconfig--getremote.origin.fetch>actual&&+test_cmpexpectactual+'++test_expect_success'refspec contains one branch after using option --single-branch with --branch''+echo"+refs/heads/side:refs/remotes/origin/side">expect&&+git--git-dir=dir_side2/.gitconfig--getremote.origin.fetch>actual&&+test_cmpexpectactual+'++test_expect_success'no refspec is written if remotes HEAD is detached''+>expect&&+git--git-dir=dir_detached/.gitconfig--getremote.origin.fetch>actual+test_cmpexpectactual+'++test_expect_success'by default all branches will be kept updated''+(+cddir_all&&gitfetch&&+gitfor-each-refrefs/remotes/origin|+sed-e"/HEAD$/d"\+-e"s|/remotes/origin/|/heads/|">../actual+)&&+# follow both master and side+gitfor-each-refrefs/heads>expect&&+test_cmpexpectactual+'++test_expect_success'--single-branch while HEAD pointing at master''+(+cddir_master&&gitfetch&&+gitfor-each-refrefs/remotes/origin|+sed-e"/HEAD$/d"\+-e"s|/remotes/origin/|/heads/|">../actual+)&&+# only follow master+gitfor-each-refrefs/heads/master>expect&&+test_cmpexpectactual+'++test_expect_success'--single-branch while HEAD pointing at side''+(+cddir_side&&gitfetch&&+gitfor-each-refrefs/remotes/origin|+sed-e"/HEAD$/d"\+-e"s|/remotes/origin/|/heads/|">../actual+)&&+# only follow side+gitfor-each-refrefs/heads/side>expect&&+test_cmpexpectactual+'++test_expect_success'--single-branch with explicit --branch side''+(+cddir_side2&&gitfetch&&+gitfor-each-refrefs/remotes/origin|+sed-e"/HEAD$/d"\+-e"s|/remotes/origin/|/heads/|">../actual+)&&+# only follow side+gitfor-each-refrefs/heads/side>expect&&+test_cmpexpectactual+'++test_expect_success'--single-branch with detached''+(+cddir_detached&&gitfetch&&+gitfor-each-refrefs/remotes/origin|+sed-e"/HEAD$/d"\+-e"s|/remotes/origin/|/heads/|">../actual+)+# nothing+>expect&&+test_cmpexpectactual+'++test_done
After running "git clone --single", the resulting repository has the
usual default "+refs/heads/*:refs/remotes/origin/*" wildcard fetch
refspec installed, which means that a subsequent "git fetch" will
end up grabbing all the other branches.
Update the fetch refspec to cover only the singly cloned ref instead
to correct this.
That means:
If "--single" is used without "--branch" or "--mirror", the
fetch refspec covers the branch on which remote's HEAD points to.
If "--single" is used with "--branch", it'll cover only the branch
specified in the "--branch" option.
If "--single" is combined with "--mirror", then it'll cover all
refs of the cloned repository.
If "--single" is used with "--branch" that specifies a tag, then
it'll cover only the ref for this tag.
Signed-off-by: Ralf Thielow <redacted>
---
changes in v6
- remove initial created tests (they tested in a too deep level)
- add tests for "--mirror" option
- add tests for the case of cloning a tag
- update commit message
I've tried to update "Documentation/git-clone.txt", but I don't
know in which way this patch changes already described behaviour.
The resulting refspec seems only be covered in the last part of
the "--single-branch" section by describing "--no-single-branch",
but this hasn't changed. Or did I miss something?
builtin/clone.c | 66 ++++++++++++++++-----
t/t5709-clone-refspec.sh | 145 +++++++++++++++++++++++++++++++++++++++++++++++
2 Dateien geändert, 197 Zeilen hinzugefügt(+), 14 Zeilen entfernt(-)
create mode 100755 t/t5709-clone-refspec.sh
@@ -0,0 +1,145 @@+#!/bin/sh++test_description='test refspec written by clone-command'+../test-lib.sh++test_expect_success'setup''+# Make two branches, "master" and "side"+echoone>file&&+gitaddfile&&+gitcommit-mone&&+echotwo>file&&+gitcommit-a-mtwo&&+gittagtwo&&+echothree>file&&+gitcommit-a-mthree&&+gitcheckout-bside&&+echofour>file&&+gitcommit-a-mfour&&+gitcheckoutmaster&&++# default clone+gitclone.dir_all&&++# default --single that follows HEAD=master+gitclone--single-branch.dir_master&&++# default --single that follows HEAD=side+gitcheckoutside&&+gitclone--single-branch.dir_side&&++# explicit --single that follows side+gitcheckoutmaster&&+gitclone--single-branch--branchside.dir_side2&&++# default --single with --mirror+gitclone--single-branch--mirror.dir_mirror&&++# default --single with --branch and --mirror+gitclone--single-branch--mirror--branchside.dir_mirror_side&&++# --single that does not know what branch to follow+gitcheckouttwo^&&+gitclone--single-branch.dir_detached&&++# explicit --single with tag+gitclone--single-branch--branchtwo.dir_tag&&++# advance both "master" and "side" branches+gitcheckoutside&&+echofive>file&&+gitcommit-a-mfive&&+gitcheckoutmaster&&+echosix>file&&+gitcommit-a-msix+'++test_expect_success'by default all branches will be kept updated''+(+cddir_all&&gitfetch&&+gitfor-each-refrefs/remotes/origin|+sed-e"/HEAD$/d"\+-e"s|/remotes/origin/|/heads/|">../actual+)&&+# follow both master and side+gitfor-each-refrefs/heads>expect&&+test_cmpexpectactual+'++test_expect_success'--single-branch while HEAD pointing at master''+(+cddir_master&&gitfetch&&+gitfor-each-refrefs/remotes/origin|+sed-e"/HEAD$/d"\+-e"s|/remotes/origin/|/heads/|">../actual+)&&+# only follow master+gitfor-each-refrefs/heads/master>expect&&+test_cmpexpectactual+'++test_expect_success'--single-branch while HEAD pointing at side''+(+cddir_side&&gitfetch&&+gitfor-each-refrefs/remotes/origin|+sed-e"/HEAD$/d"\+-e"s|/remotes/origin/|/heads/|">../actual+)&&+# only follow side+gitfor-each-refrefs/heads/side>expect&&+test_cmpexpectactual+'++test_expect_success'--single-branch with explicit --branch side''+(+cddir_side2&&gitfetch&&+gitfor-each-refrefs/remotes/origin|+sed-e"/HEAD$/d"\+-e"s|/remotes/origin/|/heads/|">../actual+)&&+# only follow side+gitfor-each-refrefs/heads/side>expect&&+test_cmpexpectactual+'+++test_expect_success'--single-branch with explicit --branch tag''+(+cddir_tag&&gitfetch&&+gitfor-each-refrefs/tags>../actual+)&&+gitfor-each-refrefs/tags>expect&&+test_cmpexpectactual+'++test_expect_success'--single-branch with --mirror''+(+cddir_mirror&&gitfetch&&+gitfor-each-refrefs>../actual+)&&+gitfor-each-refrefs>expect&&+test_cmpexpectactual+'++test_expect_success'--single-branch with explicit --branch and --mirror''+(+cddir_mirror_side&&gitfetch&&+gitfor-each-refrefs>../actual+)&&+gitfor-each-refrefs>expect&&+test_cmpexpectactual+'++test_expect_success'--single-branch with detached''+(+cddir_detached&&gitfetch&&+gitfor-each-refrefs/remotes/origin|+sed-e"/HEAD$/d"\+-e"s|/remotes/origin/|/heads/|">../actual+)+# nothing+>expect&&+test_cmpexpectactual+'++test_done
We should have added the tag right after cloning, not until the first
git-fetch. Not that I object how you do it in this patch. Just a note
to myself that if I'm going to do that, I'll need to update this test
to update the change tag before fetching and verify the tag is updated
after git-fetch.
--
Duy
We should have added the tag right after cloning, not until the first
git-fetch. Not that I object how you do it in this patch. Just a note
to myself that if I'm going to do that, I'll need to update this test
to update the change tag before fetching and verify the tag is updated
after git-fetch.
--
Duy
Right. I'll create two tests to replace this one. The first test
verifys that the tag
has been added after cloning. And in the second test, the tag gets updated in
the cloned repository and we verify that the next fetch updates the tag, which
catches my "delivery" tag example.