我们正试图远离TFS。使用git-tfs工具,我们能够迁移现有仓库的一部分,但在某些麻烦的签入时崩溃了。我们已经能够制作一套拼凑的Git repos,它涵盖了大多数原始TFS提交。
目前有:
期望:
我们有什么方法可以将它们拼接成一个Git仓库吗?我们不关心保留SHA(它们都是新的),但我们无法打破文件历史记录。
使用git的'graft'功能有一种简单的方法可以做到这一点。这是@torek提到的与git replace
相同目标的功能,但在您的情况下更容易使用。
首先,导入同一存储库中的所有历史记录。在最新的存储库中,为其他2个存储库做:
git remote add c:/path/toward/other/repository
git fetch
然后在帮助之后创建git移植文件.git/info/grafts
:https://git.wiki.kernel.org/index.php/GraftPoint(你的文件中应该有2行)
如果您使用git log
或任何Git GUI,您现在应该看到您想要的历史记录。
如果您满意,则重写历史记录以使其明确:
git filter-branch
您现在可以将历史记录推送到中央存储库或共享它。
Ps:关于这个主题的另一个文档,但融化移植和替换git功能:https://legacy-developer.atlassian.com/blog/2015/08/grafting-earlier-history-with-git/
Git没有文件历史记录。
Git存储提交,提交是历史。它们是唯一的历史。 (我说它不是文件历史记录,因为它是提交历史记录。)每个提交都有父提交,或者如果提交是合并,则有两个父项(如果它是章鱼合并,则可能超过两个)。
除了拥有父级之外,每次提交都是该提交中所有文件的独立快照。这里没有历史:它只是一个快照。如果你想看看前一次提交和当前提交之间发生了什么,你就让Git解压缩先前的提交(旧的快照O)和当前提交(快照N为新)并运行diff O N.这就是改变了:无论如何O和N之间有所不同。
你可以要求Git合成一个文件历史记录,但它是通过一个可怕的黑客来实现的:它在每个提交中查找一个特定的已更改文件,因为它返回到提交历史记录。它打印提交,当提交与该提交的父进行比较时,该提交会更改文件。如果文件名更改 - 如果提交重命名文件 - 并且您已使用--follow
,Git会更改它正在查找的(单个)文件名,所以现在它在以前的名称下查找。
如果您的历史记录包含一系列提交:
(history starts here, at a root commit)
|
v
o--o--<branches and merges...>--o <-- end
和第二个历史:
o--o--<branches and merges...>--o <-- end
o--o--...--o <-- end2
^
|
(we want to replace this one)
在单个存储库中,您可以编写一个“替换”提交对象(使用git replace
),就像我们要替换的第二个根提交一样,除了一件事:作为其父提交,它具有end
的提交点。
这种替换提交有效地将两个历史拼接在一起。
根据需要对您想要添加的多个拼接重复此操作,因为您在单个存储库中具有多个单独的提交链。然后,您可以在此存储库上运行git filter-branch
,该存储库复制每个提交,但遵循替换。这具有将移植物固定在适当位置的效果。例如,请参阅What does git filter-branch with no arguments do?或Rebase entire git branch onto orphan branch while keeping commit tree intact。
- 创建一个新的空存储库New。
- 进行初始提交,因为我们在进行合并之前需要一个提交。
- 将远程添加到旧存储库OldA。
- 将OldA / master合并为New / master。
- 创建一个子目录OldA。
- 将所有文件移动到子目录OldA中。
- 提交所有文件移动。
- 为OldB重复3-6。