[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Fixing problems reported by "git fsck"
From: |
Shahab Vahedi |
Subject: |
Fixing problems reported by "git fsck" |
Date: |
Thu, 30 Nov 2023 18:38:15 +0000 |
TL;DR;
There are problems in internal structure of DejaGnu's git repo. A
POSIX shell script is proposed at the end of this message that fixes
them. During this fix, no commit is touched, so the history remains
intact. Please continue reading for further details.
I have cloned DejaGnu's codebase from the official repo. When I
wanted to push it to a Github account, it got rejected. I looked
further into the matter and noticed that "git fsck" is detecting
some errors in the repo:
----------------------------------------------------------------------
$ git --version
git version 2.42.0
$ git clone git://git.sv.gnu.org/dejagnu.git
$ cd dejagnu
$ git fsck
error in tag 0d2d0605443b24b470155111fc695a73c962173f:
missingSpaceBeforeDate: invalid author/committer line
- missing space before date
error in tag acdc1784d37050d3945c8fb5258fc0e50cbc40db:
[ditto]
error in tag 94fbb053f944416569221e1de7ff91fd48e6ebde:
[ditto]
error in tag 4dbe11b30f3e573058f30664e70ee08b56ef5292:
[ditto]
error in tag ca14993ef275ae7d0f0218ef59048373ee6dfe18:
[ditto]
----------------------------------------------------------------------
According to Git's fsck, there are 5 corrupted tag objects. Let's
check which tags they are exactly:
----------------------------------------------------------------------
$ git for-each-ref | grep "refs/tags"
0d2d0605443b24b470155... tag refs/tags/dejagnu-1.4.1-release
acdc1784d37050d3945c8... tag refs/tags/dejagnu-1.4.2-release
94fbb053f944416569221... tag refs/tags/dejagnu-1.4.3-release
4dbe11b30f3e573058f30... tag refs/tags/dejagnu-1.4.4-release
...
ca14993ef275ae7d0f021... tag refs/tags/from-devo
...
----------------------------------------------------------------------
And inspecting them, say the second one (acdc178), reveals:
----------------------------------------------------------------------
$ git show acdc178 | head
tag release_1_4_2 ---> The tag is called "release_1_4_2",
while the name is "dejagnu-1.4.2-release"
(cross checked with "git for-each-ref").
Tagger: Rob Savoye <rob@welcomehome.org>
Date: Thu Jan 1 00:00:00 1970 +0000
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
`--> epoch time!
commit 56a71936f9f95d480cfca7766df89e73f200d081
Author: Rob Savoye <rob@welcomehome.org>
Date: Thu Sep 13 02:34:49 2001 +0000
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
`--> commit date (good candidate).
Change the version number to 1.4.2.
----------------------------------------------------------------------
The date property of the tag is not correct.
DejaGnu is not the first software project that suffers from this.
Apparently, the same problem was observed in X.org repo. In this blog
post [1] a plausible solution was discussed.
[1] Pushing X.org Git repos to Github et al.
https://sunweavers.net/blog/node/36
The idea is to remove the faulty tags and replace them with new ones
that has the same property plus the date coming from the commit that
they point to. The proposed script did not work out of the box in
DejaGnu's case and needed to be adjusted. I couldn't have done this
without the help of "osse" in #git IRC channel on LiberaChat.
Finally the POSIX shell script:
----------------------------------------------------------------------
#! /bin/sh
# shellcheck disable=SC2250
set -e
git fsck 2>&1 |
grep "error in tag" |
sed -r -e "s/error in tag ([0-9a-f]+):.*/\1/" |
while read -r broken
do
# extracting tag info: ID, commit it points to, name, and the message
tag=$(git cat-file tag "$broken" | sed -n 's/^tag //p')
commit=$(git rev-parse "$broken^{commit}")
tag_name=$(git for-each-ref | grep "$broken" | cut -d '/' -f 3)
tag_msg=$(git cat-file tag "$broken" | sed -n '/^$/,$p' | tail -n +2)
# print the tag SHA1 and its ID (not the same as its name)
echo; echo "$broken -- $tag"
# rebuild the information for the "git tag" command ensuing
GIT_COMMITTER_NAME=$(git log -1 --format='%cn' "$commit")
GIT_COMMITTER_EMAIL=$(git log -1 --format='%ce' "$commit")
GIT_COMMITTER_DATE=$(git log -1 --format='%cD' "$commit")
export GIT_COMMITTER_NAME
export GIT_COMMITTER_EMAIL
export GIT_COMMITTER_DATE
git tag -d "$tag_name" # without this, the faulty $tag won't go away.
git tag -a -f -m "$tag_msg" "$tag_name" "$commit"
done
echo
# drop all old content...
git reflog expire --expire=all --all
git gc --prune=all
# no more errors should be reported...
git fsck
----------------------------------------------------------------------
Caveat Emptor: I'm not sure of the impact of "git gc --prune=all" on
DejaGnu's code base as it has some branches. So please double check
that doesn't remove things that it shouldn't.
Cheers,
Shahab