重写子模块历史记录后包含子模块的存储库

时间:2016-05-25 16:08:52

标签: git git-submodules

使用 var sqlCommand = string.Format(@" MERGE [test2] AS target USING (select @property_id as property_id, @val as {0}) AS source ON (target.property_id = source.property_id) WHEN MATCHED THEN UPDATE SET {0}= source.{0} WHEN NOT MATCHED THEN INSERT (property_id, {0}) VALUES (source.property_id, source.{0}); ", columnName); 重写存储库的历史记录后,所有SHA都会更改。

现在,如果该存储库(让我们称之为git filter-branch)用作另一个存储库中的git子模块(让我们称之为X),我们就会遇到问题。
实际上,Y根据该子模块中提交的SHA知道要加载的子模块Y的版本。由于X中的所有SHA现在都已更改,X指向不再存在的SHA。

有没有办法重写Y的历史记录,使其指向子模块Y的新提交SHA(当前提交和过去提交)?

我猜想,鉴于旧的SHA和新的SHA之间存在对应关系,原则上这是可能的,但我担心它会涉及令人讨厌的bash脚本。
还有什么比较容易了吗?

1 个答案:

答案 0 :(得分:8)

  

但我担心它会涉及令人讨厌的bash脚本。

恐怕确实如此。

  

有没有更容易的事情?

不是我知道的。
以下是该脚本工作所需的一些线索(不是完整的脚本):

如果您仍然可以访问重写的仓库,则其原始历史记录(过滤器分支之前)保留在.git/refs/original

这意味着您可以循环使用旧历史SHA1:

 git -C /path/to/rewritten/repo for-each-ref --format="%(refname)" refs/original

如果更改仅限于一个分支,则可以轻松地将新SHA1与旧分区匹配(第一个旧分区与重写分支的第一个提交匹配,第二个旧分支匹配......等等)

如果没有,你必须寻找一个转速才能找到一个匹配(相同的日期,合理的提交消息)

git rev-list --all \
  | while read commit
 do
 ...

确保父repo更新其子模块的引用:

cd parent/repo
cd asubmodule
git fetch

这样,新的SHA1可用。

最后,您可以在父代仓库中执行过滤器分支,寻找 gitlink special entry in the index,匹配其中一个旧版SHA1。

对于每个匹配,你检查子模块文件夹中的新SHA1,返回到父级仓库的一级,添加并提交:这将记录一个新的gitlink SHA1。

cd parent/repo/asubmodule
git checkout <new SHA1>
cd ..
git add .
git commit -m "Record new SHA1 for asubmodule"