That is not what anyone means when they talk about immutable objects or refs in Git. I can delete a commit from `.git` but they are still considered immutable.
A branch is mutable since you can push it forward without `--force` as long as the current commit becomes an ancestor of the next tip. Can you change a remote tag without `--force`? I don't know off the top of my head. But I doubt it.
To /tmp/foo1/
! [rejected] ddd -> ddd (already exists)
error: failed to push some refs to '/tmp/foo1/'
hint: Updates were rejected because the tag already exists in the remote.
I think any ref is 'mutable' by these standards, and any hash is immutable (that's the entire point of a hash).
If you don't know, maybe you could give me the benefit of the doubt?
In any case, the syntax to delete a remote tag is just e.g.
$ git push origin :mytag
After that you are free to push a new tag to replace the old, with no warnings or --force flags.
When we use a tag to specify the version of a dependency, we trust the maintainer not to do this. If we don't have that level of trust we can use SHA1's instead. We should not pretend that there is anything in git that tries to prevent a tag from being rewritten by someone who wants to.
You can delete a random commit, but if anyone references it transitively, it'll immediately detect that breakage. E.g. you can't modify or remove commits "in the past" on your main branch. And "moving" a commit creates a new commit, with a different sha.
Tags do not do that. Moving or removing a tag retains no history about the move, nor is the old value left hanging around somewhere (after pruning), nor will anyone who had not yet pulled the tag notice the removal, as with branches. Most configs will complain about the tag disappearing or moving, as with branches, but that depends on your config and the command you ran.
(annotated tags do have their own sha and creation date and whatnot, which is great, but next to nothing references them. and removing them from a commit leaves no evidence that it ever was on that commit, as the commit is unmodified)
> Most configs will complain about the tag disappearing or moving, as with branches, but that depends on your config and the command you ran.
Needing `--force` with a default setup is literally all I meant by "immutable", apparently a cursed word in this context (the tip of a branch is supposed to be able to move in that common-history sense of movement). Gawd.
annotated tags are immutable, they're part of the history that makes up the sha.
normal tags are just labels that can be changed or deleted at will. removing a normal/lightweight tag from history doesn't change any commits and doesn't require a force push.
that is why the article recommends annotated tags. you have to force push to rewrite those. then the git describe tags based on those will be immutable unless someone goes out of their way to rewrite history.
Annotated tags affect their own sha (because they actually have one, non-annotated tags do not), but they don't affect the commit you tag in any way. Otherwise you wouldn't be able to add them at a later date - it'd change that commit's sha.
If you move a tag, annotated or no, the .git/refs/tags/x file will contain the new sha it points to... but the history of that `x` is not stored anywhere. The fact that it used to point to [old sha] is gone for good, and the old sha will eventually get garbage collected (via pruning), just like if you remove a branch.
Oh that's weird, I always thought the next commit would have its gitsha affected by the annotated tag and you couldn't just delete it, but I just tried that and it deleted fine...
Now I'm not sure what the point is of annotated tags other than the default git describe behavior.
Everyone else can enjoy Cunningham's Law working like a charm.
I think it's at least partly for providing a storage location for after-commit release signatures. You can't modify the commit to add the release-signer signature, and many things will want direct access to it, so you need/want a publicly-identifiable commit-pointer of some kind: tags.
Off at the less-structured side of things though, have you seen git notes? You can add notes to any commit: https://git-scm.com/docs/git-notes . Tags are kinda just notes with a display name.
At times I've wished that code review feedback were just stored in notes, so it'd survive changing hosting systems... but they're not quite reasonable for that :| What I think I really want is a notes tree under any commit, which kinda exists since you can add notes to notes, but there isn't really enough structure or tooling to support that kind of use out-of-the-box.