Well gosh, how did THAT happen?
Someone used a bad version of Git (or a bad tool to build Git objects). Who, when, how, etc., are not possible to say, but if you examine the various bad commits, that will probably offer some very big clues, since the bad lines should have this general form:
author A U Thor <[email protected]> 1575578639 -0800
or:
committer A U Thor <[email protected]> 1575578639 -0800
The date-and-time-stamp are the last two numeric fields. The stuff in between will likely tell you who to ask what Git version they were using.
I have no idea how to even begin to fix that.
Technically, you can't fix the bad commits themselves. The reason is that, bad or not, the raw data in the commit is the source of the hash ID of the commit. Since the hash ID is the real name of the commit, the real name of the commit requires that the commit's data be bad. If you did fix them, they would become different commits, which would have different hash-ID-names.
As VonC said, to produce a new, incompatible, but corrected repository, you must replace each of these bad commits with new-and-improved ones, perhaps using git filter-branch
or the new git filter-repo
. Whatever tool or method you use, you'll need to provide some way for replacing the bad author
and/or committer
lines in the commit headers of the bad commits, with new correct lines—date-and-time stamps that meet Git's internal requirements.
Having replaced the bad commits with corrected ones, you must now also replace every subsequent (descendant) commit, because the immediate children of these commits store their parent hash IDs (those of the bad commits) inside them as part of their data. So you must write up a new corrected child commit that preserves everything except the parent hash ID. That invalidates the child commit's children, so those too must be rewritten, and so on: all descendant commits.
This is just what these filter-branch / filter-repo tools do. You (somehow) pick out a bad commit in the repository, and they copy it to a new-and-improved commit instead. Then they copy all descendants of the original bad commit as well, so that there is a new family tree descending from the corrected commit.
Since the set of commits in a repository is the history in that repository, the result of copying all of these commits is a whole new history—a new repository, that all users of the old repository must now switch over to use. Hence the technical part of correcting the repository is usually the easiest part of this whole process. It takes some work to figure out what's wrong and how to use the tools to rewrite history, but you do that once and you're done. But then you must track down every user of the old repository and somehow convince them to stop using that one and start using the new and improved one instead.