2

假设我有一个名为“Hammerstein”的尚未发布的软件产品的巨大存储库,由著名的德国软件公司“Apfel”编写,我是该公司的员工。

有一天,“Apfel”分拆了 Hammerstein 部门并将其出售给著名的公司“Oráculo”,该公司出于民族自豪感将“Hammerstein”重命名为“Reineta”并决定将其开源。

协议要求在存储库中将所有对“Hammerstein”和“Apfel”的引用替换为“Oráculo”和“Reineta”。

所有文件名,所有提交消息,所有内容都必须替换。

因此,例如:

  1. src/core/ApfelCore/main.cpp必须成为src/core/OraculoCore/main.cpp

  2. 说的commit message"Add support for Apfel Groupware Server"必须变成"Add support for Oraculo Groupware Server"

  3. 字符串ApfelServerInstance* local_apfel,#define REINETA并且Url("http://apfel.de")必须变为OraculoServerInstance* local_oraculo,#define HAMMERSTEIN等。

这也适用于不再存在的文件HEAD

以最少的手动干预(以便可以将其批量应用于可能大量的存储库/资产)实现它的最简单和最无痛的方法是什么?

  1. BFG可以替换字符串,但它似乎只有一个--delete-file选项,而不是 a --rename-file,即使这样它也不将模式作为参数
  2. 这种方法似乎只适用HEAD于整个历史,而不适用于整个历史;我没有运气使用它--tree-filter
4

2 回答 2

4

全面披露:我是BFG Repo-Cleaner的作者

正如您在问题中所说,BFG 支持用标志替换文件内容--replace-text- 但此标志不会扩展到文件和提交消息。那么,要使 BFG 的--replace-text操作也扩展到这些代码库,需要对代码库进行哪些更改?

这归结为挂钩一些新的Cleaner[V]实现,V你想要清理的东西的类型(提交消息、目录列表)在哪里,而Cleaner只是负责V从旧的、肮脏的V. 要执行实际的文本更改,您可以重新使用用于文件内容更改的相同文本替换功能。

文件名

使用Cleaner[Seq[Tree.Entry]]- “树”是 Git 所说的文件夹(“文件树”) - 所以你只需更新FileName每个Tree.Entry.

提交消息

再次使用Cleaner[CommitNode]- ,您只是替换message字段上的文本 - 请参阅CommitMessageObjectIdsUpdater以获得非常接近的示例,了解您正在尝试执行的操作。当你在那里时,如果你愿意,你可以对作者和提交者的电子邮件地址做一些事情(例如 purge ...@apfel.com,我猜)。

速度

正如@VonC 在他的回答中提到的那样,filter-branch 可以同时进行这两种替换(文件名和提交消息),但是虽然--msg-filter标志应该相当快地更新提交消息,但我相信在大型代码库中重命名文件filter-branch会非常缓慢,例如你的。BFG 针对这种操作进行了优化,速度将提高数百倍

BFG 在https://www.bountysource.com/teams/bfg-repo-cleaner接受捐赠- 因此,如果您想支持此功能的开发,或者您发现 BFG 对解决您的问题很有用,那就是你可以在哪里有所作为。

于 2015-09-21T07:21:44.473 回答
2

在一个简单的步骤中?

不是单一的,也不是那么简单,但可能:


要更新提交消息,您需要the --msg-filter使用git filter-branch

git filter-branch -f --msg-filter 'sed "s/Apfel/Oraculo/"' -- --all

注意--all,为了过滤每个分支的所有提交
您可能需要多次重复该命令以处理不同的情况。


对于移动文件(不使用 --tree-filter),您可以参考这个答案(和这篇文章),并对其进行调整以构建新路径:

git filter-branch --index-filter 'git ls-files -s | \
  sed "s,/ApfelCore/,/OraculoCore/," | \
  GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && \
  mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' \
-- --all

如前所述,BFG可以替换所有字符串;请参阅“如何从 git 历史记录中的文件中替换文本?

java -jar bfg.jar --replace-text replacements.txt my-repo.git

replacements.txt文件应包含您要执行的所有替换,格式如下(每行一个条目)

Apfel==>Oraculo
apfel==>oraculo
REINETA==>HAMMERSTEIN
于 2015-09-20T10:55:36.137 回答