* [PATCH 01/15] t5510: use the correct tag name in test
2013-10-23 15:50 ` [PATCH 00/15] Change semantics of "fetch --tags" Michael Haggerty
@ 2013-10-23 15:50 ` Michael Haggerty
2013-10-23 15:50 ` [PATCH 02/15] t5510: prepare test refs more straightforwardly Michael Haggerty
` (14 subsequent siblings)
15 siblings, 0 replies; 57+ messages in thread
From: Michael Haggerty @ 2013-10-23 15:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister,
Michael Haggerty
Fix an apparent copy-paste error: A few lines earlier, a tag
"refs/tags/sometag" is created. Check for the (non-)existence of that
tag, not "somebranch", which is otherwise never mentioned in the
script.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
t/t5510-fetch.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 1f0f8e6..c5e5dfc 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -121,7 +121,7 @@ test_expect_success 'fetch --prune --tags does not delete the remote-tracking br
git fetch --prune --tags origin &&
git rev-parse origin/master &&
- test_must_fail git rev-parse somebranch
+ test_must_fail git rev-parse sometag
'
test_expect_success 'fetch --prune --tags with branch does not delete other remote-tracking branches' '
--
1.8.4
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 02/15] t5510: prepare test refs more straightforwardly
2013-10-23 15:50 ` [PATCH 00/15] Change semantics of "fetch --tags" Michael Haggerty
2013-10-23 15:50 ` [PATCH 01/15] t5510: use the correct tag name in test Michael Haggerty
@ 2013-10-23 15:50 ` Michael Haggerty
2013-10-23 18:36 ` Junio C Hamano
2013-10-23 15:50 ` [PATCH 03/15] t5510: check that "git fetch --prune --tags" does not prune branches Michael Haggerty
` (13 subsequent siblings)
15 siblings, 1 reply; 57+ messages in thread
From: Michael Haggerty @ 2013-10-23 15:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister,
Michael Haggerty
"git fetch" was being used with contrived refspecs to create tags and
remote-tracking branches in test repositories in preparation for the
actual tests. This is obscure and also makes one wonder whether this
is indeed just preparation or whether some side-effect of "git fetch"
is being tested.
So use the more straightforward commands "git tag" / "git update-ref"
when preparing branches in test repositories.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
t/t5510-fetch.sh | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index c5e5dfc..08d8dbb 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -88,7 +88,7 @@ test_expect_success 'fetch --prune on its own works as expected' '
cd "$D" &&
git clone . prune &&
cd prune &&
- git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
+ git update-ref refs/remotes/origin/extrabranch master &&
git fetch --prune origin &&
test_must_fail git rev-parse origin/extrabranch
@@ -98,7 +98,7 @@ test_expect_success 'fetch --prune with a branch name keeps branches' '
cd "$D" &&
git clone . prune-branch &&
cd prune-branch &&
- git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
+ git update-ref refs/remotes/origin/extrabranch master &&
git fetch --prune origin master &&
git rev-parse origin/extrabranch
@@ -117,7 +117,7 @@ test_expect_success 'fetch --prune --tags does not delete the remote-tracking br
cd "$D" &&
git clone . prune-tags &&
cd prune-tags &&
- git fetch origin refs/heads/master:refs/tags/sometag &&
+ git tag sometag master &&
git fetch --prune --tags origin &&
git rev-parse origin/master &&
@@ -128,7 +128,7 @@ test_expect_success 'fetch --prune --tags with branch does not delete other remo
cd "$D" &&
git clone . prune-tags-branch &&
cd prune-tags-branch &&
- git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
+ git update-ref refs/remotes/origin/extrabranch master &&
git fetch --prune --tags origin master &&
git rev-parse origin/extrabranch
--
1.8.4
^ permalink raw reply related [flat|nested] 57+ messages in thread
* Re: [PATCH 02/15] t5510: prepare test refs more straightforwardly
2013-10-23 15:50 ` [PATCH 02/15] t5510: prepare test refs more straightforwardly Michael Haggerty
@ 2013-10-23 18:36 ` Junio C Hamano
2013-10-24 6:49 ` Michael Haggerty
0 siblings, 1 reply; 57+ messages in thread
From: Junio C Hamano @ 2013-10-23 18:36 UTC (permalink / raw)
To: Michael Haggerty
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister
Michael Haggerty <mhagger@alum.mit.edu> writes:
> "git fetch" was being used with contrived refspecs to create tags and
> remote-tracking branches in test repositories in preparation for the
> actual tests. This is obscure and also makes one wonder whether this
> is indeed just preparation or whether some side-effect of "git fetch"
> is being tested.
>
> So use the more straightforward commands "git tag" / "git update-ref"
> when preparing branches in test repositories.
>
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
> ---
> t/t5510-fetch.sh | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
> index c5e5dfc..08d8dbb 100755
> --- a/t/t5510-fetch.sh
> +++ b/t/t5510-fetch.sh
> @@ -88,7 +88,7 @@ test_expect_success 'fetch --prune on its own works as expected' '
> cd "$D" &&
> git clone . prune &&
> cd prune &&
> - git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
> + git update-ref refs/remotes/origin/extrabranch master &&
As long as you have checked that our local 'master' should be at the
same commit as the origin's 'master' at this point, I think this
change is OK.
I wouldn't call the use of "very explicit, without any room for
mistake" refspecs "contrived", though.
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 02/15] t5510: prepare test refs more straightforwardly
2013-10-23 18:36 ` Junio C Hamano
@ 2013-10-24 6:49 ` Michael Haggerty
2013-10-24 19:50 ` Junio C Hamano
0 siblings, 1 reply; 57+ messages in thread
From: Michael Haggerty @ 2013-10-24 6:49 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister
On 10/23/2013 08:36 PM, Junio C Hamano wrote:
> Michael Haggerty <mhagger@alum.mit.edu> writes:
>
>> "git fetch" was being used with contrived refspecs to create tags and
>> remote-tracking branches in test repositories in preparation for the
>> actual tests. This is obscure and also makes one wonder whether this
>> is indeed just preparation or whether some side-effect of "git fetch"
>> is being tested.
>>
>> So use the more straightforward commands "git tag" / "git update-ref"
>> when preparing branches in test repositories.
>>
>> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
>> ---
>> t/t5510-fetch.sh | 8 ++++----
>> 1 file changed, 4 insertions(+), 4 deletions(-)
>>
>> diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
>> index c5e5dfc..08d8dbb 100755
>> --- a/t/t5510-fetch.sh
>> +++ b/t/t5510-fetch.sh
>> @@ -88,7 +88,7 @@ test_expect_success 'fetch --prune on its own works as expected' '
>> cd "$D" &&
>> git clone . prune &&
>> cd prune &&
>> - git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
>> + git update-ref refs/remotes/origin/extrabranch master &&
>
> As long as you have checked that our local 'master' should be at the
> same commit as the origin's 'master' at this point, I think this
> change is OK.
It doesn't matter what the reference points at; the only point of these
tests is to check whether branches that look like stale remote-tracking
branches are pruned or not by the later command.
> I wouldn't call the use of "very explicit, without any room for
> mistake" refspecs "contrived", though.
According to Wiktionary, contrived means "unnatural, forced".
When the goal is just to create a local reference whose contents are
irrelevant, "fetch" is not the first command that comes to my mind. It
brings a lot of unnecessary machinery to bear on such a trivial task.
Plus it is not very common in daily life to invoke "fetch" with a
complicated, asymmetic refspec like this. Because of that it cost me a
little extra time to convince myself that the "fetch" command wasn't
trying to do something more. In that sense it seems "contrived" to me.
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 02/15] t5510: prepare test refs more straightforwardly
2013-10-24 6:49 ` Michael Haggerty
@ 2013-10-24 19:50 ` Junio C Hamano
0 siblings, 0 replies; 57+ messages in thread
From: Junio C Hamano @ 2013-10-24 19:50 UTC (permalink / raw)
To: Michael Haggerty
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister
Michael Haggerty <mhagger@alum.mit.edu> writes:
>> As long as you have checked that our local 'master' should be at the
>> same commit as the origin's 'master' at this point, I think this
>> change is OK.
>
> It doesn't matter what the reference points at; the only point of these
> tests is to check whether branches that look like stale remote-tracking
> branches are pruned or not by the later command.
OK, thanks.
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH 03/15] t5510: check that "git fetch --prune --tags" does not prune branches
2013-10-23 15:50 ` [PATCH 00/15] Change semantics of "fetch --tags" Michael Haggerty
2013-10-23 15:50 ` [PATCH 01/15] t5510: use the correct tag name in test Michael Haggerty
2013-10-23 15:50 ` [PATCH 02/15] t5510: prepare test refs more straightforwardly Michael Haggerty
@ 2013-10-23 15:50 ` Michael Haggerty
2013-10-23 15:50 ` [PATCH 04/15] api-remote.txt: correct section "struct refspect" Michael Haggerty
` (12 subsequent siblings)
15 siblings, 0 replies; 57+ messages in thread
From: Michael Haggerty @ 2013-10-23 15:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister,
Michael Haggerty
"git fetch --prune --tags" is currently interpreted as follows:
* "--tags" is equivalent to specifying a refspec
"refs/tags/*:refs/tags/*", and supersedes any default refspecs
configured via remote.$REMOTE.fetch.
* "--prune" only operates on the refspecs being fetched.
Therefore, "git fetch --prune --tags" prunes tags in refs/tags/* but
does not fetch or prune other references. The fact that this command
does not prune references outside of refs/tags/* was previously
untested. So add a test that verifies the status quo.
However, the status quo is surprising, so it will be changed later in
this patch series.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
t/t5510-fetch.sh | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 08d8dbb..8328be1 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -118,9 +118,13 @@ test_expect_success 'fetch --prune --tags does not delete the remote-tracking br
git clone . prune-tags &&
cd prune-tags &&
git tag sometag master &&
+ # Create what looks like a remote-tracking branch from an earlier
+ # fetch that has since been deleted from the remote:
+ git update-ref refs/remotes/origin/fake-remote master &&
git fetch --prune --tags origin &&
git rev-parse origin/master &&
+ git rev-parse origin/fake-remote &&
test_must_fail git rev-parse sometag
'
--
1.8.4
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 04/15] api-remote.txt: correct section "struct refspect"
2013-10-23 15:50 ` [PATCH 00/15] Change semantics of "fetch --tags" Michael Haggerty
` (2 preceding siblings ...)
2013-10-23 15:50 ` [PATCH 03/15] t5510: check that "git fetch --prune --tags" does not prune branches Michael Haggerty
@ 2013-10-23 15:50 ` Michael Haggerty
2013-10-23 18:43 ` Junio C Hamano
2013-10-23 15:50 ` [PATCH 05/15] get_ref_map(): rename local variables Michael Haggerty
` (11 subsequent siblings)
15 siblings, 1 reply; 57+ messages in thread
From: Michael Haggerty @ 2013-10-23 15:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister,
Michael Haggerty
* Replace reference to function parse_ref_spec() with references to
functions parse_fetch_refspec() and parse_push_refspec().
* Correct description of src and dst: they *do* include the '*'
characters.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
Documentation/technical/api-remote.txt | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/Documentation/technical/api-remote.txt b/Documentation/technical/api-remote.txt
index 4be8776..5d245aa 100644
--- a/Documentation/technical/api-remote.txt
+++ b/Documentation/technical/api-remote.txt
@@ -58,16 +58,16 @@ default remote, given the current branch and configuration.
struct refspec
--------------
-A struct refspec holds the parsed interpretation of a refspec. If it
-will force updates (starts with a '+'), force is true. If it is a
-pattern (sides end with '*') pattern is true. src and dest are the two
-sides (if a pattern, only the part outside of the wildcards); if there
-is only one side, it is src, and dst is NULL; if sides exist but are
-empty (i.e., the refspec either starts or ends with ':'), the
-corresponding side is "".
-
-This parsing can be done to an array of strings to give an array of
-struct refpsecs with parse_ref_spec().
+A struct refspec holds the parsed interpretation of a refspec. If it
+will force updates (starts with a '+'), force is true. If it is a
+pattern (sides end with '*') pattern is true. src and dest are the
+two sides (including '*' characters if present); if there is only one
+side, it is src, and dst is NULL; if sides exist but are empty (i.e.,
+the refspec either starts or ends with ':'), the corresponding side is
+"".
+
+An array of strings can be parsed into an array of struct refspecs
+using parse_fetch_refspec() or parse_push_refspec().
remote_find_tracking(), given a remote and a struct refspec with
either src or dst filled out, will fill out the other such that the
--
1.8.4
^ permalink raw reply related [flat|nested] 57+ messages in thread
* Re: [PATCH 04/15] api-remote.txt: correct section "struct refspect"
2013-10-23 15:50 ` [PATCH 04/15] api-remote.txt: correct section "struct refspect" Michael Haggerty
@ 2013-10-23 18:43 ` Junio C Hamano
2013-10-24 7:06 ` Michael Haggerty
0 siblings, 1 reply; 57+ messages in thread
From: Junio C Hamano @ 2013-10-23 18:43 UTC (permalink / raw)
To: Michael Haggerty
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister
Michael Haggerty <mhagger@alum.mit.edu> writes:
>> Subject: Re: [PATCH 04/15] api-remote.txt: correct section "struct refspect"
refspect???
> * Replace reference to function parse_ref_spec() with references to
> functions parse_fetch_refspec() and parse_push_refspec().
>
> * Correct description of src and dst: they *do* include the '*'
> characters.
* Replace a single SP after a full-stop at the end of sentence with
double SP as if we were back in the typewriter age.
The last one made it hard to spot what actually got changed,
though. The updated text otherwise looks correct.
Thanks.
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
> ---
> Documentation/technical/api-remote.txt | 20 ++++++++++----------
> 1 file changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/Documentation/technical/api-remote.txt b/Documentation/technical/api-remote.txt
> index 4be8776..5d245aa 100644
> --- a/Documentation/technical/api-remote.txt
> +++ b/Documentation/technical/api-remote.txt
> @@ -58,16 +58,16 @@ default remote, given the current branch and configuration.
> struct refspec
> --------------
>
> -A struct refspec holds the parsed interpretation of a refspec. If it
> -will force updates (starts with a '+'), force is true. If it is a
> -pattern (sides end with '*') pattern is true. src and dest are the two
> -sides (if a pattern, only the part outside of the wildcards); if there
> -is only one side, it is src, and dst is NULL; if sides exist but are
> -empty (i.e., the refspec either starts or ends with ':'), the
> -corresponding side is "".
> -
> -This parsing can be done to an array of strings to give an array of
> -struct refpsecs with parse_ref_spec().
> +A struct refspec holds the parsed interpretation of a refspec. If it
> +will force updates (starts with a '+'), force is true. If it is a
> +pattern (sides end with '*') pattern is true. src and dest are the
> +two sides (including '*' characters if present); if there is only one
> +side, it is src, and dst is NULL; if sides exist but are empty (i.e.,
> +the refspec either starts or ends with ':'), the corresponding side is
> +"".
> +
> +An array of strings can be parsed into an array of struct refspecs
> +using parse_fetch_refspec() or parse_push_refspec().
>
> remote_find_tracking(), given a remote and a struct refspec with
> either src or dst filled out, will fill out the other such that the
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 04/15] api-remote.txt: correct section "struct refspect"
2013-10-23 18:43 ` Junio C Hamano
@ 2013-10-24 7:06 ` Michael Haggerty
0 siblings, 0 replies; 57+ messages in thread
From: Michael Haggerty @ 2013-10-24 7:06 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister
On 10/23/2013 08:43 PM, Junio C Hamano wrote:
> Michael Haggerty <mhagger@alum.mit.edu> writes:
>
>>> Subject: Re: [PATCH 04/15] api-remote.txt: correct section "struct refspect"
>
> refspect???
Thanks for catching the typo.
>> * Replace reference to function parse_ref_spec() with references to
>> functions parse_fetch_refspec() and parse_push_refspec().
>>
>> * Correct description of src and dst: they *do* include the '*'
>> characters.
>
> * Replace a single SP after a full-stop at the end of sentence with
> double SP as if we were back in the typewriter age.
:-)
I agree it's archaic, but it is standard practice in English.
Also, emacs, with the default sentence-end-double-space setting, doesn't
treat punctuation followed by a single space as an end of sentence and
when reflowing text even goes to extra effort not to break a line at
such a position (because that would make it look like it *were* the end
of the sentence).
TeX also distinguishes between interword spaces and end-of-sentence
spaces, but it uses a different heuristic (which can be overridden by
explicit markup). It also typesets them differently: end-of-sentence
spaces are a bit wider and more elastic.
Nevertheless it is probably good that there is no Unicode
END_OF_SENTENCE_SPACE character; otherwise we would never get *any* work
done for all the arguing about how to encode empty pixels :-)
> The last one made it hard to spot what actually got changed,
> though. The updated text otherwise looks correct.
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH 05/15] get_ref_map(): rename local variables
2013-10-23 15:50 ` [PATCH 00/15] Change semantics of "fetch --tags" Michael Haggerty
` (3 preceding siblings ...)
2013-10-23 15:50 ` [PATCH 04/15] api-remote.txt: correct section "struct refspect" Michael Haggerty
@ 2013-10-23 15:50 ` Michael Haggerty
2013-10-23 18:45 ` Junio C Hamano
2013-10-23 15:50 ` [PATCH 06/15] ref_remove_duplicates(): avoid redundant bisection Michael Haggerty
` (10 subsequent siblings)
15 siblings, 1 reply; 57+ messages in thread
From: Michael Haggerty @ 2013-10-23 15:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister,
Michael Haggerty
Rename "refs" -> "refspecs" and "ref_count" -> "refspec_count" to
reduce confusion, because they describe an array of "struct refspec",
as opposed to the "struct ref" objects that are also used in this
function.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
builtin/fetch.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/builtin/fetch.c b/builtin/fetch.c
index bd7a101..2248abf 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -165,8 +165,8 @@ static void find_non_local_tags(struct transport *transport,
struct ref ***tail);
static struct ref *get_ref_map(struct transport *transport,
- struct refspec *refs, int ref_count, int tags,
- int *autotags)
+ struct refspec *refspecs, int refspec_count,
+ int tags, int *autotags)
{
int i;
struct ref *rm;
@@ -175,12 +175,12 @@ static struct ref *get_ref_map(struct transport *transport,
const struct ref *remote_refs = transport_get_remote_refs(transport);
- if (ref_count || tags == TAGS_SET) {
+ if (refspec_count || tags == TAGS_SET) {
struct ref **old_tail;
- for (i = 0; i < ref_count; i++) {
- get_fetch_map(remote_refs, &refs[i], &tail, 0);
- if (refs[i].dst && refs[i].dst[0])
+ for (i = 0; i < refspec_count; i++) {
+ get_fetch_map(remote_refs, &refspecs[i], &tail, 0);
+ if (refspecs[i].dst && refspecs[i].dst[0])
*autotags = 1;
}
/* Merge everything on the command line, but not --tags */
--
1.8.4
^ permalink raw reply related [flat|nested] 57+ messages in thread
* Re: [PATCH 05/15] get_ref_map(): rename local variables
2013-10-23 15:50 ` [PATCH 05/15] get_ref_map(): rename local variables Michael Haggerty
@ 2013-10-23 18:45 ` Junio C Hamano
2013-10-24 7:24 ` Michael Haggerty
0 siblings, 1 reply; 57+ messages in thread
From: Junio C Hamano @ 2013-10-23 18:45 UTC (permalink / raw)
To: Michael Haggerty
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister
Michael Haggerty <mhagger@alum.mit.edu> writes:
> Rename "refs" -> "refspecs" and "ref_count" -> "refspec_count" to
> reduce confusion, because they describe an array of "struct refspec",
> as opposed to the "struct ref" objects that are also used in this
> function.
Good. In general, we'd prefer to name an array of things that are
primarily walked in the index order "thing[]", so that "thing number
3" can be spelled thing[3] (not things[3]) in the code, though.
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
> ---
> builtin/fetch.c | 12 ++++++------
> 1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/builtin/fetch.c b/builtin/fetch.c
> index bd7a101..2248abf 100644
> --- a/builtin/fetch.c
> +++ b/builtin/fetch.c
> @@ -165,8 +165,8 @@ static void find_non_local_tags(struct transport *transport,
> struct ref ***tail);
>
> static struct ref *get_ref_map(struct transport *transport,
> - struct refspec *refs, int ref_count, int tags,
> - int *autotags)
> + struct refspec *refspecs, int refspec_count,
> + int tags, int *autotags)
> {
> int i;
> struct ref *rm;
> @@ -175,12 +175,12 @@ static struct ref *get_ref_map(struct transport *transport,
>
> const struct ref *remote_refs = transport_get_remote_refs(transport);
>
> - if (ref_count || tags == TAGS_SET) {
> + if (refspec_count || tags == TAGS_SET) {
> struct ref **old_tail;
>
> - for (i = 0; i < ref_count; i++) {
> - get_fetch_map(remote_refs, &refs[i], &tail, 0);
> - if (refs[i].dst && refs[i].dst[0])
> + for (i = 0; i < refspec_count; i++) {
> + get_fetch_map(remote_refs, &refspecs[i], &tail, 0);
> + if (refspecs[i].dst && refspecs[i].dst[0])
> *autotags = 1;
> }
> /* Merge everything on the command line, but not --tags */
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 05/15] get_ref_map(): rename local variables
2013-10-23 18:45 ` Junio C Hamano
@ 2013-10-24 7:24 ` Michael Haggerty
0 siblings, 0 replies; 57+ messages in thread
From: Michael Haggerty @ 2013-10-24 7:24 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister
On 10/23/2013 08:45 PM, Junio C Hamano wrote:
> Michael Haggerty <mhagger@alum.mit.edu> writes:
>
>> Rename "refs" -> "refspecs" and "ref_count" -> "refspec_count" to
>> reduce confusion, because they describe an array of "struct refspec",
>> as opposed to the "struct ref" objects that are also used in this
>> function.
>
> Good. In general, we'd prefer to name an array of things that are
> primarily walked in the index order "thing[]", so that "thing number
> 3" can be spelled thing[3] (not things[3]) in the code, though.
Since I didn't change singular -> plural or vice versa in this patch,
it's a bit off topic, but in case you are curious I prefer plural to
distinguish which pointers point at lists or arrays as opposed to single
objects. This convention conveniently leaves the singular available to
name a variable that is used for a single object; for example, in a loop
struct thing thing = things[i];
(The convention in SQL is different: tables are usually named using
singular nouns. But that makes sense in SQL because there is not really
a way to reference a single row in a table as an aggregate, so there is
no need to reserve the singular noun for that purpose. In fact, in
SELECT statements the table name often appears in a context that makes
it look like it does refer to a single row:
SELECT employee.name, employee.salary FROM ...
So I think it makes sense to use different conventions in C vs. SQL.)
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH 06/15] ref_remove_duplicates(): avoid redundant bisection
2013-10-23 15:50 ` [PATCH 00/15] Change semantics of "fetch --tags" Michael Haggerty
` (4 preceding siblings ...)
2013-10-23 15:50 ` [PATCH 05/15] get_ref_map(): rename local variables Michael Haggerty
@ 2013-10-23 15:50 ` Michael Haggerty
2013-10-23 15:50 ` [PATCH 07/15] ref_remove_duplicates(): simplify function Michael Haggerty
` (9 subsequent siblings)
15 siblings, 0 replies; 57+ messages in thread
From: Michael Haggerty @ 2013-10-23 15:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister,
Michael Haggerty
The old code called string_list_lookup(), and if that failed called
string_list_insert(), thus doing the bisection search through the
string list twice in the latter code path.
Instead, just call string_list_insert() right away. If an entry for
that peer reference name already existed, then its util pointer is
always non-NULL.
Of course this doesn't change the fact that the repeated
string_list_insert() calls make the function scale like O(N^2) if the
input reference list is not already approximately sorted.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
The O(N^2) algorithm mentioned above essentially boils down to
for each reference:
insert reference into string_list (sorted)
Because the insertion requires later array entries to be shifted to
the right, the algorithm scales like O(N^2) if the entries are not
already approximately in order.
I can think of three easy ways to fix this:
* Use a hash map instead of a sorted string_list to record which
entries have already been seen.
* If the order of the result doesn't matter and it doesn't matter
*which* of the duplicates is retained, then insert all of the names
into the string_list unsorted, then sort them all in one go, then
iterate through looking for duplicates and stringing the survivors
together in a new linked list.
* If the order is important, or it is important that the *first* of
duplicates be retained, then iterate through the linked list twice.
The first time, just add the entries to the string_list. Then sort
the string_list using a stable sort (e.g., git_qsort()). Then
iterate through the linked list a second time as in the current
code.
See also my comments to commit 10.
However, I believe that the O(N^2) worst case is unlikely to bite in
most cases. This function is called from
builtin/fetch.c:get_ref_map(), and the input list is the concatenation
of several sub-lists. Most sublists come from resolving refspecs, and
the last comes from find_non_local_tags(). I believe that each of the
sublists is sorted. So the O(N^2) worst-case could only occur if more
than one of the sublists is large and at least two of the large
sublists are not in the correct order relative to each other.
I tried to concoct such a test case by creating a repository with
about 20k branches and 20k tags, instrumenting
ref_remove_duplicates(), and then fetching with something like
git fetch --prune origin refs/heads/*:refs/remotes/origin/* \
refs/tags/*:refs/tags/*
Indeed, the running time of ref_remove_duplicates() became significant
when the order of the refspecs was reversed, but it was still less
than a second out of a much longer command invocation.
So I didn't bother fixing the O(N^2) algorithm. If somebody reports
real-world slowness here, we can always come back to it.
remote.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/remote.c b/remote.c
index e9fedfa..a44e897 100644
--- a/remote.c
+++ b/remote.c
@@ -750,13 +750,15 @@ void ref_remove_duplicates(struct ref *ref_map)
struct string_list refs = STRING_LIST_INIT_NODUP;
struct string_list_item *item = NULL;
struct ref *prev = NULL, *next = NULL;
+
for (; ref_map; prev = ref_map, ref_map = next) {
next = ref_map->next;
if (!ref_map->peer_ref)
continue;
- item = string_list_lookup(&refs, ref_map->peer_ref->name);
- if (item) {
+ item = string_list_insert(&refs, ref_map->peer_ref->name);
+ if (item->util) {
+ /* Entry already existed */
if (strcmp(((struct ref *)item->util)->name,
ref_map->name))
die("%s tracks both %s and %s",
@@ -767,11 +769,9 @@ void ref_remove_duplicates(struct ref *ref_map)
free(ref_map->peer_ref);
free(ref_map);
ref_map = prev; /* skip this; we freed it */
- continue;
+ } else {
+ item->util = ref_map;
}
-
- item = string_list_insert(&refs, ref_map->peer_ref->name);
- item->util = ref_map;
}
string_list_clear(&refs, 0);
}
--
1.8.4
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 07/15] ref_remove_duplicates(): simplify function
2013-10-23 15:50 ` [PATCH 00/15] Change semantics of "fetch --tags" Michael Haggerty
` (5 preceding siblings ...)
2013-10-23 15:50 ` [PATCH 06/15] ref_remove_duplicates(): avoid redundant bisection Michael Haggerty
@ 2013-10-23 15:50 ` Michael Haggerty
2013-10-23 15:50 ` [PATCH 08/15] ref_remove_duplicates(): improve documentation comment Michael Haggerty
` (8 subsequent siblings)
15 siblings, 0 replies; 57+ messages in thread
From: Michael Haggerty @ 2013-10-23 15:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister,
Michael Haggerty
* Use a dedicated variable, ref, for referring to the current item
rather than using the ref_map pointer for this purpose.
* Use a (struct ref **) as iteration variable to avoid having to keep
track of prev and next in addition to the pointer to the current
item.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
remote.c | 32 ++++++++++++++++++--------------
1 file changed, 18 insertions(+), 14 deletions(-)
diff --git a/remote.c b/remote.c
index a44e897..5ade07f 100644
--- a/remote.c
+++ b/remote.c
@@ -748,29 +748,33 @@ int for_each_remote(each_remote_fn fn, void *priv)
void ref_remove_duplicates(struct ref *ref_map)
{
struct string_list refs = STRING_LIST_INIT_NODUP;
- struct string_list_item *item = NULL;
- struct ref *prev = NULL, *next = NULL;
+ struct ref **p;
- for (; ref_map; prev = ref_map, ref_map = next) {
- next = ref_map->next;
- if (!ref_map->peer_ref)
+ for (p = &ref_map; *p; ) {
+ struct ref *ref = *p;
+ struct string_list_item *item;
+
+ if (!ref->peer_ref) {
+ p = &ref->next;
continue;
+ }
- item = string_list_insert(&refs, ref_map->peer_ref->name);
+ item = string_list_insert(&refs, ref->peer_ref->name);
if (item->util) {
/* Entry already existed */
if (strcmp(((struct ref *)item->util)->name,
- ref_map->name))
+ ref->name))
die("%s tracks both %s and %s",
- ref_map->peer_ref->name,
+ ref->peer_ref->name,
((struct ref *)item->util)->name,
- ref_map->name);
- prev->next = ref_map->next;
- free(ref_map->peer_ref);
- free(ref_map);
- ref_map = prev; /* skip this; we freed it */
+ ref->name);
+ /* item is a duplicate; remove and free it */
+ *p = ref->next;
+ free(ref->peer_ref);
+ free(ref);
} else {
- item->util = ref_map;
+ item->util = ref;
+ p = &ref->next;
}
}
string_list_clear(&refs, 0);
--
1.8.4
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 08/15] ref_remove_duplicates(): improve documentation comment
2013-10-23 15:50 ` [PATCH 00/15] Change semantics of "fetch --tags" Michael Haggerty
` (6 preceding siblings ...)
2013-10-23 15:50 ` [PATCH 07/15] ref_remove_duplicates(): simplify function Michael Haggerty
@ 2013-10-23 15:50 ` Michael Haggerty
2013-10-23 18:47 ` Junio C Hamano
2013-10-23 15:50 ` [PATCH 09/15] builtin/fetch.c: reorder function definitions Michael Haggerty
` (7 subsequent siblings)
15 siblings, 1 reply; 57+ messages in thread
From: Michael Haggerty @ 2013-10-23 15:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister,
Michael Haggerty
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
remote.h | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/remote.h b/remote.h
index 131130a..40293c0 100644
--- a/remote.h
+++ b/remote.h
@@ -149,7 +149,14 @@ int resolve_remote_symref(struct ref *ref, struct ref *list);
int ref_newer(const unsigned char *new_sha1, const unsigned char *old_sha1);
/*
- * Removes and frees any duplicate refs in the map.
+ * Remove and free all but the first of any entries in the input list
+ * that map the same remote reference to the same local reference. If
+ * there are two entries that map different remote references to the
+ * same local reference, die.
+ *
+ * Note that the first entry is never removed; therefore, the pointer
+ * passed in as argument still points to the head of the list after
+ * the function returns.
*/
void ref_remove_duplicates(struct ref *ref_map);
--
1.8.4
^ permalink raw reply related [flat|nested] 57+ messages in thread
* Re: [PATCH 08/15] ref_remove_duplicates(): improve documentation comment
2013-10-23 15:50 ` [PATCH 08/15] ref_remove_duplicates(): improve documentation comment Michael Haggerty
@ 2013-10-23 18:47 ` Junio C Hamano
0 siblings, 0 replies; 57+ messages in thread
From: Junio C Hamano @ 2013-10-23 18:47 UTC (permalink / raw)
To: Michael Haggerty
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister
Michael Haggerty <mhagger@alum.mit.edu> writes:
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Up to this point the patches all look very sensible (modulo minor
nits I sent separately). Will come back to the rest of the topics
later.
Thanks.
> ---
> remote.h | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/remote.h b/remote.h
> index 131130a..40293c0 100644
> --- a/remote.h
> +++ b/remote.h
> @@ -149,7 +149,14 @@ int resolve_remote_symref(struct ref *ref, struct ref *list);
> int ref_newer(const unsigned char *new_sha1, const unsigned char *old_sha1);
>
> /*
> - * Removes and frees any duplicate refs in the map.
> + * Remove and free all but the first of any entries in the input list
> + * that map the same remote reference to the same local reference. If
> + * there are two entries that map different remote references to the
> + * same local reference, die.
> + *
> + * Note that the first entry is never removed; therefore, the pointer
> + * passed in as argument still points to the head of the list after
> + * the function returns.
> */
> void ref_remove_duplicates(struct ref *ref_map);
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH 09/15] builtin/fetch.c: reorder function definitions
2013-10-23 15:50 ` [PATCH 00/15] Change semantics of "fetch --tags" Michael Haggerty
` (7 preceding siblings ...)
2013-10-23 15:50 ` [PATCH 08/15] ref_remove_duplicates(): improve documentation comment Michael Haggerty
@ 2013-10-23 15:50 ` Michael Haggerty
2013-10-23 15:50 ` [PATCH 10/15] fetch --tags: fetch tags *in addition to* other stuff Michael Haggerty
` (6 subsequent siblings)
15 siblings, 0 replies; 57+ messages in thread
From: Michael Haggerty @ 2013-10-23 15:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister,
Michael Haggerty
Reorder function definitions to avoid the need for a forward
declaration of function find_non_local_tags().
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
builtin/fetch.c | 198 +++++++++++++++++++++++++++-----------------------------
1 file changed, 97 insertions(+), 101 deletions(-)
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 2248abf..61e8117 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -160,9 +160,105 @@ static void add_merge_config(struct ref **head,
}
}
+static int add_existing(const char *refname, const unsigned char *sha1,
+ int flag, void *cbdata)
+{
+ struct string_list *list = (struct string_list *)cbdata;
+ struct string_list_item *item = string_list_insert(list, refname);
+ item->util = xmalloc(20);
+ hashcpy(item->util, sha1);
+ return 0;
+}
+
+static int will_fetch(struct ref **head, const unsigned char *sha1)
+{
+ struct ref *rm = *head;
+ while (rm) {
+ if (!hashcmp(rm->old_sha1, sha1))
+ return 1;
+ rm = rm->next;
+ }
+ return 0;
+}
+
static void find_non_local_tags(struct transport *transport,
struct ref **head,
- struct ref ***tail);
+ struct ref ***tail)
+{
+ struct string_list existing_refs = STRING_LIST_INIT_DUP;
+ struct string_list remote_refs = STRING_LIST_INIT_NODUP;
+ const struct ref *ref;
+ struct string_list_item *item = NULL;
+
+ for_each_ref(add_existing, &existing_refs);
+ for (ref = transport_get_remote_refs(transport); ref; ref = ref->next) {
+ if (prefixcmp(ref->name, "refs/tags/"))
+ continue;
+
+ /*
+ * The peeled ref always follows the matching base
+ * ref, so if we see a peeled ref that we don't want
+ * to fetch then we can mark the ref entry in the list
+ * as one to ignore by setting util to NULL.
+ */
+ if (!suffixcmp(ref->name, "^{}")) {
+ if (item && !has_sha1_file(ref->old_sha1) &&
+ !will_fetch(head, ref->old_sha1) &&
+ !has_sha1_file(item->util) &&
+ !will_fetch(head, item->util))
+ item->util = NULL;
+ item = NULL;
+ continue;
+ }
+
+ /*
+ * If item is non-NULL here, then we previously saw a
+ * ref not followed by a peeled reference, so we need
+ * to check if it is a lightweight tag that we want to
+ * fetch.
+ */
+ if (item && !has_sha1_file(item->util) &&
+ !will_fetch(head, item->util))
+ item->util = NULL;
+
+ item = NULL;
+
+ /* skip duplicates and refs that we already have */
+ if (string_list_has_string(&remote_refs, ref->name) ||
+ string_list_has_string(&existing_refs, ref->name))
+ continue;
+
+ item = string_list_insert(&remote_refs, ref->name);
+ item->util = (void *)ref->old_sha1;
+ }
+ string_list_clear(&existing_refs, 1);
+
+ /*
+ * We may have a final lightweight tag that needs to be
+ * checked to see if it needs fetching.
+ */
+ if (item && !has_sha1_file(item->util) &&
+ !will_fetch(head, item->util))
+ item->util = NULL;
+
+ /*
+ * For all the tags in the remote_refs string list,
+ * add them to the list of refs to be fetched
+ */
+ for_each_string_list_item(item, &remote_refs) {
+ /* Unless we have already decided to ignore this item... */
+ if (item->util)
+ {
+ struct ref *rm = alloc_ref(item->string);
+ rm->peer_ref = alloc_ref(item->string);
+ hashcpy(rm->old_sha1, item->util);
+ **tail = rm;
+ *tail = &rm->next;
+ }
+ }
+
+ string_list_clear(&remote_refs, 0);
+}
static struct ref *get_ref_map(struct transport *transport,
struct refspec *refspecs, int refspec_count,
@@ -612,106 +708,6 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map)
return result;
}
-static int add_existing(const char *refname, const unsigned char *sha1,
- int flag, void *cbdata)
-{
- struct string_list *list = (struct string_list *)cbdata;
- struct string_list_item *item = string_list_insert(list, refname);
- item->util = xmalloc(20);
- hashcpy(item->util, sha1);
- return 0;
-}
-
-static int will_fetch(struct ref **head, const unsigned char *sha1)
-{
- struct ref *rm = *head;
- while (rm) {
- if (!hashcmp(rm->old_sha1, sha1))
- return 1;
- rm = rm->next;
- }
- return 0;
-}
-
-static void find_non_local_tags(struct transport *transport,
- struct ref **head,
- struct ref ***tail)
-{
- struct string_list existing_refs = STRING_LIST_INIT_DUP;
- struct string_list remote_refs = STRING_LIST_INIT_NODUP;
- const struct ref *ref;
- struct string_list_item *item = NULL;
-
- for_each_ref(add_existing, &existing_refs);
- for (ref = transport_get_remote_refs(transport); ref; ref = ref->next) {
- if (prefixcmp(ref->name, "refs/tags/"))
- continue;
-
- /*
- * The peeled ref always follows the matching base
- * ref, so if we see a peeled ref that we don't want
- * to fetch then we can mark the ref entry in the list
- * as one to ignore by setting util to NULL.
- */
- if (!suffixcmp(ref->name, "^{}")) {
- if (item && !has_sha1_file(ref->old_sha1) &&
- !will_fetch(head, ref->old_sha1) &&
- !has_sha1_file(item->util) &&
- !will_fetch(head, item->util))
- item->util = NULL;
- item = NULL;
- continue;
- }
-
- /*
- * If item is non-NULL here, then we previously saw a
- * ref not followed by a peeled reference, so we need
- * to check if it is a lightweight tag that we want to
- * fetch.
- */
- if (item && !has_sha1_file(item->util) &&
- !will_fetch(head, item->util))
- item->util = NULL;
-
- item = NULL;
-
- /* skip duplicates and refs that we already have */
- if (string_list_has_string(&remote_refs, ref->name) ||
- string_list_has_string(&existing_refs, ref->name))
- continue;
-
- item = string_list_insert(&remote_refs, ref->name);
- item->util = (void *)ref->old_sha1;
- }
- string_list_clear(&existing_refs, 1);
-
- /*
- * We may have a final lightweight tag that needs to be
- * checked to see if it needs fetching.
- */
- if (item && !has_sha1_file(item->util) &&
- !will_fetch(head, item->util))
- item->util = NULL;
-
- /*
- * For all the tags in the remote_refs string list,
- * add them to the list of refs to be fetched
- */
- for_each_string_list_item(item, &remote_refs) {
- /* Unless we have already decided to ignore this item... */
- if (item->util)
- {
- struct ref *rm = alloc_ref(item->string);
- rm->peer_ref = alloc_ref(item->string);
- hashcpy(rm->old_sha1, item->util);
- **tail = rm;
- *tail = &rm->next;
- }
- }
-
- string_list_clear(&remote_refs, 0);
-}
-
static void check_not_current_branch(struct ref *ref_map)
{
struct branch *current_branch = branch_get(NULL);
--
1.8.4
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 10/15] fetch --tags: fetch tags *in addition to* other stuff
2013-10-23 15:50 ` [PATCH 00/15] Change semantics of "fetch --tags" Michael Haggerty
` (8 preceding siblings ...)
2013-10-23 15:50 ` [PATCH 09/15] builtin/fetch.c: reorder function definitions Michael Haggerty
@ 2013-10-23 15:50 ` Michael Haggerty
2013-10-24 20:51 ` Junio C Hamano
2013-10-23 15:50 ` [PATCH 11/15] fetch --prune: prune only based on explicit refspecs Michael Haggerty
` (5 subsequent siblings)
15 siblings, 1 reply; 57+ messages in thread
From: Michael Haggerty @ 2013-10-23 15:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister,
Michael Haggerty
Previously, fetch's "--tags" option was considered equivalent to
specifying the refspec "refs/tags/*:refs/tags/*" on the command line;
in particular, it caused the remote.<name>.refspec configuration to be
ignored.
But it is not very useful to fetch tags without also fetching other
references, whereas it *is* quite useful to be able to fetch tags *in
addition to* other references. So change the semantics of this option
to do the latter.
If a user wants to fetch *only* tags, then it is still possible to
specifying an explicit refspec:
git fetch <remote> 'refs/tags/*:refs/tags/*'
Please note that the documentation prior to 1.8.0.3 was ambiguous
about this aspect of "fetch --tags" behavior. Commit
f0cb2f137c 2012-12-14 fetch --tags: clarify documentation
made the documentation match the old behavior. This commit changes
the documentation to match the new behavior.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
The change to builtin/fetch.c:get_ref_map() has the side effect of
changing the order that the (struct ref) objects are listed in
ref_map. It seems to me that this could probably only matter in the
case of duplicates. But later ref_remove_duplicates() is called, so
duplicates are eliminated. However, ref_remove_duplicates() always
retains the first instance of duplicates and discards the rest. It is
conceivable that the boolean flags (which are not inspected by
ref_remove_duplicates()) could differ among the duplicates, and that
therefore changing the order of the items in the original list has the
effect of changing the flags on the items that are retained.
I don't know this code well enough to judge whether this might be a
problem.
If it is, then the correct approach is probably either to teach
ref_remove_duplicates() to ensure that the flags are also consistent
across duplicates, or to somehow combine the flags from all duplicates
into the one that is retained. Please let me know if this is needed.
Documentation/fetch-options.txt | 8 +++---
builtin/fetch.c | 46 +++++++++++++++++++-------------
git-pull.sh | 2 +-
t/t5510-fetch.sh | 22 ++++++++++++---
t/t5515/fetch.br-unconfig_--tags_.._.git | 1 +
t/t5515/fetch.master_--tags_.._.git | 1 +
t/t5525-fetch-tagopt.sh | 23 ++++++++++++----
7 files changed, 71 insertions(+), 32 deletions(-)
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index ba1fe49..0e6d2ac 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -61,11 +61,9 @@ endif::git-pull[]
ifndef::git-pull[]
-t::
--tags::
- This is a short-hand for giving `refs/tags/*:refs/tags/*`
- refspec from the command line, to ask all tags to be fetched
- and stored locally. Because this acts as an explicit
- refspec, the default refspecs (configured with the
- remote.$name.fetch variable) are overridden and not used.
+ This is a short-hand requesting that all tags be fetched from
+ the remote in addition to whatever else is being fetched. It
+ is similar to using the refspec `refs/tags/*:refs/tags/*`.
--recurse-submodules[=yes|on-demand|no]::
This option controls if and under what conditions new commits of
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 61e8117..7edb1ea 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -271,7 +271,7 @@ static struct ref *get_ref_map(struct transport *transport,
const struct ref *remote_refs = transport_get_remote_refs(transport);
- if (refspec_count || tags == TAGS_SET) {
+ if (refspec_count) {
struct ref **old_tail;
for (i = 0; i < refspec_count; i++) {
@@ -279,11 +279,9 @@ static struct ref *get_ref_map(struct transport *transport,
if (refspecs[i].dst && refspecs[i].dst[0])
*autotags = 1;
}
- /* Merge everything on the command line, but not --tags */
+ /* Merge everything on the command line (but not --tags) */
for (rm = ref_map; rm; rm = rm->next)
rm->fetch_head_status = FETCH_HEAD_MERGE;
- if (tags == TAGS_SET)
- get_fetch_map(remote_refs, tag_refspec, &tail, 0);
/*
* For any refs that we happen to be fetching via command-line
@@ -334,8 +332,13 @@ static struct ref *get_ref_map(struct transport *transport,
tail = &ref_map->next;
}
}
- if (tags == TAGS_DEFAULT && *autotags)
+
+ if (tags == TAGS_SET)
+ /* also fetch all tags */
+ get_fetch_map(remote_refs, tag_refspec, &tail, 0);
+ else if (tags == TAGS_DEFAULT && *autotags)
find_non_local_tags(transport, &ref_map, &tail);
+
ref_remove_duplicates(ref_map);
return ref_map;
@@ -826,31 +829,38 @@ static int do_fetch(struct transport *transport,
goto cleanup;
}
if (prune) {
- /*
- * If --tags was specified, pretend that the user gave us
- * the canonical tags refspec
- */
+ struct refspec *prune_refspecs;
+ int prune_refspec_count;
+
+ if (ref_count) {
+ prune_refspecs = refs;
+ prune_refspec_count = ref_count;
+ } else {
+ prune_refspecs = transport->remote->fetch;
+ prune_refspec_count = transport->remote->fetch_refspec_nr;
+ }
+
if (tags == TAGS_SET) {
+ /*
+ * --tags was specified. Pretend that the user also
+ * gave us the canonical tags refspec
+ */
const char *tags_str = "refs/tags/*:refs/tags/*";
struct refspec *tags_refspec, *refspec;
/* Copy the refspec and add the tags to it */
- refspec = xcalloc(ref_count + 1, sizeof(struct refspec));
+ refspec = xcalloc(prune_refspec_count + 1, sizeof(*refspec));
tags_refspec = parse_fetch_refspec(1, &tags_str);
- memcpy(refspec, refs, ref_count * sizeof(struct refspec));
- memcpy(&refspec[ref_count], tags_refspec, sizeof(struct refspec));
- ref_count++;
+ memcpy(refspec, prune_refspecs, prune_refspec_count * sizeof(*refspec));
+ memcpy(&refspec[prune_refspec_count], tags_refspec, sizeof(*refspec));
- prune_refs(refspec, ref_count, ref_map);
+ prune_refs(refspec, prune_refspec_count + 1, ref_map);
- ref_count--;
/* The rest of the strings belong to fetch_one */
free_refspec(1, tags_refspec);
free(refspec);
- } else if (ref_count) {
- prune_refs(refs, ref_count, ref_map);
} else {
- prune_refs(transport->remote->fetch, transport->remote->fetch_refspec_nr, ref_map);
+ prune_refs(prune_refspecs, prune_refspec_count, ref_map);
}
}
free_refs(ref_map);
diff --git a/git-pull.sh b/git-pull.sh
index b946fd9..dac7e1c 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -172,7 +172,7 @@ error_on_no_merge_candidates () {
do
case "$opt" in
-t|--t|--ta|--tag|--tags)
- echo "Fetching tags only, you probably meant:"
+ echo "It doesn't make sense to pull tags; you probably meant:"
echo " git fetch --tags"
exit 1
esac
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 8328be1..02e5901 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -113,7 +113,7 @@ test_expect_success 'fetch --prune with a namespace keeps other namespaces' '
git rev-parse origin/master
'
-test_expect_success 'fetch --prune --tags does not delete the remote-tracking branches' '
+test_expect_success 'fetch --prune --tags prunes tags and branches' '
cd "$D" &&
git clone . prune-tags &&
cd prune-tags &&
@@ -124,7 +124,7 @@ test_expect_success 'fetch --prune --tags does not delete the remote-tracking br
git fetch --prune --tags origin &&
git rev-parse origin/master &&
- git rev-parse origin/fake-remote &&
+ test_must_fail git rev-parse origin/fake-remote &&
test_must_fail git rev-parse sometag
'
@@ -132,10 +132,26 @@ test_expect_success 'fetch --prune --tags with branch does not delete other remo
cd "$D" &&
git clone . prune-tags-branch &&
cd prune-tags-branch &&
+ git tag sometag master &&
git update-ref refs/remotes/origin/extrabranch master &&
git fetch --prune --tags origin master &&
- git rev-parse origin/extrabranch
+ git rev-parse origin/extrabranch &&
+ test_must_fail git rev-parse sometag
+'
+
+test_expect_success 'fetch --prune --tags with refspec prunes based on refspec' '
+ cd "$D" &&
+ git clone . prune-tags-refspec &&
+ cd prune-tags-refspec &&
+ git tag sometag master &&
+ git update-ref refs/remotes/origin/foo/otherbranch master &&
+ git update-ref refs/remotes/origin/extrabranch master &&
+
+ git fetch --prune --tags origin refs/heads/foo/*:refs/remotes/origin/foo/* &&
+ test_must_fail git rev-parse refs/remotes/origin/foo/otherbranch &&
+ git rev-parse origin/extrabranch &&
+ test_must_fail git rev-parse sometag
'
test_expect_success 'fetch tags when there is no tags' '
diff --git a/t/t5515/fetch.br-unconfig_--tags_.._.git b/t/t5515/fetch.br-unconfig_--tags_.._.git
index 1669cc4..0f70f66 100644
--- a/t/t5515/fetch.br-unconfig_--tags_.._.git
+++ b/t/t5515/fetch.br-unconfig_--tags_.._.git
@@ -1,4 +1,5 @@
# br-unconfig --tags ../.git
+0567da4d5edd2ff4bb292a465ba9e64dcad9536b ../
6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../
22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../
diff --git a/t/t5515/fetch.master_--tags_.._.git b/t/t5515/fetch.master_--tags_.._.git
index 8a74935..ab473a6 100644
--- a/t/t5515/fetch.master_--tags_.._.git
+++ b/t/t5515/fetch.master_--tags_.._.git
@@ -1,4 +1,5 @@
# master --tags ../.git
+0567da4d5edd2ff4bb292a465ba9e64dcad9536b ../
6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../
22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../
diff --git a/t/t5525-fetch-tagopt.sh b/t/t5525-fetch-tagopt.sh
index 4fbf7a1..45815f7 100755
--- a/t/t5525-fetch-tagopt.sh
+++ b/t/t5525-fetch-tagopt.sh
@@ -8,7 +8,8 @@ setup_clone () {
git clone --mirror . $1 &&
git remote add remote_$1 $1 &&
(cd $1 &&
- git tag tag_$1)
+ git tag tag_$1 &&
+ git branch branch_$1)
}
test_expect_success setup '
@@ -21,21 +22,33 @@ test_expect_success setup '
test_expect_success "fetch with tagopt=--no-tags does not get tag" '
git fetch remote_one &&
- test_must_fail git show-ref tag_one
+ test_must_fail git show-ref tag_one &&
+ git show-ref remote_one/branch_one
'
test_expect_success "fetch --tags with tagopt=--no-tags gets tag" '
+ (
+ cd one &&
+ git branch second_branch_one
+ ) &&
git fetch --tags remote_one &&
- git show-ref tag_one
+ git show-ref tag_one &&
+ git show-ref remote_one/second_branch_one
'
test_expect_success "fetch --no-tags with tagopt=--tags does not get tag" '
git fetch --no-tags remote_two &&
- test_must_fail git show-ref tag_two
+ test_must_fail git show-ref tag_two &&
+ git show-ref remote_two/branch_two
'
test_expect_success "fetch with tagopt=--tags gets tag" '
+ (
+ cd two &&
+ git branch second_branch_two
+ ) &&
git fetch remote_two &&
- git show-ref tag_two
+ git show-ref tag_two &&
+ git show-ref remote_two/second_branch_two
'
test_done
--
1.8.4
^ permalink raw reply related [flat|nested] 57+ messages in thread
* Re: [PATCH 10/15] fetch --tags: fetch tags *in addition to* other stuff
2013-10-23 15:50 ` [PATCH 10/15] fetch --tags: fetch tags *in addition to* other stuff Michael Haggerty
@ 2013-10-24 20:51 ` Junio C Hamano
2013-10-25 15:08 ` Michael Haggerty
2013-10-26 5:10 ` Michael Haggerty
0 siblings, 2 replies; 57+ messages in thread
From: Junio C Hamano @ 2013-10-24 20:51 UTC (permalink / raw)
To: Michael Haggerty
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister
Michael Haggerty <mhagger@alum.mit.edu> writes:
> Previously, fetch's "--tags" option was considered equivalent to
> specifying the refspec "refs/tags/*:refs/tags/*" on the command line;
> in particular, it caused the remote.<name>.refspec configuration to be
> ignored.
>
> But it is not very useful to fetch tags without also fetching other
> references, whereas it *is* quite useful to be able to fetch tags *in
> addition to* other references.
True but when fetching other references, tags relevant to the
history being fetched by default should automatically follow, so the
above explains why "fetch --tags" is not a useful thing to do daily.
> So change the semantics of this option
> to do the latter.
And I am not opposed to that change in the semantics; it makes an
operation that is not so useful less annoying.
> If a user wants to fetch *only* tags, then it is still possible to
> specifying an explicit refspec:
>
> git fetch <remote> 'refs/tags/*:refs/tags/*'
>
> Please note that the documentation prior to 1.8.0.3 was ambiguous
> about this aspect of "fetch --tags" behavior. Commit
>
> f0cb2f137c 2012-12-14 fetch --tags: clarify documentation
>
> made the documentation match the old behavior. This commit changes
> the documentation to match the new behavior.
The "old behaviour as designed". The documentation change was not
about refusing to fix a bug but the above makes it sound as if it
were a such commit.
> The change to builtin/fetch.c:get_ref_map() has the side effect of
> changing the order that the (struct ref) objects are listed in
> ref_map. It seems to me that this could probably only matter in the
> case of duplicates. But later ref_remove_duplicates() is called, so
> duplicates are eliminated. However, ref_remove_duplicates() always
> retains the first instance of duplicates and discards the rest. It is
> conceivable that the boolean flags (which are not inspected by
> ref_remove_duplicates()) could differ among the duplicates, and that
> therefore changing the order of the items in the original list has the
> effect of changing the flags on the items that are retained.
>
> I don't know this code well enough to judge whether this might be a
> problem.
> If it is, then the correct approach is probably either to teach
> ref_remove_duplicates() to ensure that the flags are also consistent
> across duplicates, or to somehow combine the flags from all duplicates
> into the one that is retained. Please let me know if this is needed.
I do not think either of these two is sufficient if you want to fix
it; ref_remove_duplicates() needs to be taught to retain the first
one it encounters among the duplicates, not "ensure the flags are
consistent" by erroring out when they are not among duplicates, nor
"somehow combine" flags from later one to the first one.
But I suspect that, if this behaviour change were a problem, such a
configuration was a problem before this change to most people; the
order of duplicated [remote "foo"] section would not be under
control of those who only use "git remote" without using an editor
to tweak .git/config file anyway. So I do not think this regression
is too big a deal; it is something you can fix later on top.
> diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
> index ba1fe49..0e6d2ac 100644
> --- a/Documentation/fetch-options.txt
> +++ b/Documentation/fetch-options.txt
> @@ -61,11 +61,9 @@ endif::git-pull[]
> ifndef::git-pull[]
> -t::
> --tags::
> - This is a short-hand for giving `refs/tags/*:refs/tags/*`
> - refspec from the command line, to ask all tags to be fetched
> - and stored locally. Because this acts as an explicit
> - refspec, the default refspecs (configured with the
> - remote.$name.fetch variable) are overridden and not used.
> + This is a short-hand requesting that all tags be fetched from
> + the remote in addition to whatever else is being fetched. It
> + is similar to using the refspec `refs/tags/*:refs/tags/*`.
This is no longer a short-hand, is it? There is no other way to ask
"fetch the usual stuff, and then refs/tags/*:refs/tags/* as well".
It should be sufficient for me to locally do:
s/This is a short-hand requesting/Request/;
I think.
> diff --git a/git-pull.sh b/git-pull.sh
> index b946fd9..dac7e1c 100755
> --- a/git-pull.sh
> +++ b/git-pull.sh
> @@ -172,7 +172,7 @@ error_on_no_merge_candidates () {
> do
> case "$opt" in
> -t|--t|--ta|--tag|--tags)
> - echo "Fetching tags only, you probably meant:"
> + echo "It doesn't make sense to pull tags; you probably meant:"
s/pull tags/pull all tags/; perhaps?
> echo " git fetch --tags"
> exit 1
> esac
> diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
> index 8328be1..02e5901 100755
> --- a/t/t5510-fetch.sh
> +++ b/t/t5510-fetch.sh
> @@ -113,7 +113,7 @@ test_expect_success 'fetch --prune with a namespace keeps other namespaces' '
> git rev-parse origin/master
> '
>
> -test_expect_success 'fetch --prune --tags does not delete the remote-tracking branches' '
> +test_expect_success 'fetch --prune --tags prunes tags and branches' '
> cd "$D" &&
> git clone . prune-tags &&
> cd prune-tags &&
> @@ -124,7 +124,7 @@ test_expect_success 'fetch --prune --tags does not delete the remote-tracking br
>
> git fetch --prune --tags origin &&
> git rev-parse origin/master &&
> - git rev-parse origin/fake-remote &&
> + test_must_fail git rev-parse origin/fake-remote &&
Nice.
> test_must_fail git rev-parse sometag
> '
>
> @@ -132,10 +132,26 @@ test_expect_success 'fetch --prune --tags with branch does not delete other remo
> cd "$D" &&
> git clone . prune-tags-branch &&
> cd prune-tags-branch &&
> + git tag sometag master &&
> git update-ref refs/remotes/origin/extrabranch master &&
>
> git fetch --prune --tags origin master &&
> - git rev-parse origin/extrabranch
> + git rev-parse origin/extrabranch &&
> + test_must_fail git rev-parse sometag
OK, and I'd imagine this will be an issue for a later patch to
address...
> diff --git a/t/t5515/fetch.br-unconfig_--tags_.._.git b/t/t5515/fetch.br-unconfig_--tags_.._.git
> index 1669cc4..0f70f66 100644
> --- a/t/t5515/fetch.br-unconfig_--tags_.._.git
> +++ b/t/t5515/fetch.br-unconfig_--tags_.._.git
> @@ -1,4 +1,5 @@
> # br-unconfig --tags ../.git
> +0567da4d5edd2ff4bb292a465ba9e64dcad9536b ../
> 6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../
> 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../
> 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../
> diff --git a/t/t5515/fetch.master_--tags_.._.git b/t/t5515/fetch.master_--tags_.._.git
> index 8a74935..ab473a6 100644
> --- a/t/t5515/fetch.master_--tags_.._.git
> +++ b/t/t5515/fetch.master_--tags_.._.git
> @@ -1,4 +1,5 @@
> # master --tags ../.git
> +0567da4d5edd2ff4bb292a465ba9e64dcad9536b ../
> 6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../
> 8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../
> 22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../
This shows us that the updated error message for "git pull --tags"
is much less likely to be given to the user, as we are much more
likely to be fetching something we would want to fetch and merge.
Good.
Thanks.
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 10/15] fetch --tags: fetch tags *in addition to* other stuff
2013-10-24 20:51 ` Junio C Hamano
@ 2013-10-25 15:08 ` Michael Haggerty
2013-10-28 19:10 ` Junio C Hamano
2013-10-26 5:10 ` Michael Haggerty
1 sibling, 1 reply; 57+ messages in thread
From: Michael Haggerty @ 2013-10-25 15:08 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister
On 10/24/2013 10:51 PM, Junio C Hamano wrote:
> Michael Haggerty <mhagger@alum.mit.edu> writes:
>
>> Previously, fetch's "--tags" option was considered equivalent to
>> specifying the refspec "refs/tags/*:refs/tags/*" on the command line;
>> in particular, it caused the remote.<name>.refspec configuration to be
>> ignored.
>>
>> But it is not very useful to fetch tags without also fetching other
>> references, whereas it *is* quite useful to be able to fetch tags *in
>> addition to* other references.
>
> True but when fetching other references, tags relevant to the
> history being fetched by default should automatically follow, so the
> above explains why "fetch --tags" is not a useful thing to do daily.
Maybe not necessary in many scenarios, but is it harmful for the common
case of cloning from and then periodically fetching from an upstream?
ISTM that the result of the declarative --tags option
we have all upstream tags
is easier to reason about than the history-dependent tag-following behavior
we have all upstream tags that point to commits that were
reachable from an upstream branch at the time of this or one
of the previous fetches
I just noticed that this is not explained very clearly in the fetch man
page. I will try to improve it.
>> If a user wants to fetch *only* tags, then it is still possible to
>> specifying an explicit refspec:
>>
>> git fetch <remote> 'refs/tags/*:refs/tags/*'
>>
>> Please note that the documentation prior to 1.8.0.3 was ambiguous
>> about this aspect of "fetch --tags" behavior. Commit
>>
>> f0cb2f137c 2012-12-14 fetch --tags: clarify documentation
>>
>> made the documentation match the old behavior. This commit changes
>> the documentation to match the new behavior.
>
> The "old behaviour as designed". The documentation change was not
> about refusing to fix a bug but the above makes it sound as if it
> were a such commit.
I didn't mean to imply this. My point in mentioning the documentation
change was that even though the old behavior has been in effect for a
while, it was not clearly documented until quite recently. But I guess
it is a moot point.
>> The change to builtin/fetch.c:get_ref_map() has the side effect of
>> changing the order that the (struct ref) objects are listed in
>> ref_map. It seems to me that this could probably only matter in the
>> case of duplicates. But later ref_remove_duplicates() is called, so
>> duplicates are eliminated. However, ref_remove_duplicates() always
>> retains the first instance of duplicates and discards the rest. It is
>> conceivable that the boolean flags (which are not inspected by
>> ref_remove_duplicates()) could differ among the duplicates, and that
>> therefore changing the order of the items in the original list has the
>> effect of changing the flags on the items that are retained.
>>
>> I don't know this code well enough to judge whether this might be a
>> problem.
>
>> If it is, then the correct approach is probably either to teach
>> ref_remove_duplicates() to ensure that the flags are also consistent
>> across duplicates, or to somehow combine the flags from all duplicates
>> into the one that is retained. Please let me know if this is needed.
>
> I do not think either of these two is sufficient if you want to fix
> it; ref_remove_duplicates() needs to be taught to retain the first
> one it encounters among the duplicates, not "ensure the flags are
> consistent" by erroring out when they are not among duplicates, nor
> "somehow combine" flags from later one to the first one.
>
> But I suspect that, if this behaviour change were a problem, such a
> configuration was a problem before this change to most people; the
> order of duplicated [remote "foo"] section would not be under
> control of those who only use "git remote" without using an editor
> to tweak .git/config file anyway. So I do not think this regression
> is too big a deal; it is something you can fix later on top.
I'll address your second point first: I agree that the order among
explicit refspecs couldn't really be a problem because it is already
arbitrary. However, get_ref_map() adds references from other sources to
the result list. For example, if there are command-line arguments, it adds
1. command-line arguments (with fetch_head_status=FETCH_HEAD_MERGE)
2. configured refspecs (with fetch_head_status=FETCH_HEAD_IGNORE)
3. if (--tags)
then tags_refspec (with fetch_head_status=FETCH_HEAD_NOT_FOR_MERGE)
else the result of find_non_local_tags() (with
fetch_head_status=FETCH_HEAD_NOT_FOR_MERGE)
It could very well be that the order matters across different classes of
reference.
Regarding your first point: if it matters which of the duplicates is
chosen, then it can only matter because they differ in some other way
than their reference names, for example in their flags. So a robust way
of de-duping them (if it is possible) would be to compare the two
records and decide which one should take precedence based on this other
information rather than based on which one happened to come earlier in
the list. Then the list order would be immaterial and (for example) it
wouldn't be a problem to reorder the items.
I'm being very wishy-washy because I haven't yet invested the time to
learn how these lists of refs are used. Maybe I need to do so.
I have run out of time, so I will address your comments about the
documentation changes in a separate email.
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 10/15] fetch --tags: fetch tags *in addition to* other stuff
2013-10-25 15:08 ` Michael Haggerty
@ 2013-10-28 19:10 ` Junio C Hamano
2013-10-30 4:26 ` Michael Haggerty
0 siblings, 1 reply; 57+ messages in thread
From: Junio C Hamano @ 2013-10-28 19:10 UTC (permalink / raw)
To: Michael Haggerty
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister
Michael Haggerty <mhagger@alum.mit.edu> writes:
>> True but when fetching other references, tags relevant to the
>> history being fetched by default should automatically follow, so the
>> above explains why "fetch --tags" is not a useful thing to do daily.
>
> Maybe not necessary in many scenarios, but is it harmful for the common
> case of cloning from and then periodically fetching from an upstream?
There is no mention of "harmful"; I only said "not useful". And it
comes primarily from knowing why "--tags" was introduced in the
first place; I should have said "less useful than before, ever since
we started to reliably auto-follow".
The only "harmful" part is its interaction with "--prune", which
your series nicely addresses.
> ISTM that the result of the declarative --tags option
>
> we have all upstream tags
>
> is easier to reason about than the history-dependent tag-following behavior
I'd say "we have all the relevant tags" and "we have all the tags
the other side has" are equally valid things to wish for, depending
who you are and how your project is organized, and one is not
necessarily easy/useful than the other. In case it was unclear, I
was not seriously advocating to deprecate/remove "--tags".
> Regarding your first point: if it matters which of the duplicates is
> chosen, then it can only matter because they differ in some other way
> than their reference names, for example in their flags. So a robust way
> of de-duping them (if it is possible) would be to compare the two
> records and decide which one should take precedence based on this other
> information rather than based on which one happened to come earlier in
> the list. Then the list order would be immaterial and (for example) it
> wouldn't be a problem to reorder the items.
But that changes the behaviour to those who has cared to rely on the
ordering. With the change to first collect and then sort unstably
before deduping, the series already tells them not to rely on the
order, and two of us tentatively agreed in this discussion that it
is not likely to matter. If later this agreement turns out to be a
mistake and there are people who *do* rely on the ordering, the only
acceptable fix for them is by making sure we restore the "first one
trumps" semantics, not by defining an alternative, arguably better,
behaviour---that is not a regression fix.
In any case, thanks for working on this topic.
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 10/15] fetch --tags: fetch tags *in addition to* other stuff
2013-10-28 19:10 ` Junio C Hamano
@ 2013-10-30 4:26 ` Michael Haggerty
0 siblings, 0 replies; 57+ messages in thread
From: Michael Haggerty @ 2013-10-30 4:26 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister,
Jeff King
On 10/28/2013 08:10 PM, Junio C Hamano wrote:
> Michael Haggerty <mhagger@alum.mit.edu> writes:
>
>>> True but when fetching other references, tags relevant to the
>>> history being fetched by default should automatically follow, so the
>>> above explains why "fetch --tags" is not a useful thing to do daily.
>>
>> Maybe not necessary in many scenarios, but is it harmful for the common
>> case of cloning from and then periodically fetching from an upstream?
>
> There is no mention of "harmful"; I only said "not useful". And it
> comes primarily from knowing why "--tags" was introduced in the
> first place; I should have said "less useful than before, ever since
> we started to reliably auto-follow".
>
> The only "harmful" part is its interaction with "--prune", which
> your series nicely addresses.
OK, then we are in agreement.
>> ISTM that the result of the declarative --tags option
>>
>> we have all upstream tags
>>
>> is easier to reason about than the history-dependent tag-following behavior
>
> I'd say "we have all the relevant tags" and "we have all the tags
> the other side has" are equally valid things to wish for, depending
> who you are and how your project is organized, and one is not
> necessarily easy/useful than the other. In case it was unclear, I
> was not seriously advocating to deprecate/remove "--tags".
Yes, I agree that both are valid things to wish for. I guess I was
mostly thinking about which would be a better default.
"clone" and "remote add", by default, configure the repo to fetch all
branches on the remote. For this default setup, what are the pros and
cons of the two tag-fetching options (assuming that this patch series
has fixed the problem with tag pruning)?
Pros of auto-following:
* Doesn't require a change to the status quo
* The the user can change the refspec to be more restrictive without
having to change the tag-following option and it continues to do the
right thing.
* If the project has branches outside of refs/heads (which would not, by
default, be fetched--think continuous integration artifacts) and also
has tags pointing at those branches, the user might get unwanted
contents with "--tags", but not with auto-following.
Pros of --tags:
* Easier to understand (?) because result is not history-dependent.
* Avoids missing tags that are not directly on a branch:
o---o---o---o <- branch
\
o <- tag
So it's not obvious that one is better than the other. I think if I
were choosing the behavior for the first time, I would favor --tags.
But I don't think the advantage is strong enough to make it worth
changing the existing default.
>> Regarding your first point: if it matters which of the duplicates is
>> chosen, then it can only matter because they differ in some other way
>> than their reference names, for example in their flags. So a robust way
>> of de-duping them (if it is possible) would be to compare the two
>> records and decide which one should take precedence based on this other
>> information rather than based on which one happened to come earlier in
>> the list. Then the list order would be immaterial and (for example) it
>> wouldn't be a problem to reorder the items.
>
> But that changes the behaviour to those who has cared to rely on the
> ordering. With the change to first collect and then sort unstably
> before deduping, the series already tells them not to rely on the
> order, and two of us tentatively agreed in this discussion that it
> is not likely to matter. If later this agreement turns out to be a
> mistake and there are people who *do* rely on the ordering, the only
> acceptable fix for them is by making sure we restore the "first one
> trumps" semantics, not by defining an alternative, arguably better,
> behaviour---that is not a regression fix.
Please note that the current patch series does *not* change the
algorithm to use an unstable sort; that was only a suggestion for the
future should somebody discover that the O(N^2) algorithm in this
function is a performance bottleneck.
What the old patch series *did* do was change the ordering that
get_ref_map() adds references to the list in the case of (refspec_count
&& tags == TAGS_SET) by moving the (tags == TAGS_SET) handling outside
of the "true" branch of the (refspec_count) conditional. This had the
result that the references added by
get_fetch_map(remote_refs, tag_refspec, &tail, 0);
came after, rather than before, the references opportunistically being
fetched with FETCH_HEAD_IGNORE status.
But I dug even deeper and found that there was a (rather obscure)
situation where the ordering change could lead to incorrect behavior,
namely if all of the following are true:
* there is a configured refspec for tags, like refs/tags/*:refs/tags/*
* the user runs fetch with the --tags option and also with an explicit
refspec on the command line to fetch a remote tag (e.g.,
refs/tags/foo:refs/heads/foo).
In that case (after this version of this patch), an entry for
refs/tags/foo:refs/heads/foo would be added to the list, then the
opportunistic "refs/tags/foo:refs/tags/foo" would be added with
FETCH_HEAD_IGNORE. Then the --tags option would be processed, adding a
second record "refs/tags/foo:refs/tags/foo" to the list, but this time
with FETCH_HEAD_NOT_FOR_MERGE. The call to ref_remove_duplicates()
would remove the last entry, leaving the entry with FETCH_HEAD_IGNORE
instead of the (correct) entry with FETCH_HEAD_NOT_FOR_MERGE. The
result would be that refs/tags/foo would not be written to FETCH_HEAD.
So I will re-roll this series with a few extra patches that first, avoid
subjecting the --tags entries to the opportunistic-update machinery (it
is redundant), and also preserve the old order where the --tags entries
precede the opportunistic entries in the list.
Thanks again for your comments!
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 10/15] fetch --tags: fetch tags *in addition to* other stuff
2013-10-24 20:51 ` Junio C Hamano
2013-10-25 15:08 ` Michael Haggerty
@ 2013-10-26 5:10 ` Michael Haggerty
1 sibling, 0 replies; 57+ messages in thread
From: Michael Haggerty @ 2013-10-26 5:10 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister
On 10/24/2013 10:51 PM, Junio C Hamano wrote:
> Michael Haggerty <mhagger@alum.mit.edu> writes:
>> diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
>> index ba1fe49..0e6d2ac 100644
>> --- a/Documentation/fetch-options.txt
>> +++ b/Documentation/fetch-options.txt
>> @@ -61,11 +61,9 @@ endif::git-pull[]
>> ifndef::git-pull[]
>> -t::
>> --tags::
>> - This is a short-hand for giving `refs/tags/*:refs/tags/*`
>> - refspec from the command line, to ask all tags to be fetched
>> - and stored locally. Because this acts as an explicit
>> - refspec, the default refspecs (configured with the
>> - remote.$name.fetch variable) are overridden and not used.
>> + This is a short-hand requesting that all tags be fetched from
>> + the remote in addition to whatever else is being fetched. It
>> + is similar to using the refspec `refs/tags/*:refs/tags/*`.
>
> This is no longer a short-hand, is it? There is no other way to ask
> "fetch the usual stuff, and then refs/tags/*:refs/tags/* as well".
>
> It should be sufficient for me to locally do:
>
> s/This is a short-hand requesting/Request/;
>
> I think.
Yes, that's better.
>> diff --git a/git-pull.sh b/git-pull.sh
>> index b946fd9..dac7e1c 100755
>> --- a/git-pull.sh
>> +++ b/git-pull.sh
>> @@ -172,7 +172,7 @@ error_on_no_merge_candidates () {
>> do
>> case "$opt" in
>> -t|--t|--ta|--tag|--tags)
>> - echo "Fetching tags only, you probably meant:"
>> + echo "It doesn't make sense to pull tags; you probably meant:"
>
> s/pull tags/pull all tags/; perhaps?
Yes, that's also an improvement.
Thanks,
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH 11/15] fetch --prune: prune only based on explicit refspecs
2013-10-23 15:50 ` [PATCH 00/15] Change semantics of "fetch --tags" Michael Haggerty
` (9 preceding siblings ...)
2013-10-23 15:50 ` [PATCH 10/15] fetch --tags: fetch tags *in addition to* other stuff Michael Haggerty
@ 2013-10-23 15:50 ` Michael Haggerty
2013-10-24 21:11 ` Junio C Hamano
2013-10-23 15:50 ` [PATCH 12/15] query_refspecs(): move some constants out of the loop Michael Haggerty
` (4 subsequent siblings)
15 siblings, 1 reply; 57+ messages in thread
From: Michael Haggerty @ 2013-10-23 15:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister,
Michael Haggerty
The old behavior of "fetch --prune" was to prune whatever was being
fetched. In particular, "fetch --prune --tags" caused tags not only
to be fetched, but also to be pruned. This is inappropriate because
there is only one tags namespace that is shared among the local
repository and all remotes. Therefore, if the user defines a local
tag and then runs "git fetch --prune --tags", then the local tag is
deleted. Moreover, "--prune" and "--tags" can also be configured via
fetch.prune / remote.<name>.prune and remote.<name>.tagopt, making it
even less obvious that an invocation of "git fetch" could result in
tag lossage.
Since the command "git remote update" invokes "git fetch", it had the
same problem.
The command "git remote prune", on the other hand, disregarded the
setting of remote.<name>.tagopt, and so its behavior was inconsistent
with that of the other commands.
So the old behavior made it too easy to lose tags. To fix this
problem, change "fetch --prune" to prune references based only on
refspecs specified explicitly by the user, either on the command line
or via remote.<name>.fetch. Thus, tags are no longer made subject to
pruning by the --tags option or the remote.<name>.tagopt setting.
However, tags *are* still subject to pruning if they are fetched as
part of a refspec, and that is good. For example:
* On the command line,
git fetch --prune 'refs/tags/*:refs/tags/*'
causes tags, and only tags, to be fetched and pruned, and is
therefore a simple way for the user to get the equivalent of the old
behavior of "--prune --tag".
* For a remote that was configured with the "--mirror" option, the
configuration is set to include
[remote "name"]
fetch = +refs/*:refs/*
, which causes tags to be subject to pruning along with all other
references. This is the behavior that will typically be desired for
a mirror.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
Documentation/config.txt | 2 +-
Documentation/fetch-options.txt | 15 ++++++++++++---
builtin/fetch.c | 39 +++++++++------------------------------
t/t5510-fetch.sh | 10 +++++-----
4 files changed, 27 insertions(+), 39 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index d4d93c9..83c1700 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2086,7 +2086,7 @@ remote.<name>.vcs::
remote.<name>.prune::
When set to true, fetching from this remote by default will also
remove any remote-tracking branches which no longer exist on the
- remote (as if the `--prune` option was give on the command line).
+ remote (as if the `--prune` option was given on the command line).
Overrides `fetch.prune` settings, if any.
remotes.<group>::
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index 0e6d2ac..5d12219 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -41,8 +41,14 @@ ifndef::git-pull[]
-p::
--prune::
- After fetching, remove any remote-tracking branches which
- no longer exist on the remote.
+ After fetching, remove any remote-tracking branches that
+ no longer exist on the remote. Tags are not subject to
+ pruning in the usual case that they are fetched because of the
+ --tags option or remote.<name>.tagopt. However, if tags are
+ fetched due to an explicit refspec (either on the command line
+ or in the remote configuration, for example if the remote was
+ cloned with the --mirror option), then they are also subject
+ to pruning.
endif::git-pull[]
ifdef::git-pull[]
@@ -63,7 +69,10 @@ ifndef::git-pull[]
--tags::
This is a short-hand requesting that all tags be fetched from
the remote in addition to whatever else is being fetched. It
- is similar to using the refspec `refs/tags/*:refs/tags/*`.
+ is similar to using the refspec `refs/tags/*:refs/tags/*`,
+ except that it doesn't subject tags to pruning, regardless of
+ a --prune option or the configuration settings of fetch.prune
+ or remote.<name>.prune.
--recurse-submodules[=yes|on-demand|no]::
This option controls if and under what conditions new commits of
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 7edb1ea..47b63a7 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -829,38 +829,17 @@ static int do_fetch(struct transport *transport,
goto cleanup;
}
if (prune) {
- struct refspec *prune_refspecs;
- int prune_refspec_count;
-
+ /*
+ * We only prune based on refspecs specified
+ * explicitly (via command line or configuration); we
+ * don't care whether --tags was specified.
+ */
if (ref_count) {
- prune_refspecs = refs;
- prune_refspec_count = ref_count;
- } else {
- prune_refspecs = transport->remote->fetch;
- prune_refspec_count = transport->remote->fetch_refspec_nr;
- }
-
- if (tags == TAGS_SET) {
- /*
- * --tags was specified. Pretend that the user also
- * gave us the canonical tags refspec
- */
- const char *tags_str = "refs/tags/*:refs/tags/*";
- struct refspec *tags_refspec, *refspec;
-
- /* Copy the refspec and add the tags to it */
- refspec = xcalloc(prune_refspec_count + 1, sizeof(*refspec));
- tags_refspec = parse_fetch_refspec(1, &tags_str);
- memcpy(refspec, prune_refspecs, prune_refspec_count * sizeof(*refspec));
- memcpy(&refspec[prune_refspec_count], tags_refspec, sizeof(*refspec));
-
- prune_refs(refspec, prune_refspec_count + 1, ref_map);
-
- /* The rest of the strings belong to fetch_one */
- free_refspec(1, tags_refspec);
- free(refspec);
+ prune_refs(refs, ref_count, ref_map);
} else {
- prune_refs(prune_refspecs, prune_refspec_count, ref_map);
+ prune_refs(transport->remote->fetch,
+ transport->remote->fetch_refspec_nr,
+ ref_map);
}
}
free_refs(ref_map);
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 02e5901..5d4581d 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -113,7 +113,7 @@ test_expect_success 'fetch --prune with a namespace keeps other namespaces' '
git rev-parse origin/master
'
-test_expect_success 'fetch --prune --tags prunes tags and branches' '
+test_expect_success 'fetch --prune --tags prunes branches but not tags' '
cd "$D" &&
git clone . prune-tags &&
cd prune-tags &&
@@ -125,10 +125,10 @@ test_expect_success 'fetch --prune --tags prunes tags and branches' '
git fetch --prune --tags origin &&
git rev-parse origin/master &&
test_must_fail git rev-parse origin/fake-remote &&
- test_must_fail git rev-parse sometag
+ git rev-parse sometag
'
-test_expect_success 'fetch --prune --tags with branch does not delete other remote-tracking branches' '
+test_expect_success 'fetch --prune --tags with branch does not prune other things' '
cd "$D" &&
git clone . prune-tags-branch &&
cd prune-tags-branch &&
@@ -137,7 +137,7 @@ test_expect_success 'fetch --prune --tags with branch does not delete other remo
git fetch --prune --tags origin master &&
git rev-parse origin/extrabranch &&
- test_must_fail git rev-parse sometag
+ git rev-parse sometag
'
test_expect_success 'fetch --prune --tags with refspec prunes based on refspec' '
@@ -151,7 +151,7 @@ test_expect_success 'fetch --prune --tags with refspec prunes based on refspec'
git fetch --prune --tags origin refs/heads/foo/*:refs/remotes/origin/foo/* &&
test_must_fail git rev-parse refs/remotes/origin/foo/otherbranch &&
git rev-parse origin/extrabranch &&
- test_must_fail git rev-parse sometag
+ git rev-parse sometag
'
test_expect_success 'fetch tags when there is no tags' '
--
1.8.4
^ permalink raw reply related [flat|nested] 57+ messages in thread
* Re: [PATCH 11/15] fetch --prune: prune only based on explicit refspecs
2013-10-23 15:50 ` [PATCH 11/15] fetch --prune: prune only based on explicit refspecs Michael Haggerty
@ 2013-10-24 21:11 ` Junio C Hamano
2013-10-26 6:49 ` Michael Haggerty
0 siblings, 1 reply; 57+ messages in thread
From: Junio C Hamano @ 2013-10-24 21:11 UTC (permalink / raw)
To: Michael Haggerty
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister
Michael Haggerty <mhagger@alum.mit.edu> writes:
> ...
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Everything in the proposed log message made sense to me.
> diff --git a/Documentation/config.txt b/Documentation/config.txt
> index d4d93c9..83c1700 100644
> --- a/Documentation/config.txt
> +++ b/Documentation/config.txt
> @@ -2086,7 +2086,7 @@ remote.<name>.vcs::
> remote.<name>.prune::
> When set to true, fetching from this remote by default will also
> remove any remote-tracking branches which no longer exist on the
> - remote (as if the `--prune` option was give on the command line).
> + remote (as if the `--prune` option was given on the command line).
Shouldn't we stop saying "branches" here?
> diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
> index 0e6d2ac..5d12219 100644
> --- a/Documentation/fetch-options.txt
> +++ b/Documentation/fetch-options.txt
> @@ -41,8 +41,14 @@ ifndef::git-pull[]
>
> -p::
> --prune::
> - After fetching, remove any remote-tracking branches which
> - no longer exist on the remote.
> + After fetching, remove any remote-tracking branches that
Likewise. This is a lot more important than the one in
remote.<name>.prune documentation, as the next sentence "Tags are
not subject to ..." implies that they fall into the same category as
what gets pruned here, i.e. "remote-tracking branches" in the above
sentence, but nobody calls refs/tags/v1.0.0 a "remote-tracking
branch" even if it came from your 'origin'.
> + no longer exist on the remote. Tags are not subject to
> + pruning in the usual case that they are fetched because of the
> + --tags option or remote.<name>.tagopt.
We should mention the most usual case tags are fetched, before
mentioning the case the unusual option "--tags" was used from the
command line or .tagopt configuration was used. Namely, when the
tags are automatically followed.
> + However, if tags are
> + fetched due to an explicit refspec (either on the command line
> + or in the remote configuration, for example if the remote was
> + cloned with the --mirror option), then they are also subject
> + to pruning.
Very good.
> @@ -63,7 +69,10 @@ ifndef::git-pull[]
> --tags::
> This is a short-hand requesting that all tags be fetched from
> the remote in addition to whatever else is being fetched. It
> - is similar to using the refspec `refs/tags/*:refs/tags/*`.
> + is similar to using the refspec `refs/tags/*:refs/tags/*`,
> + except that it doesn't subject tags to pruning, regardless of
> + a --prune option or the configuration settings of fetch.prune
> + or remote.<name>.prune.
Using --tags is not similar to using refs/tags/*:refs/tags/* after
the previous patch already; "git fetch origin --tags" and "git fetch
origin refs/tags/*:refs/tags/*" are vastly different and that was
the whole point of the previous step. And that "calling something
not so similar similar" needs to be fixed further here to clarify
that they are not similar in yet another way.
We should just lose "It is similar to using" from 10/15 and start
over, perhaps? Add the first paragraph of the below in 10/15 and
add the rest in 11/15, or something.
--tags::
Request that all tags be fetched from the remote
under the same name (i.e. `refs/tags/X` is created in
our repository by copying their `refs/tags/X`), in
addition to whatever is fetched by the same `git
fetch` command without this option on the command
line.
+
When `refs/tags/*` hierarchy from the remote is copied only
because this option was given, they are not subject to be
pruned when `--prune` option (or configuration variables
like `fetch.prune` or `remote.<name>.prune`) is in effect.
That would make it clear that they are subject to pruning when --mirror
or an explicit refspec refs/tags/*:refs/tags/* is given, as tags are
not fetched "only because of --tags" in such cases.
> diff --git a/builtin/fetch.c b/builtin/fetch.c
> index 7edb1ea..47b63a7 100644
> --- a/builtin/fetch.c
> +++ b/builtin/fetch.c
> @@ -829,38 +829,17 @@ static int do_fetch(struct transport *transport,
> goto cleanup;
> }
> if (prune) {
> - struct refspec *prune_refspecs;
> - int prune_refspec_count;
> -
> + /*
> + * We only prune based on refspecs specified
> + * explicitly (via command line or configuration); we
> + * don't care whether --tags was specified.
> + */
> if (ref_count) {
> - prune_refspecs = refs;
> - prune_refspec_count = ref_count;
> - } else {
> - prune_refspecs = transport->remote->fetch;
> - prune_refspec_count = transport->remote->fetch_refspec_nr;
> - }
> -
> - if (tags == TAGS_SET) {
> - /*
> - * --tags was specified. Pretend that the user also
> - * gave us the canonical tags refspec
> - */
> - const char *tags_str = "refs/tags/*:refs/tags/*";
> - struct refspec *tags_refspec, *refspec;
> -
> - /* Copy the refspec and add the tags to it */
> - refspec = xcalloc(prune_refspec_count + 1, sizeof(*refspec));
> - tags_refspec = parse_fetch_refspec(1, &tags_str);
> - memcpy(refspec, prune_refspecs, prune_refspec_count * sizeof(*refspec));
> - memcpy(&refspec[prune_refspec_count], tags_refspec, sizeof(*refspec));
> -
> - prune_refs(refspec, prune_refspec_count + 1, ref_map);
> -
> - /* The rest of the strings belong to fetch_one */
> - free_refspec(1, tags_refspec);
> - free(refspec);
> + prune_refs(refs, ref_count, ref_map);
> } else {
> - prune_refs(prune_refspecs, prune_refspec_count, ref_map);
> + prune_refs(transport->remote->fetch,
> + transport->remote->fetch_refspec_nr,
> + ref_map);
> }
> }
Nice.
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 11/15] fetch --prune: prune only based on explicit refspecs
2013-10-24 21:11 ` Junio C Hamano
@ 2013-10-26 6:49 ` Michael Haggerty
2013-10-28 15:08 ` Junio C Hamano
0 siblings, 1 reply; 57+ messages in thread
From: Michael Haggerty @ 2013-10-26 6:49 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister
On 10/24/2013 11:11 PM, Junio C Hamano wrote:
> Michael Haggerty <mhagger@alum.mit.edu> writes:
>
>> ...
>> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
>
> Everything in the proposed log message made sense to me.
>
>> diff --git a/Documentation/config.txt b/Documentation/config.txt
>> index d4d93c9..83c1700 100644
>> --- a/Documentation/config.txt
>> +++ b/Documentation/config.txt
>> @@ -2086,7 +2086,7 @@ remote.<name>.vcs::
>> remote.<name>.prune::
>> When set to true, fetching from this remote by default will also
>> remove any remote-tracking branches which no longer exist on the
>> - remote (as if the `--prune` option was give on the command line).
>> + remote (as if the `--prune` option was given on the command line).
>
> Shouldn't we stop saying "branches" here?
>
>> diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
>> index 0e6d2ac..5d12219 100644
>> --- a/Documentation/fetch-options.txt
>> +++ b/Documentation/fetch-options.txt
>> @@ -41,8 +41,14 @@ ifndef::git-pull[]
>>
>> -p::
>> --prune::
>> - After fetching, remove any remote-tracking branches which
>> - no longer exist on the remote.
>> + After fetching, remove any remote-tracking branches that
>
> Likewise. This is a lot more important than the one in
> remote.<name>.prune documentation, as the next sentence "Tags are
> not subject to ..." implies that they fall into the same category as
> what gets pruned here, i.e. "remote-tracking branches" in the above
> sentence, but nobody calls refs/tags/v1.0.0 a "remote-tracking
> branch" even if it came from your 'origin'.
OK, I will change both of the above from "remote-tracking branches" to
"remote-tracking references".
>> + no longer exist on the remote. Tags are not subject to
>> + pruning in the usual case that they are fetched because of the
>> + --tags option or remote.<name>.tagopt.
>
> We should mention the most usual case tags are fetched, before
> mentioning the case the unusual option "--tags" was used from the
> command line or .tagopt configuration was used. Namely, when the
> tags are automatically followed.
OK, I will change this in the next draft.
>> @@ -63,7 +69,10 @@ ifndef::git-pull[]
>> --tags::
>> This is a short-hand requesting that all tags be fetched from
>> the remote in addition to whatever else is being fetched. It
>> - is similar to using the refspec `refs/tags/*:refs/tags/*`.
>> + is similar to using the refspec `refs/tags/*:refs/tags/*`,
>> + except that it doesn't subject tags to pruning, regardless of
>> + a --prune option or the configuration settings of fetch.prune
>> + or remote.<name>.prune.
>
> Using --tags is not similar to using refs/tags/*:refs/tags/* after
> the previous patch already; "git fetch origin --tags" and "git fetch
> origin refs/tags/*:refs/tags/*" are vastly different and that was
> the whole point of the previous step. And that "calling something
> not so similar similar" needs to be fixed further here to clarify
> that they are not similar in yet another way.
>
> We should just lose "It is similar to using" from 10/15 and start
> over, perhaps? Add the first paragraph of the below in 10/15 and
> add the rest in 11/15, or something.
>
> --tags::
> Request that all tags be fetched from the remote
> under the same name (i.e. `refs/tags/X` is created in
> our repository by copying their `refs/tags/X`), in
> addition to whatever is fetched by the same `git
> fetch` command without this option on the command
> line.
> +
> When `refs/tags/*` hierarchy from the remote is copied only
> because this option was given, they are not subject to be
> pruned when `--prune` option (or configuration variables
> like `fetch.prune` or `remote.<name>.prune`) is in effect.
>
> That would make it clear that they are subject to pruning when --mirror
> or an explicit refspec refs/tags/*:refs/tags/* is given, as tags are
> not fetched "only because of --tags" in such cases.
I see your point. What do you think about the following version, which
is a bit more compact and refers the reader to --prune for the full story:
-t::
--tags::
Fetch all tags from the remote (i.e., fetch remote tags
`refs/tags/*` into local tags with the same name), in addition
to whatever else would otherwise be fetched. Using this
option does not subject tags to pruning, even if --prune is
used (though tags may be pruned anyway if they are also the
destination of an explicit refspec; see '--prune').
I also want to improve the description of tag auto-following in general.
I will send a re-rolled patch series in the next couple of days.
Thanks for your prompt and helpful advice!
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 11/15] fetch --prune: prune only based on explicit refspecs
2013-10-26 6:49 ` Michael Haggerty
@ 2013-10-28 15:08 ` Junio C Hamano
0 siblings, 0 replies; 57+ messages in thread
From: Junio C Hamano @ 2013-10-28 15:08 UTC (permalink / raw)
To: Michael Haggerty
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister
Michael Haggerty <mhagger@alum.mit.edu> writes:
> On 10/24/2013 11:11 PM, Junio C Hamano wrote:
> ...
>> We should just lose "It is similar to using" from 10/15 and start
>> over, perhaps? Add the first paragraph of the below in 10/15 and
>> add the rest in 11/15, or something.
>>
>> --tags::
>> Request that all tags be fetched from the remote
>> under the same name (i.e. `refs/tags/X` is created in
>> our repository by copying their `refs/tags/X`), in
>> addition to whatever is fetched by the same `git
>> fetch` command without this option on the command
>> line.
>> +
>> When `refs/tags/*` hierarchy from the remote is copied only
>> because this option was given, they are not subject to be
>> pruned when `--prune` option (or configuration variables
>> like `fetch.prune` or `remote.<name>.prune`) is in effect.
>>
>> That would make it clear that they are subject to pruning when --mirror
>> or an explicit refspec refs/tags/*:refs/tags/* is given, as tags are
>> not fetched "only because of --tags" in such cases.
>
> I see your point. What do you think about the following version, which
> is a bit more compact and refers the reader to --prune for the full story:
>
> -t::
> --tags::
> Fetch all tags from the remote (i.e., fetch remote tags
> `refs/tags/*` into local tags with the same name), in addition
> to whatever else would otherwise be fetched. Using this
> option does not subject tags to pruning, even if --prune is
> used (though tags may be pruned anyway if they are also the
> destination of an explicit refspec; see '--prune').
I like the first sentence of yours better. The second sentence feels
somewhat iffy, though. --tags refs/tags/*:refs/tags/* will allow
tags to be pruned, so s/option does not/option alone does not/ needs
to be done to be precise, at least.
Thanks.
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH 12/15] query_refspecs(): move some constants out of the loop
2013-10-23 15:50 ` [PATCH 00/15] Change semantics of "fetch --tags" Michael Haggerty
` (10 preceding siblings ...)
2013-10-23 15:50 ` [PATCH 11/15] fetch --prune: prune only based on explicit refspecs Michael Haggerty
@ 2013-10-23 15:50 ` Michael Haggerty
2013-10-23 15:50 ` [PATCH 13/15] builtin/remote.c: reorder function definitions Michael Haggerty
` (3 subsequent siblings)
15 siblings, 0 replies; 57+ messages in thread
From: Michael Haggerty @ 2013-10-23 15:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister,
Michael Haggerty
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
remote.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/remote.c b/remote.c
index 5ade07f..ff5b62a 100644
--- a/remote.c
+++ b/remote.c
@@ -829,6 +829,8 @@ static int query_refspecs(struct refspec *refs, int ref_count, struct refspec *q
{
int i;
int find_src = !query->src;
+ const char *needle = find_src ? query->dst : query->src;
+ char **result = find_src ? &query->src : &query->dst;
if (find_src && !query->dst)
return error("query_refspecs: need either src or dst");
@@ -837,8 +839,6 @@ static int query_refspecs(struct refspec *refs, int ref_count, struct refspec *q
struct refspec *refspec = &refs[i];
const char *key = find_src ? refspec->dst : refspec->src;
const char *value = find_src ? refspec->src : refspec->dst;
- const char *needle = find_src ? query->dst : query->src;
- char **result = find_src ? &query->src : &query->dst;
if (!refspec->dst)
continue;
--
1.8.4
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 13/15] builtin/remote.c: reorder function definitions
2013-10-23 15:50 ` [PATCH 00/15] Change semantics of "fetch --tags" Michael Haggerty
` (11 preceding siblings ...)
2013-10-23 15:50 ` [PATCH 12/15] query_refspecs(): move some constants out of the loop Michael Haggerty
@ 2013-10-23 15:50 ` Michael Haggerty
2013-10-23 15:50 ` [PATCH 14/15] builtin/remote.c:update(): use struct argv_array Michael Haggerty
` (2 subsequent siblings)
15 siblings, 0 replies; 57+ messages in thread
From: Michael Haggerty @ 2013-10-23 15:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister,
Michael Haggerty
Reorder function definitions to remove the need for forward
declarations.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
builtin/remote.c | 159 +++++++++++++++++++++++++++----------------------------
1 file changed, 78 insertions(+), 81 deletions(-)
diff --git a/builtin/remote.c b/builtin/remote.c
index 4e14891..ecedd96 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -77,9 +77,6 @@ static const char * const builtin_remote_seturl_usage[] = {
static int verbose;
-static int show_all(void);
-static int prune_remote(const char *remote, int dry_run);
-
static inline int postfixcmp(const char *string, const char *postfix)
{
int len1 = strlen(string), len2 = strlen(postfix);
@@ -1084,6 +1081,64 @@ static int show_push_info_item(struct string_list_item *item, void *cb_data)
return 0;
}
+static int get_one_entry(struct remote *remote, void *priv)
+{
+ struct string_list *list = priv;
+ struct strbuf url_buf = STRBUF_INIT;
+ const char **url;
+ int i, url_nr;
+
+ if (remote->url_nr > 0) {
+ strbuf_addf(&url_buf, "%s (fetch)", remote->url[0]);
+ string_list_append(list, remote->name)->util =
+ strbuf_detach(&url_buf, NULL);
+ } else
+ string_list_append(list, remote->name)->util = NULL;
+ if (remote->pushurl_nr) {
+ url = remote->pushurl;
+ url_nr = remote->pushurl_nr;
+ } else {
+ url = remote->url;
+ url_nr = remote->url_nr;
+ }
+ for (i = 0; i < url_nr; i++)
+ {
+ strbuf_addf(&url_buf, "%s (push)", url[i]);
+ string_list_append(list, remote->name)->util =
+ strbuf_detach(&url_buf, NULL);
+ }
+
+ return 0;
+}
+
+static int show_all(void)
+{
+ struct string_list list = STRING_LIST_INIT_NODUP;
+ int result;
+
+ list.strdup_strings = 1;
+ result = for_each_remote(get_one_entry, &list);
+
+ if (!result) {
+ int i;
+
+ sort_string_list(&list);
+ for (i = 0; i < list.nr; i++) {
+ struct string_list_item *item = list.items + i;
+ if (verbose)
+ printf("%s\t%s\n", item->string,
+ item->util ? (const char *)item->util : "");
+ else {
+ if (i && !strcmp((item - 1)->string, item->string))
+ continue;
+ printf("%s\n", item->string);
+ }
+ }
+ }
+ string_list_clear(&list, 1);
+ return result;
+}
+
static int show(int argc, const char **argv)
{
int no_query = 0, result = 0, query_flag = 0;
@@ -1246,26 +1301,6 @@ static int set_head(int argc, const char **argv)
return result;
}
-static int prune(int argc, const char **argv)
-{
- int dry_run = 0, result = 0;
- struct option options[] = {
- OPT__DRY_RUN(&dry_run, N_("dry run")),
- OPT_END()
- };
-
- argc = parse_options(argc, argv, NULL, options, builtin_remote_prune_usage,
- 0);
-
- if (argc < 1)
- usage_with_options(builtin_remote_prune_usage, options);
-
- for (; argc; argc--, argv++)
- result |= prune_remote(*argv, dry_run);
-
- return result;
-}
-
static int prune_remote(const char *remote, int dry_run)
{
int result = 0, i;
@@ -1304,6 +1339,26 @@ static int prune_remote(const char *remote, int dry_run)
return result;
}
+static int prune(int argc, const char **argv)
+{
+ int dry_run = 0, result = 0;
+ struct option options[] = {
+ OPT__DRY_RUN(&dry_run, N_("dry run")),
+ OPT_END()
+ };
+
+ argc = parse_options(argc, argv, NULL, options, builtin_remote_prune_usage,
+ 0);
+
+ if (argc < 1)
+ usage_with_options(builtin_remote_prune_usage, options);
+
+ for (; argc; argc--, argv++)
+ result |= prune_remote(*argv, dry_run);
+
+ return result;
+}
+
static int get_remote_default(const char *key, const char *value, void *priv)
{
if (strcmp(key, "remotes.default") == 0) {
@@ -1505,64 +1560,6 @@ static int set_url(int argc, const char **argv)
return 0;
}
-static int get_one_entry(struct remote *remote, void *priv)
-{
- struct string_list *list = priv;
- struct strbuf url_buf = STRBUF_INIT;
- const char **url;
- int i, url_nr;
-
- if (remote->url_nr > 0) {
- strbuf_addf(&url_buf, "%s (fetch)", remote->url[0]);
- string_list_append(list, remote->name)->util =
- strbuf_detach(&url_buf, NULL);
- } else
- string_list_append(list, remote->name)->util = NULL;
- if (remote->pushurl_nr) {
- url = remote->pushurl;
- url_nr = remote->pushurl_nr;
- } else {
- url = remote->url;
- url_nr = remote->url_nr;
- }
- for (i = 0; i < url_nr; i++)
- {
- strbuf_addf(&url_buf, "%s (push)", url[i]);
- string_list_append(list, remote->name)->util =
- strbuf_detach(&url_buf, NULL);
- }
-
- return 0;
-}
-
-static int show_all(void)
-{
- struct string_list list = STRING_LIST_INIT_NODUP;
- int result;
-
- list.strdup_strings = 1;
- result = for_each_remote(get_one_entry, &list);
-
- if (!result) {
- int i;
-
- sort_string_list(&list);
- for (i = 0; i < list.nr; i++) {
- struct string_list_item *item = list.items + i;
- if (verbose)
- printf("%s\t%s\n", item->string,
- item->util ? (const char *)item->util : "");
- else {
- if (i && !strcmp((item - 1)->string, item->string))
- continue;
- printf("%s\n", item->string);
- }
- }
- }
- string_list_clear(&list, 1);
- return result;
-}
-
int cmd_remote(int argc, const char **argv, const char *prefix)
{
struct option options[] = {
--
1.8.4
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 14/15] builtin/remote.c:update(): use struct argv_array
2013-10-23 15:50 ` [PATCH 00/15] Change semantics of "fetch --tags" Michael Haggerty
` (12 preceding siblings ...)
2013-10-23 15:50 ` [PATCH 13/15] builtin/remote.c: reorder function definitions Michael Haggerty
@ 2013-10-23 15:50 ` Michael Haggerty
2013-10-23 15:50 ` [PATCH 15/15] fetch, remote: properly convey --no-prune options to subprocesses Michael Haggerty
2013-10-23 16:59 ` [PATCH 00/15] Change semantics of "fetch --tags" Junio C Hamano
15 siblings, 0 replies; 57+ messages in thread
From: Michael Haggerty @ 2013-10-23 15:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister,
Michael Haggerty
Use struct argv_array for calling the "git fetch" subprocesses.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
builtin/remote.c | 33 +++++++++++++++++----------------
1 file changed, 17 insertions(+), 16 deletions(-)
diff --git a/builtin/remote.c b/builtin/remote.c
index ecedd96..bffe2f9 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -6,6 +6,7 @@
#include "strbuf.h"
#include "run-command.h"
#include "refs.h"
+#include "argv-array.h"
static const char * const builtin_remote_usage[] = {
N_("git remote [-v | --verbose]"),
@@ -1376,36 +1377,36 @@ static int update(int argc, const char **argv)
N_("prune remotes after fetching")),
OPT_END()
};
- const char **fetch_argv;
- int fetch_argc = 0;
+ struct argv_array fetch_argv = ARGV_ARRAY_INIT;
int default_defined = 0;
-
- fetch_argv = xmalloc(sizeof(char *) * (argc+5));
+ int retval;
argc = parse_options(argc, argv, NULL, options, builtin_remote_update_usage,
PARSE_OPT_KEEP_ARGV0);
- fetch_argv[fetch_argc++] = "fetch";
+ argv_array_push(&fetch_argv, "fetch");
if (prune)
- fetch_argv[fetch_argc++] = "--prune";
+ argv_array_push(&fetch_argv, "--prune");
if (verbose)
- fetch_argv[fetch_argc++] = "-v";
- fetch_argv[fetch_argc++] = "--multiple";
+ argv_array_push(&fetch_argv, "-v");
+ argv_array_push(&fetch_argv, "--multiple");
if (argc < 2)
- fetch_argv[fetch_argc++] = "default";
+ argv_array_push(&fetch_argv, "default");
for (i = 1; i < argc; i++)
- fetch_argv[fetch_argc++] = argv[i];
+ argv_array_push(&fetch_argv, argv[i]);
- if (strcmp(fetch_argv[fetch_argc-1], "default") == 0) {
+ if (strcmp(fetch_argv.argv[fetch_argv.argc-1], "default") == 0) {
git_config(get_remote_default, &default_defined);
- if (!default_defined)
- fetch_argv[fetch_argc-1] = "--all";
+ if (!default_defined) {
+ argv_array_pop(&fetch_argv);
+ argv_array_push(&fetch_argv, "--all");
+ }
}
- fetch_argv[fetch_argc] = NULL;
-
- return run_command_v_opt(fetch_argv, RUN_GIT_CMD);
+ retval = run_command_v_opt(fetch_argv.argv, RUN_GIT_CMD);
+ argv_array_clear(&fetch_argv);
+ return retval;
}
static int remove_all_fetch_refspecs(const char *remote, const char *key)
--
1.8.4
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 15/15] fetch, remote: properly convey --no-prune options to subprocesses
2013-10-23 15:50 ` [PATCH 00/15] Change semantics of "fetch --tags" Michael Haggerty
` (13 preceding siblings ...)
2013-10-23 15:50 ` [PATCH 14/15] builtin/remote.c:update(): use struct argv_array Michael Haggerty
@ 2013-10-23 15:50 ` Michael Haggerty
2013-10-24 21:17 ` Junio C Hamano
2013-10-23 16:59 ` [PATCH 00/15] Change semantics of "fetch --tags" Junio C Hamano
15 siblings, 1 reply; 57+ messages in thread
From: Michael Haggerty @ 2013-10-23 15:50 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister,
Michael Haggerty
If --no-prune is passed to one of the following commands:
git fetch --all
git fetch --multiple
git fetch --recurse-submodules
git remote update
then it must also be passed to the "fetch" subprocesses that those
commands use to do their work. Otherwise there might be a fetch.prune
or remote.<name>.prune configuration setting that causes pruning to
occur, contrary to the user's express wish.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
builtin/fetch.c | 4 ++--
builtin/remote.c | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 47b63a7..8711df0 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -915,8 +915,8 @@ static void add_options_to_argv(struct argv_array *argv)
{
if (dry_run)
argv_array_push(argv, "--dry-run");
- if (prune > 0)
- argv_array_push(argv, "--prune");
+ if (prune != -1)
+ argv_array_push(argv, prune ? "--prune" : "--no-prune");
if (update_head_ok)
argv_array_push(argv, "--update-head-ok");
if (force)
diff --git a/builtin/remote.c b/builtin/remote.c
index bffe2f9..f532f35 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -1371,7 +1371,7 @@ static int get_remote_default(const char *key, const char *value, void *priv)
static int update(int argc, const char **argv)
{
- int i, prune = 0;
+ int i, prune = -1;
struct option options[] = {
OPT_BOOL('p', "prune", &prune,
N_("prune remotes after fetching")),
@@ -1386,8 +1386,8 @@ static int update(int argc, const char **argv)
argv_array_push(&fetch_argv, "fetch");
- if (prune)
- argv_array_push(&fetch_argv, "--prune");
+ if (prune != -1)
+ argv_array_push(&fetch_argv, prune ? "--prune" : "--no-prune");
if (verbose)
argv_array_push(&fetch_argv, "-v");
argv_array_push(&fetch_argv, "--multiple");
--
1.8.4
^ permalink raw reply related [flat|nested] 57+ messages in thread
* Re: [PATCH 15/15] fetch, remote: properly convey --no-prune options to subprocesses
2013-10-23 15:50 ` [PATCH 15/15] fetch, remote: properly convey --no-prune options to subprocesses Michael Haggerty
@ 2013-10-24 21:17 ` Junio C Hamano
0 siblings, 0 replies; 57+ messages in thread
From: Junio C Hamano @ 2013-10-24 21:17 UTC (permalink / raw)
To: Michael Haggerty
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister
I finished reading thru the remainder and all looked good (again
except minor nits I sent reviews for separately).
Thanks, will queue.
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 00/15] Change semantics of "fetch --tags"
2013-10-23 15:50 ` [PATCH 00/15] Change semantics of "fetch --tags" Michael Haggerty
` (14 preceding siblings ...)
2013-10-23 15:50 ` [PATCH 15/15] fetch, remote: properly convey --no-prune options to subprocesses Michael Haggerty
@ 2013-10-23 16:59 ` Junio C Hamano
15 siblings, 0 replies; 57+ messages in thread
From: Junio C Hamano @ 2013-10-23 16:59 UTC (permalink / raw)
To: Michael Haggerty
Cc: git, Carlos Martín Nieto, Michael Schubert, Johan Herland,
Jeff King, Marc Branchaud, Nicolas Pitre, John Szakmeister
Michael Haggerty <mhagger@alum.mit.edu> writes:
> This is my proposed fix for the "local tag killer" problem that I
> reported recently [1].
>
> There are three main things changed by this patch series:
> ...
Haven't looked at any of the 1-15 messages, but the basic design to
demote "--tags" from being an explicit "refs/tags/*:refs/tags/*"
given from the command line to a more special case option sounds
very sane and solid.
With the auto-following of tags, I think it is a _mistake_ to have
"--tags" anywhere on the command line (and "tagopt" config) these
days, and I do not expect a huge fallout from incompatibility that
arises from the change in behaviour.
Thanks---looking forward to reading it through.
^ permalink raw reply [flat|nested] 57+ messages in thread