public inbox for git@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] fetch: clobber existing tags with --prune-tags
@ 2026-02-15 20:23 Orgad Shaneh via GitGitGadget
  2026-02-15 20:23 ` [PATCH 1/2] fetch: add a test for --force flag Orgad Shaneh via GitGitGadget
  2026-02-15 20:23 ` [PATCH 2/2] fetch: clobber existing tags with --prune-tags Orgad Shaneh via GitGitGadget
  0 siblings, 2 replies; 6+ messages in thread
From: Orgad Shaneh via GitGitGadget @ 2026-02-15 20:23 UTC (permalink / raw)
  To: git; +Cc: Orgad Shaneh

This was documented but not implemented.

In the flag description: prune local tags no longer on remote and clobber
changed tags

In the documentation: ... to prune local tags that don't exist on the
remote, and force-update those tags that differ.

Orgad Shaneh (2):
  fetch: add a test for --force flag
  fetch: clobber existing tags with --prune-tags

 builtin/fetch.c       |  2 +-
 t/t5516-fetch-push.sh | 13 +++++++++++--
 2 files changed, 12 insertions(+), 3 deletions(-)


base-commit: 852829b3dd2fe4e7c7fc4d8badde644cf1b66c74
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2200%2Forgads%2Ffetch-prune-clobber-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2200/orgads/fetch-prune-clobber-v1
Pull-Request: https://github.com/git/git/pull/2200
-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/2] fetch: add a test for --force flag
  2026-02-15 20:23 [PATCH 0/2] fetch: clobber existing tags with --prune-tags Orgad Shaneh via GitGitGadget
@ 2026-02-15 20:23 ` Orgad Shaneh via GitGitGadget
  2026-02-15 20:23 ` [PATCH 2/2] fetch: clobber existing tags with --prune-tags Orgad Shaneh via GitGitGadget
  1 sibling, 0 replies; 6+ messages in thread
From: Orgad Shaneh via GitGitGadget @ 2026-02-15 20:23 UTC (permalink / raw)
  To: git; +Cc: Orgad Shaneh, Orgad Shaneh

From: Orgad Shaneh <orgad.shaneh@audiocodes.com>

