I have Git configured to record reflogs for all refs:
$ git config core.logallrefupdates
always
And this works. Including recording the reflog for annotated tags. But
git reflog
does not give any output if the ref points to an annotated
tag:
$ git reflog anno1
<no output>
However it works for lightweight tags. Supposedly because the lightweight tag points directly to a commit (unlike an annotated tag which points to a tag object).
It would be nice to get the reflog for the annotated tag in case I want
to “reset” (git tag --force […]
) to a previous state.
I can print the reflog file directly like this:
cat .git/logs/refs/tags/anno1
But I don’t see a way to do it with some git(1) command.
By testing the behavior of "git tag" followed by "git reflog":
# setup:
git init
git config core.logallrefupdates always
echo "aaa" > a.txt && git add . && git commit -m "a.txt"
echo "bbb" > b.txt && git add . && git commit -m "b.txt"
echo "ccc" > c.txt && git add . && git commit -m "c.txt"
echo "ddd" > d.txt && git add . && git commit -m "d.txt"
git log --oneline
# 0bd20d6 (HEAD -> master) d.txt
# ffd5ae1 c.txt
# 4fcdb8c b.txt
# ab28d11 a.txt
# testing behavior of tag + reflog:
git tag foo HEAD~3 # 'foo' is a lightweight tag to a commit
git reflog foo
# ab28d11 (tag: foo) refs/tags/foo@{0}: tag: tagging ab28d11 (a.txt, 2024-10-29)
git tag --force foo -m "annotated" HEAD~2 # 'foo' is now an annotated tag
git reflog foo
# no output
git tag --force foo HEAD~1 # 'foo' is a lightweight tag to a commit again
git reflog foo
# ffd5ae1 (tag: foo) refs/tags/foo@{0}: tag: tagging ffd5ae1 (c.txt, 2024-10-29) # note the foo@{0} and foo@{2}:
# ab28d11 refs/tags/foo@{2}: tag: tagging ab28d11 (a.txt, 2024-10-29) # only commits (the steps when 'foo' is a lightweight tag to a commit) are reported
git tag --force foo -m "annotated" HEAD # 'foo' is an annotated tag again
git reflog foo
# no output
cat .git/logs/refs/tags/foo # even though all changes are correctly recorded in the log
# 0000000000000000000000000000000000000000 ab28d1107a0c2ee820d0952caed5830ac53da724 LeGEC <my@e.mail> 1730172212 +0200 tag: tagging ab28d11 (a.txt, 2024-10-29)
# ab28d1107a0c2ee820d0952caed5830ac53da724 4c248a3ad8933e0b16c97610b9ab664f30e2fe45 LeGEC <my@e.mail> 1730172222 +0200 tag: tagging 4fcdb8c (b.txt, 2024-10-29)
# 4c248a3ad8933e0b16c97610b9ab664f30e2fe45 ffd5ae198cbcc9eae8cf6a26ce72229aa9770f0e LeGEC <my@e.mail> 1730172241 +0200 tag: tagging ffd5ae1 (c.txt, 2024-10-29)
# ffd5ae198cbcc9eae8cf6a26ce72229aa9770f0e 14c9592ed9737d98ba6460bc37a3b9741342b944 LeGEC <my@e.mail> 1730172255 +0200 tag: tagging 0bd20d6 (d.txt, 2024-10-29)
# for completion: check what happens when the tag points to a blob or tree:
git tag -f foo HEAD~1:c.txt # 'foo' now tags a blob
git reflog foo
# no output
git tag -f foo HEAD~1: # 'foo' now points to a tree
git cat-file -t foo
# tree
git reflog foo
# no output
cat .git/logs/refs/tags/foo # again: all changes are recorded in the log
# 0000000000000000000000000000000000000000 ab28d1107a0c2ee820d0952caed5830ac53da724 LeGEC <my@e.mail> 1730172212 +0200 tag: tagging ab28d11 (a.txt, 2024-10-29)
# ab28d1107a0c2ee820d0952caed5830ac53da724 4c248a3ad8933e0b16c97610b9ab664f30e2fe45 LeGEC <my@e.mail> 1730172222 +0200 tag: tagging 4fcdb8c (b.txt, 2024-10-29)
# 4c248a3ad8933e0b16c97610b9ab664f30e2fe45 ffd5ae198cbcc9eae8cf6a26ce72229aa9770f0e LeGEC <my@e.mail> 1730172241 +0200 tag: tagging ffd5ae1 (c.txt, 2024-10-29)
# ffd5ae198cbcc9eae8cf6a26ce72229aa9770f0e 14c9592ed9737d98ba6460bc37a3b9741342b944 LeGEC <my@e.mail> 1730172255 +0200 tag: tagging 0bd20d6 (d.txt, 2024-10-29)
# 14c9592ed9737d98ba6460bc37a3b9741342b944 b2a7546679fdf79ca0eb7bfbee1e1bb342487380 LeGEC <my@e.mail> 1730172610 +0200 tag: tagging b2a7546 (blob object)
# b2a7546679fdf79ca0eb7bfbee1e1bb342487380 15b6c2b4cbb04ddb97da706346ed34086664309d LeGEC <my@e.mail> 1730172731 +0200 tag: tagging 15b6c2b (tree object)
it is pretty obvious that git reflog
currently only deals with commit
objects.
It turns out that, when the current value of a tag isn't a commit (e.g: when the tag isn't a lightweight tag to a commit), git reflog
won't even display the history of that ref ;
and when it does display the history, only commits are displayed.