tg-tag.sh: only supply --updateref when dropping @{0}
commit64b2481adce4d3d79216271a27c1ff63f38930f1
authorKyle J. McKay <mackyle@gmail.com>
Mon, 5 Mar 2018 19:05:39 +0000 (5 11:05 -0800)
committerKyle J. McKay <mackyle@gmail.com>
Wed, 7 Mar 2018 22:21:10 +0000 (7 14:21 -0800)
treebd89ee9d39c9d66e17eb7dccfb2934c0570283ed
parente73409387f3275d2d34c070d1afa5dd118aeaa53
tg-tag.sh: only supply --updateref when dropping @{0}

The help warns that dropping the @{0} entry will usually modify
the ref itself.  It does not, however, say anything about dropping
other entries modifying the ref itself!

Therefore do NOT pass the `--updateref` option to `git reflog delete`
unless the "@{0}" entry is being dropped.

Normally this should not matter as Git assumes in many places that
that both of these will return the same value for an existing ref:

    git rev-parse --verify <refname>
    git rev-parse --verify <refname>@{0}

When that's truly the case updating the ref to match the @{0}
entry will have no effect unless the @{0} entry is actually being
dropped.

Actually, the above is a bit misleading because Git ALWAYS returns
the <refname> value whenever <refname>@{0} has been requested even
if the actual @{0} entry in the reflog has a different hash value,
but it still picks up the message from the @{0} entry regardless.
Git will, however, sometimes spit out a warning about the reflog
"unexpectedly ended" when it does this.

Nevertheless, it's trivial to create a reflog for HEAD where the
hash value for <refname> differs from the hash recorded in the
reflog for <refname>@{0} simply by doing this:

    git checkout master
    # this next command will fail if master is a root commit
    git checkout master~
    git symbolic-ref HEAD refs/heads/master

At this point the reflog entry for HEAD@{0} does NOT match the
value for `git rev-parse --verify HEAD`.

Now then after doing this:

    git reflog --rewrite --updateref HEAD@{1}

Git versions prior to 2.4.0 will go ahead and update HEAD to match
the @{0} entry even though HEAD is a symbolic ref thereby stepping
on the actual value of refs/heads/master.

Avoid this possibility by omitting the `--updateref` option unless
it is actually entry @{0} that's being removed AND the refname
being updated is NOT a symbolic ref.

Furthermore, if dropping @{0} results in the ref going away
entirely (i.e. @{0} was the only entry and it was NOT a symbolic
ref) then Git versions prior to 2.4.0 will leave the ref set to
an all 0 hash value.  Add clean up for that case too.

Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
tg-tag.sh