2017-10-20 75 views
1

我将git存储库的内容移动到另一个存储库,对于所有常规提交,一切都很好。不过,我遇到了子模块的问题。git filter-tree和修改子模块

设置,我们从两个回购开始。我们称他们为“文档”,“行动”,我们要“文档”的内容移动到“操作”的子目录,像这样:

docs/ 
    file1.txt 
    dir1/ 
    file2.txt 
    other-docs/ <- This is a git submodule 

operations/ 
    bin/ 
    do-things 
    docs/ 
    important.txt 

而且我们希望最终版本看这样,这里的“文档”回购协议在操作回购“文档/遗产”结束:

operations/ 
    bin/ 
    do-things 
    docs/ 
    important.txt 
    legacy/ 
     file1.txt 
     dir1/ 
     file2.txt 
     other-docs/ <- This is a git submodule 

我有一个使用的git filter-branch --tree-filtergit rebase一个组合的脚本(衍合新的内容到现有的内容和处理冲突如.gitignore文件)来执行实际的迁移,但是,在运行迁移后,我最终得到:

其中other-docs子模块仍位于新回购的根部。

我明白为什么会发生这种情况。当我通过提交移动东西时,没有子模块的实际文件,因此,在“该目录中的所有内容都按照您离开它的方式提交”模型git filter-branch --tree-filter,有没有任何“离开“用于子模块。

所以,第一个问题:是否有一些方面使用git filter-branch我可以解释这一点?我想知道的一个地方是,如果我可以添加--commit-filter并弄乱那里的东西,但我并不完全清楚提交过滤器周围的不变量是什么。

如果不存在,是否有其他地方我可以做到这一点。据我所知,我将不得不修改子模块的现有提交,基本上“删除”旧的不正确位置的子模块,并将子模块“添加”到新的正确位置。我想我可以通过一个交互式的rebase操作来编写脚本,找到这些提交并修改它们。如果有更好的方法,这听起来像很多工作。

任何想法赞赏。

回答

1

我明白为什么会发生这种情况。当我通过提交移动东西时,没有子模块的实际文件,因此,在“该目录中的所有内容都按照您离开它的方式提交”模型git filter-branch --tree-filter,有没有任何“离开“用于子模块。

这就是问题所在。它似乎有点讨厌。

所以,第一个问题:是否有一些方面使用git filter-branch我可以解释这一点?我想知道的一个地方是,如果我可以添加--commit-filter并弄乱那里的东西,但我并不完全清楚提交过滤器周围的不变量是什么。

可以。这不是很漂亮。

更好的做法是在--index-filter。由于the documentation提示,过滤器按列出的顺序运行,所以索引过滤器在树过滤器后运行。它可以对树形过滤器的周围代码编写的索引进行任何操作。 (树形过滤器使用git update-index --add-remove来更新索引条目,如果需要,根据您的过滤器留下的树来自动更新文件。)

您也可以直接在索引过滤器中执行所有操作,速度要快得多,因为这不需要考虑实际的文件系统操作(mkdir,创建文件等)。虽然索引过滤器通常很难编写,但命令可以构建一个全新的索引或只更新现有索引的某些部分,但必须先构建一个或一些更改,方法是先读出旧索引(使用git ls-files --stage,也许)并操纵结果文本。

但是这让你做你想做的。

3

树过滤器很容易,但它们很慢,而且你发现它们不知所云。更好的方法是只检查你需要修改的内容,其余的则使用git read-tree

git filter-branch --index-filter=' 

     # load up the docs-repo commit we're importing under docs/legacy/ 
     git read-tree --prefix=docs/legacy/ $(imported-commit-for $GIT_COMMIT): 

     # hoist any imported submodule configs 
     git checkout .gitmodules 
     git checkout docs/legacy/.gitmodules 2>&- && 
     sed -n "s,path ,path docs/legacy/, 
      s,^,git config -f .gitmodules ,e" && 
     git rm docs/legacy/.gitmodules && 
     git add .gitmodules 

     # any other needed content updates here 
' 
+0

尼斯:我没有注意到--prefix保持当前索引内容不变,只是增加了新的内容。 'git checkout'和'git add'步骤有点痛苦,但几乎每种方法都是如此。 – torek

+0

@torek Yah,如果你愿意,你可以真正运行它作为一个树型过滤器,在读取树中添加一个“-u”以更新工作树并消除签出并添加,因为filter-branch只会遍历整个树对你来说,但浪费的流失如此冒犯了我无法遵守的感情。嗯。我应该把它作为一种选择,让任何人不会因为浪费而被冒犯。 – jthill

+0

heh。不。不能让自己发布结果,不管它看起来更干净。 – jthill