Re: [PATCH v2 12/12] fetch: add a --fetch-prune option and fetch.pruneTags config
- From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- Date
- Jan 22, 2018, 23:48 UTC
- Message-ID
- <87tvvdh2vh.fsf@evledraar.gmail.com>
- In-Reply-To
- <xmqq372xmxcu.fsf@gitster.mtv.corp.google.com>
On Mon, Jan 22 2018, Junio C. Hamano jotted:
Show 41 quoted lines
> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
>> Add a --fetch-prune option to git-fetch, along with fetch.pruneTags
>> config option. This allows for doing any of:
>>
>> git fetch -p -P
>> git fetch --prune --prune-tags
>> git fetch -p -P origin
>> git fetch --prune --prune-tags origin
>>
>> Or simply:
>>
>> git config fetch.prune true &&
>> git config fetch.pruneTags true &&
>> git fetch
>>
>> Instead of the much more verbose:
>>
>> git fetch --prune origin 'refs/tags/*:refs/tags/*' '+refs/heads/*:refs/remotes/origin/*'
>>
>> Before this feature it was painful to support the use-case of pulling
>> from a repo which is having both its branches *and* tags deleted
>> regularly, and wanting our local references to reflect upstream.
>>
>> At work we create deployment tags in the repo for each rollout, and
>> there's *lots* of those, so they're archived within weeks for
>> performance reasons.
>>
>> Without this change it's hard to centrally configure such repos in
>> /etc/gitconfig (on servers that are only used for working with
>> them). You need to set fetch.prune=true globally, and then for each
>> repo:
>>
>> git -C {} config --replace-all remote.origin.fetch "refs/tags/*:refs/tags/*" "^refs/tags/*:refs/tags/*$"
>
> I think the last one is supposed to be a regular expression on
> existing values. Shouldn't the asterisks be quoted?
>
> Otherwise, it would appears as if "refs/tags:refs/tags///" are
> replaced with "refs/tags/*:refs/tags/*", but it certainly is not
> what you are doing.Yes, well spotted. I copied this from an escaped version and forgot to update that escaping. Will fix.
> I also wonder why the existing one does not expect a leading '+', > which I think is what we place by default when you clone.
I didn't raise this because I didn't want to get side-tracked with yet another thing, but it appears to me that a + prefix in tags refspecs does absolutely nothing. Consider on a fresh git.git clobbering the new v2.16.1 tag locally:
$ git tag -a -m"fake" -f v2.16.1 v2.16.0
Updated tag 'v2.16.1' (was eb5fcb24f)This should clobber it, and does:
$ git fetch --prune --dry-run origin '+refs/tags/*:refs/tags/*'
From github.com:git/git
t [tag update] v2.16.1 -> v2.16.1But so will this without +, which seems like a bug to me:
$ git fetch --prune --dry-run origin 'refs/tags/*:refs/tags/*'
From github.com:git/git
t [tag update] v2.16.1 -> v2.16.1But maybe I'm missing something.
Show 9 quoted lines
>> +-P:: >> +--prune-tags:: >> + .... This option is >> + merely a shorthand for providing the explicit tag refspec >> + along with `--prune`, see the discussion about that in its >> + documentation. > > So would "git fetch -P origin" be like "git fetch --prune --tags > origin"?
No, as I understand it --tags just has the effect of considering remote tags that aren't tags of the branches you're fetching, so e.g. on a fresh git.git:
$ git tag -a -m"fake" -f v2.16.2 v2.16.0
$ git fetch --prune --tags --dry-run
$I.e. it does nothing. Whereas this will prune the new fake tag:
$ git fetch --prune origin 'refs/tags/*:refs/tags/*'
From github.com:git/git
- [deleted] (none) -> v2.16.2And so does the --prune-tags option:
$ ~/g/git/git-fetch --prune --prune-tags origin
From github.com:git/git
- [deleted] (none) -> v2.16.2Show 45 quoted lines
>> + >> See the PRUNING section below for more details. >> >> diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt >> index 18fac0da2e..5682ed4ae1 100644 >> --- a/Documentation/git-fetch.txt >> +++ b/Documentation/git-fetch.txt >> @@ -148,6 +148,30 @@ So be careful when using this with a refspec like >> `refs/tags/*:refs/tags/*`, or any other refspec which might map >> references from multiple remotes to the same local namespace. >> >> +Since keeping up-to-date with both branches and tags on the remote is >> +a common use-case the `--prune-tags` option can be supplied along with >> +`--prune` to prune local tags that don't exist on the remote. Tag >> +pruning can also be enabled with `fetch.pruneTags` or >> +`remote.<name>.pruneTags` in the config. See linkgit:git-config[1]. >> + >> +The `--prune-tags` option is equivalent to having >> +`refs/tags/*:refs/tags/*` configured in the refspecs for the >> +remote. This can lead to some seemingly strange interactions: >> + >> +------------------------------------------------ >> +# These both fetch tags >> +$ git fetch --no-tags origin 'refs/tags/*:refs/tags/*' >> +$ git fetch --no-tags --prune-tags origin >> +------------------------------------------------ > > This description is too confusing. First you say "having > ... configured in the refspecs for the remote", but configured > refspecs for the remote (I presume that you are missing 'fetch' from > that description and are talking about the "remote.$name.fetch" > configuration variable) are overridden when you give explicit > refspecs from the command line, so the above two are not even > equivalent. The first one gives a refspec explicitly from the > command line, so other configured refspecs like > > [remote "origin"] fetch = +refs/heads/*:refs/remotes/origin/* > > should be ignored, while the second one, if --prune-tags tells Git > to behave as if > > [remote "origin"] fetch = refs/tags/*:refs/tags/* > > also exists in the config, would not cause other ones for the same > remote from getting ignored. So...
Indeed, I'll reword this. FWIW I meant something closer to "declared in the refspecs of the remote" not "configured ... remote".