There are two ways to force-fetch tags that have changed: either by
specifying an explicit forced ref (+refs/tags/*:refs/tags/*), or by
using --force.

The first approach was already tested, but the second was not. This
has now been addressed.

Signed-off-by: Orgad Shaneh <orgad.shaneh@audiocodes.com>
---
 t/t5516-fetch-push.sh | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 29e2f17608..31df7faf56 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -1105,7 +1105,10 @@ test_force_fetch_tag () {
 			git commit -m 'file1' &&
 			git tag $tag_args testTag &&
 			test_must_fail git -C ../child1 fetch origin tag testTag &&
-			git -C ../child1 fetch origin '+refs/tags/*:refs/tags/*'
+			git -C ../child1 fetch origin '+refs/tags/*:refs/tags/*' &&
+			git tag $tag_args testTag HEAD^ &&
+			test_must_fail git -C ../child1 fetch origin tag testTag &&
+			git -C ../child1 fetch --force origin tag testTag
 		)
 	"
 }
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/2] fetch: clobber existing tags with --prune-tags
  2026-02-15 20:23 [PATCH 0/2] fetch: clobber existing tags with --prune-tags Orgad Shaneh via GitGitGadget
  2026-02-15 20:23 ` [PATCH 1/2] fetch: add a test for --force flag Orgad Shaneh via GitGitGadget
@ 2026-02-15 20:23 ` Orgad Shaneh via GitGitGadget
  2026-03-18  8:27   ` Orgad Shaneh
  2026-03-21 18:26   ` Junio C Hamano
  1 sibling, 2 replies; 6+ messages in thread
From: Orgad Shaneh via GitGitGadget @ 2026-02-15 20:23 UTC (permalink / raw)
  To: git; +Cc: Orgad Shaneh, Orgad Shaneh

From: Orgad Shaneh <orgad.shaneh@audiocodes.com>

This was documented but not implemented.

In the flag description:
prune local tags no longer on remote *and clobber changed tags*

In the documentation:
... to prune local tags that don't exist on the remote, *and
force-update those tags that differ*.

Signed-off-by: Orgad Shaneh <orgad.shaneh@audiocodes.com>
---
 builtin/fetch.c       |  2 +-
 t/t5516-fetch-push.sh | 10 ++++++++--
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/builtin/fetch.c b/builtin/fetch.c
index a3bc7e9380..c212f50b86 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -981,7 +981,7 @@ static int update_local_ref(struct ref *ref,
 	    starts_with(ref->name, "refs/tags/")) {
 		struct ref_update_display_info *info;
 
-		if (force || ref->force) {
+		if (force || ref->force || prune_tags) {
 			int r;
 
 			r = s_update_ref("updating tag", ref, transaction, 0);
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 31df7faf56..4d29043baf 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -1092,7 +1092,7 @@ test_force_fetch_tag () {
 	tag_type_description=$1
 	tag_args=$2
 
-	test_expect_success "fetch will not clobber an existing $tag_type_description without --force" "
+	test_expect_success "fetch will not clobber an existing $tag_type_description without --force or --prune-tags" "
 		mk_test testrepo heads/main &&
 		mk_child testrepo child1 &&
 		mk_child testrepo child2 &&
@@ -1108,7 +1108,13 @@ test_force_fetch_tag () {
 			git -C ../child1 fetch origin '+refs/tags/*:refs/tags/*' &&
 			git tag $tag_args testTag HEAD^ &&
 			test_must_fail git -C ../child1 fetch origin tag testTag &&
-			git -C ../child1 fetch --force origin tag testTag
+			git -C ../child1 fetch --force origin tag testTag &&
+			git tag $tag_args testTag HEAD &&
+			test_must_fail git -C ../child1 fetch origin tag testTag &&
+			git -C ../child1 fetch --prune-tags origin tag testTag &&
+			git tag $tag_args testTag HEAD^ &&
+			test_must_fail git -C ../child1 fetch origin tag testTag &&
+			git -C ../child1 -c fetch.prunetags=true fetch origin tag testTag
 		)
 	"
 }
-- 
gitgitgadget

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/2] fetch: clobber existing tags with --prune-tags
  2026-02-15 20:23 ` [PATCH 2/2] fetch: clobber existing tags with --prune-tags Orgad Shaneh via GitGitGadget
@ 2026-03-18  8:27   ` Orgad Shaneh
  2026-03-21 18:26   ` Junio C Hamano
  1 sibling, 0 replies; 6+ messages in thread
From: Orgad Shaneh @ 2026-03-18  8:27 UTC (permalink / raw)
  To: Orgad Shaneh via GitGitGadget; +Cc: git, Orgad Shaneh

On Sun, Feb 15, 2026 at 10:23 PM Orgad Shaneh via GitGitGadget
<gitgitgadget@gmail.com> wrote:
>
> From: Orgad Shaneh <orgad.shaneh@audiocodes.com>
>
> This was documented but not implemented.
>
> In the flag description:
> prune local tags no longer on remote *and clobber changed tags*
>
> In the documentation:
> ... to prune local tags that don't exist on the remote, *and
> force-update those tags that differ*.
>
> Signed-off-by: Orgad Shaneh <orgad.shaneh@audiocodes.com>
> ---
>  builtin/fetch.c       |  2 +-
>  t/t5516-fetch-push.sh | 10 ++++++++--
>  2 files changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/builtin/fetch.c b/builtin/fetch.c
> index a3bc7e9380..c212f50b86 100644
> --- a/builtin/fetch.c
> +++ b/builtin/fetch.c
> @@ -981,7 +981,7 @@ static int update_local_ref(struct ref *ref,
>             starts_with(ref->name, "refs/tags/")) {
>                 struct ref_update_display_info *info;
>
> -               if (force || ref->force) {
> +               if (force || ref->force || prune_tags) {
>                         int r;
>
>                         r = s_update_ref("updating tag", ref, transaction, 0);
> diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
> index 31df7faf56..4d29043baf 100755
> --- a/t/t5516-fetch-push.sh
> +++ b/t/t5516-fetch-push.sh
> @@ -1092,7 +1092,7 @@ test_force_fetch_tag () {
>         tag_type_description=$1
>         tag_args=$2
>
> -       test_expect_success "fetch will not clobber an existing $tag_type_description without --force" "
> +       test_expect_success "fetch will not clobber an existing $tag_type_description without --force or --prune-tags" "
>                 mk_test testrepo heads/main &&
>                 mk_child testrepo child1 &&
>                 mk_child testrepo child2 &&
> @@ -1108,7 +1108,13 @@ test_force_fetch_tag () {
>                         git -C ../child1 fetch origin '+refs/tags/*:refs/tags/*' &&
>                         git tag $tag_args testTag HEAD^ &&
>                         test_must_fail git -C ../child1 fetch origin tag testTag &&
> -                       git -C ../child1 fetch --force origin tag testTag
> +                       git -C ../child1 fetch --force origin tag testTag &&
> +                       git tag $tag_args testTag HEAD &&
> +                       test_must_fail git -C ../child1 fetch origin tag testTag &&
> +                       git -C ../child1 fetch --prune-tags origin tag testTag &&
> +                       git tag $tag_args testTag HEAD^ &&
> +                       test_must_fail git -C ../child1 fetch origin tag testTag &&
> +                       git -C ../child1 -c fetch.prunetags=true fetch origin tag testTag
>                 )
>         "
>  }
> --
> gitgitgadget

Gently pinging this thread. I submitted this patch about a month ago
and would appreciate any feedback once someone finds a moment to
review it.

Thanks!

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/2] fetch: clobber existing tags with --prune-tags
  2026-02-15 20:23 ` [PATCH 2/2] fetch: clobber existing tags with --prune-tags Orgad Shaneh via GitGitGadget
  2026-03-18  8:27   ` Orgad Shaneh
@ 2026-03-21 18:26   ` Junio C Hamano
  2026-03-26  7:57     ` Orgad Shaneh
  1 sibling, 1 reply; 6+ messages in thread
From: Junio C Hamano @ 2026-03-21 18:26 UTC (permalink / raw)
  To: Orgad Shaneh via GitGitGadget
  Cc: git, Ævar Arnfjörð Bjarmason, Orgad Shaneh,
	Orgad Shaneh

"Orgad Shaneh via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Orgad Shaneh <orgad.shaneh@audiocodes.com>
>
> This was documented but not implemented.

And instead what did the command do / how did the command behave?

It also is curious when it was "broken".  It could be that it was
broken from day one when 97716d21 (fetch: add a --prune-tags option
and fetch.pruneTags config, 2018-02-09) was written, c1a7902f (Merge
branch 'ab/fetch-prune', 2018-03-06) merged it, and Git 2.17 was
shipped with it, but knowing Ævar (by the way where is he these
days???), I somehow doubt it.

And unless it was broken from day one, we must find out if the
change in behaviour was deliberate, in which case it would be the
doucmentation and not the implementation that needs fixing.

> In the flag description:
> prune local tags no longer on remote *and clobber changed tags*
>
> In the documentation:
> ... to prune local tags that don't exist on the remote, *and
> force-update those tags that differ*.
> ...
> diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
> index 31df7faf56..4d29043baf 100755
> --- a/t/t5516-fetch-push.sh
> +++ b/t/t5516-fetch-push.sh
> @@ -1092,7 +1092,7 @@ test_force_fetch_tag () {
>  	tag_type_description=$1
>  	tag_args=$2
>  
> -	test_expect_success "fetch will not clobber an existing $tag_type_description without --force" "
> +	test_expect_success "fetch will not clobber an existing $tag_type_description without --force or --prune-tags" "
>  		mk_test testrepo heads/main &&
>  		mk_child testrepo child1 &&
>  		mk_child testrepo child2 &&
> @@ -1108,7 +1108,13 @@ test_force_fetch_tag () {
>  			git -C ../child1 fetch origin '+refs/tags/*:refs/tags/*' &&
>  			git tag $tag_args testTag HEAD^ &&
>  			test_must_fail git -C ../child1 fetch origin tag testTag &&
> -			git -C ../child1 fetch --force origin tag testTag
> +			git -C ../child1 fetch --force origin tag testTag &&
> +			git tag $tag_args testTag HEAD &&
> +			test_must_fail git -C ../child1 fetch origin tag testTag &&
> +			git -C ../child1 fetch --prune-tags origin tag testTag &&
> +			git tag $tag_args testTag HEAD^ &&
> +			test_must_fail git -C ../child1 fetch origin tag testTag &&
> +			git -C ../child1 -c fetch.prunetags=true fetch origin tag testTag
>  		)
>  	"
>  }

None of the steps we see in the added test do not seem to check that
--prune-tags does clobber existing tag that no longer exists on the
other side.  It only checks the "git fetch" command exits with
status 0, but does not see if the tag actually went away after the
operation is done.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/2] fetch: clobber existing tags with --prune-tags
  2026-03-21 18:26   ` Junio C Hamano
@ 2026-03-26  7:57     ` Orgad Shaneh
  0 siblings, 0 replies; 6+ messages in thread
From: Orgad Shaneh @ 2026-03-26  7:57 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Orgad Shaneh via GitGitGadget, git,
	Ævar Arnfjörð Bjarmason, Orgad Shaneh

On Sat, Mar 21, 2026 at 8:27 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> "Orgad Shaneh via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
> > From: Orgad Shaneh <orgad.shaneh@audiocodes.com>
> >
> > This was documented but not implemented.
>
> And instead what did the command do / how did the command behave?

Even when passing --prune-tags or setting fetch.pruneTags, git fetch
fails to force-update tags, resulting in the following error:

! [rejected]        testTag    -> testTag  (would clobber existing tag)

Furthermore, when a tag clobber is rejected, the entire fetch operation
fails, preventing the update of other refs and even new tags.

> It also is curious when it was "broken".  It could be that it was
> broken from day one when 97716d21 (fetch: add a --prune-tags option
> and fetch.pruneTags config, 2018-02-09) was written, c1a7902f (Merge
> branch 'ab/fetch-prune', 2018-03-06) merged it, and Git 2.17 was
> shipped with it, but knowing Ævar (by the way where is he these
> days???), I somehow doubt it.
>
> And unless it was broken from day one, we must find out if the
> change in behaviour was deliberate, in which case it would be the
> doucmentation and not the implementation that needs fixing.

I dug into the feature history and found:
1. The flag was added in 97716d21 (fetch: add a --prune-tags option
   and fetch.pruneTags config, 2018-02-09) as you mentioned.
2. Tag clobbering protection was added later in 0bc8d71b (fetch: stop
   clobbering existing tags without --force, 2018-08-31).

It appears the --prune-tags flag was overlooked in that later commit,
either in its behavior or its documentation.

Since there is currently no way to suppress this error globally, if you
consider the current behavior acceptable and prefer to fix the
documentation, I suggest adding a fetch.force config to allow clobbering.

> >                       git -C ../child1 fetch origin '+refs/tags/*:refs/tags/*' &&
> >                       git tag $tag_args testTag HEAD^ &&
> >                       test_must_fail git -C ../child1 fetch origin tag testTag &&
> > -                     git -C ../child1 fetch --force origin tag testTag
> > +                     git -C ../child1 fetch --force origin tag testTag &&
> > +                     git tag $tag_args testTag HEAD &&
> > +                     test_must_fail git -C ../child1 fetch origin tag testTag &&
> > +                     git -C ../child1 fetch --prune-tags origin tag testTag &&
> > +                     git tag $tag_args testTag HEAD^ &&
> > +                     test_must_fail git -C ../child1 fetch origin tag testTag &&
> > +                     git -C ../child1 -c fetch.prunetags=true fetch origin tag testTag
> >               )
> >       "
> >  }
>
> None of the steps we see in the added test do not seem to check that
> --prune-tags does clobber existing tag that no longer exists on the
> other side.  It only checks the "git fetch" command exits with
> status 0, but does not see if the tag actually went away after the
> operation is done.

In these tests, the tag is being replaced rather than deleted. Existing
tests for the pruning mechanism itself are located in t/t5510-fetch.sh.

Would you like me to add a check for the tag content itself to verify
the update? I suppose I should do the same for the existing test cases
in that block as well.

- Orgad

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-03-26  7:57 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-15 20:23 [PATCH 0/2] fetch: clobber existing tags with --prune-tags Orgad Shaneh via GitGitGadget
2026-02-15 20:23 ` [PATCH 1/2] fetch: add a test for --force flag Orgad Shaneh via GitGitGadget
2026-02-15 20:23 ` [PATCH 2/2] fetch: clobber existing tags with --prune-tags Orgad Shaneh via GitGitGadget
2026-03-18  8:27   ` Orgad Shaneh
2026-03-21 18:26   ` Junio C Hamano
2026-03-26  7:57     ` Orgad Shaneh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox