我有一个项目,其中一些文件在不同的地方有多个副本。例如:
src/location1/foobar.h
src/location1/foobar.cpp
src/location2/foobar.h
src/location2/foobar.cpp
我正在将这些内容提取到自己的库中。因此,我希望以以下内容结束:
src/location3/foobar.h combining multiple versions of foobar.h
src/location3/foobar.cpp combining multiple versions of foobar.cpp
我已经通过了第一个障碍,删除所有不需要的文件使用:
git filter-repo --path-glob \*foobar\*
在这个过程中发现filter-branch最近被更高级的filter-repo取代了(值得重复,因为filter-branch仍然出现在这里的许多热门答案中)。
现在我想把这些副本合并成一个保存它们所有历史的副本,两个候选对象是merge
和merge-file
。merge-file
要求标识每个文件的共同祖先,这可能是一个难题:
src/location3/foobar.h
这是提交历史中未知的地方。我们用git merge-base
来寻找最佳的共同祖先。
我不清楚如何指定git merge-file的文件版本:
git mv src/location1/foobar.h src/newlocation/foobar.h
git commit
git merge-file src/newlocation/foobar.h src/location3/foobar@<commitid> src/location2/foobar.h
...
git merge-file src/newlocation/foobar.h src/location3/foobar@<commitid> src/location3/foobar.h
这是相当辛苦的,必须为每个文件重复。另一种方法是创建多个临时分支:
git checkout -b newlibbranch
git mv src/location1/foobar.h src/newlocation/foobar.h
git mv src/location1/foobar.cpp src/newlocation/foobar.cpp
git commit
git checkout oldversion
git checkout -b v2
git mv src/location2/foobar.h src/newlocation/foobar.h
git mv src/location2/foobar.cpp src/newlocation/foobar.cpp
git commit
git checkout newlibbranch
git merge --allow-unrelated-histories v2
这也是相当辛苦的。虽然它可能是脚本化的。还有一个实际问题,因为合并是"重命名/重命名"冲突,而不是实际文件的合并。这似乎可以通过添加--allow-unrelated-histors来解决
所以我的问题是:
关于任务:
1.有没有更好的方法?也许是一个合并工具,我不知道就像我不知道过滤器-回购
1.我认为多个合并分支的方式比git merge-file更好是正确的吗?
关于合并文件:
1.如何为git merge-file指定文件特定版本
1.是否有一个命令或脚本可以自动找到共同的祖先。例如:
git merge-file-wrapper location1 location2 -->
base = `git merge-base location1 location2`
git merge-file location1 $base location2
难道这是不存在的,因为有一些隐藏的陷阱?
1条答案
按热度按时间uxhixvfz1#
我还没有找到任何自动化的工具来做这件事,所以在生态系统中可能有一个缺口。
在我的例子中,我有多个文件要移动,其中一些文件比其他文件有更多的副本,这增加了一些有趣的复杂性,但在重构以删除重复时并不罕见。
我最后做的是:
这些合并中的大多数都是琐碎的事情,比如为每个子项目更改名称空间。
结果是一组文件,其中包含我想要的所有更改以及每个文件的所有更改历史。
为了让这一点更具体一些:
(note这应该在项目的新克隆上完成)
rename-threshold可以帮助git确信两个文件来自同一个地方,否则一个版本可能会简单地替换另一个版本,而不保留链接它们的修改历史。我认为结果等同于使用git commit-tree链接多个提交,这是解决这个问题的另一种方法。
您可以使用
git blame
验证历史记录,查看每个文件中的每一行来自何处,使用git log
查看实际提交。Raymond Chen对此有一个series of blogs,可能会感兴趣。他使用commit-tree来处理这个任务。我认为这会起作用,但我认为对于我的情况来说,这是一个有点太低级的方法。
这是为了完整起见,因为您可能会将文件移动到另一个项目中。请参阅“如何合并两个Git仓库?“了解更多详细信息
我认为这方面的时机已经成熟,可以贡献一个脚本来为git添加一个新的合并工具。