Subject: RE: Suggestion: error "tag ... already exists" should distinguish between tagging different or same commit:

From: <[email-masked]>
Date: Mon, 7 Jul 2025 19:12:58 -0400

On July 7, 2025 6:24 PM, Junio C Hamano wrote:
>Junio C Hamano <[email-masked]> writes:
>
>> Or simply something like this.  I am not convinced (yet) that this is
>> a good idea; I merely is showing that the implementation would look
>> like this.
>>
>> ----- >8 -----
>> Subject: tag: allow idempotent "git tag" without "--force"
>>
>> When "git tag T O" is told to create a tag pointing at an object O
>> without the "--force" option, it refuses with "tag T already exists",
>> even when T points at O (which makes it a no-op).
>>
>> Let's allow this "idempotent" case by special casing.
>>
>> Signed-off-by: Junio C Hamano <[email-masked]>
>> ---
>>  builtin/tag.c  |  2 +-
>>  t/t7004-tag.sh | 12 +++++++++---
>>  2 files changed, 10 insertions(+), 4 deletions(-)
>
>As I see nobody biting, I am inclined to say that this is not such a
brilliant idea.  Let's
>chuck it.
>
>>
>> diff --git c/builtin/tag.c w/builtin/tag.c index
>> 4742b27d16..5380a46494 100644
>> --- c/builtin/tag.c
>> +++ w/builtin/tag.c
>> @@ -660,7 +660,7 @@ int cmd_tag(int argc,
>>
>>  	if (refs_read_ref(get_main_ref_store(the_repository), ref.buf,
&prev))
>>  		oidclr(&prev, the_repository->hash_algo);
>> -	else if (!force)
>> +	else if (!force && (create_tag_object || !oideq(&object, &prev)))
>>  		die(_("tag '%s' already exists"), tag);
>>
>>  	opt.message_given = msg.given || msgfile; diff --git
>> c/t/t7004-tag.sh w/t/t7004-tag.sh index 10835631ca..9a253a44a8 100755
>> --- c/t/t7004-tag.sh
>> +++ w/t/t7004-tag.sh
>> @@ -126,7 +126,7 @@ test_expect_success 'annotated tag with
--create-reflog
>has correct message' '
>>  '
>>
>>  test_expect_success '--create-reflog does not create reflog on failure'
'
>> -	test_must_fail git tag --create-reflog mytag &&
>> +	test_must_fail git tag --create-reflog mytag no-such-object &&
>>  	test_must_fail git reflog exists refs/tags/mytag  '
>>
>> @@ -183,8 +183,14 @@ test_expect_success 'listing tags using a
>> non-matching pattern should output not
>>
>>  # special cases for creating tags:
>>
>> -test_expect_success 'trying to create a tag with the name of one
existing should
>fail' '
>> -	test_must_fail git tag mytag
>> +test_expect_success 'recreating a tag without --force' '
>> +	# light-weight tag pointing at the same thing
>> +	# now succeeds
>> +	git tag mytag HEAD &&
>> +	# light-weight tag pointing at a different thing
>> +	test_must_fail git tag mytag HEAD: &&
>> +	# creating annotated tag, pointing at the same object.
>> +	test_must_fail git tag -a -m anno mytag $taggedobject
>>  '
>>
>>  test_expect_success 'trying to create a tag with a non-valid name should
fail' '

Considering that git tag T O will generally require a git push --force and
always a
git pull --force in order to update tags on the upstream and receiving an
update
to the tag locally, I think requiring git tag --force T O when O is
different from the
current tag is a reasonable idea from a consistency standpoint. I do support
the
notion of git tag T O not requiring a --force if O is already where the tag
is
pointing. The only counter case I can really see in this is when -s is used
to allow
the sign to be updated but even then, does --force really change anything
when
only signing (I think not) because O does not change. If O changes when
signing,
I think that --force is almost essential to avoid messing up the signatures.

--Randall