我有一个现有的私有 git 存储库(有两个分支),托管在 GitHub 上。我打算将其公开,但不想公开作者的电子邮件地址。因此,计划是通过将 替换 来重写提交历史,<old-author-email>
并<new-author-email>
重新签署提交。另外,我想保留时间戳(这对我很重要!)。
因此,基于广泛的研究,我提出了以下步骤:
- 在我的本地机器上克隆存储库。
- 创建一个 python-3.x 虚拟环境,并运行
pip install git-filter-repo
。(来源) .mailmap
在存储库中创建一个文件WORKING_DIR
,其中包含电子邮件重新映射信息。(来源)- 跑步
git-filter-repo --force --mailmap .mailmap
。 (源1,来源2) - 以某种方式辞去新承诺!
- 然后运行
git push origin <your_branch_name> --force
,以重写远程提交历史记录。(来源)- 如果这一步不起作用,我就会直接删除原来的 Github 存储库;创建一个同名的新存储库,然后将本地存储库推送到该存储库。
上述步骤(直到步骤 4),重写作者电子邮件并重新计算哈希值,但丢弃签名。文档中说:(来源)
由于 git filter-repo 调用 fast-export 和 fast-import 来完成大量繁重的工作,它继承了这些系统的局限性……提交被重写意味着它们将具有新的哈希值;因此,提交和标签上的签名无法继续工作,而是被删除(因此签名的标签变为带注释的标签)
因此,为了撤销提交,我发现了以下方法(来源)。
git filter-branch --commit-filter 'git commit-tree -S "$@";' HEAD
但git filter-branch
不建议使用(来源),甚至 Git 自己的文档(来源)。
问题:
- 并且,有没有办法重写作者电子邮件并重新签署新的提交,全部使用
git-filter-repo
? - 如果没有!那么,如何在整个提交历史中重写作者电子邮件并重新提出新的提交?(比我的方法更好!)
答案1
如果存储库有多个分支,则此方法无效。因此,在开始之前,请根据您的要求将所有辅助分支合并到主分支(通常为
master
/main
)。然后删除所有辅助分支。(本地和远程存储库中均有)
我想到了一个可能的解决方案:
- 在我的本地机器上克隆存储库。
- 创建一个 python-3.x 虚拟环境,激活它,然后运行
pip install git-filter-repo GitPython
。 cd <repo-directory>/../
即本地存储库的直接父目录WORKING_DIR
- 运行以下 python 脚本:这将
.mailmap
在 之外创建一个文件,<repo-directory>
其中包含出现在所述存储库提交历史记录中的所有唯一作者/提交者姓名和电子邮件组合 - 将被替换为 和NEW_NAME
。NEW_EMAIL
(进一步编辑代码以排除某些名称/电子邮件被重写)
from git import Repo repo_path = '<repo-directory>' repo = Repo(repo_path) commits_list = list(repo.iter_commits()) unq = set() for cmt in commits_list: unq.add((cmt.committer.name, cmt.committer.email)) unq.add((cmt.author.name, cmt.author.email)) NEW_NAME = "<new-author-name>" NEW_EMAIL = "<new-author-email>" lines = list() for c in unq: lines.append(f"{NEW_NAME} <{NEW_EMAIL}> {c[0]} <{c[1]}>\n") with open(".mailmap", "w") as f: f.writelines(lines)
cd <repo-directory>
,然后运行git-filter-repo --mailmap ../.mailmap
。--> 运行此命令,由于某种原因,似乎删除了remote
存储库链接,即git remote -v
没有返回任何内容。- 要重置存储库的远程,请运行
git remote add origin <remote-repo-url>
- 不要这样做:如果你有多个分支要签署提交,请运行
git filter-branch --commit-filter 'git commit-tree -S "$@";' HEAD
。此外,您可能必须添加一个-f
标志才能使其工作。对于分支单独运行,即您需要签出到每个分支并运行所述命令。- 执行上述步骤后,我运行
git fsck --full --strict
后没有出现任何错误。所以,我认为它运行良好! - 但是有没有更好的方法来检查存储库的完整性?
- 执行上述步骤后,我运行
- 最后,运行
git push origin <primary-branch> --force
以使用更新的提交历史覆盖所有远程分支。