如何在不破坏文件历史记录的情况下组合多个Git存储库?

时间:2017-12-21 16:18:44

标签: git tfs git-tfs

我们正试图远离TFS。使用git-tfs工具,我们能够迁移现有仓库的一部分,但在某些麻烦的签入时崩溃了。我们已经能够制作一套拼凑的Git repos,它涵盖了大多数原始TFS提交。

目前有:

  • Git repo从2009年到2011年的变化
  • 2011年至2016年更改的Git回购
  • Git repo,从2016年到现在的变化

所需:

  • 涵盖2009年至目前的大Git回购
  • 整个时间存在的任何文件都只有一个文件历史记录

我们有什么方法可以将它们拼接成一个Git仓库吗?我们并不关心保留SHA(他们反正全新),但我们无法打破文件历史记录。

3 个答案:

答案 0 :(得分:3)

Git没有拥有文件历史记录。

Git存储提交,提交历史记录。它们是唯一的历史。 (我说它不是文件历史记录,因为它的提交历史记录。)每个提交都有一个父提交,或者如果提交是一个合并,两个父母(或者可能超过如果是章鱼合并,则为两个。

除了拥有父级之外,每次提交都是该提交中所有文件的独立快照。这里没有历史:它只是一个快照。如果您想查看上一次提交和当前提交之间发生的情况,您可以让Git解压缩先前的提交(旧的快照 O )和当前提交(快照 N for new)并运行diff ON 。发生了什么变化: O N 之间有什么不同。

你可以要求Git合成一个文件历史记录,但它是通过一个可怕的黑客来实现的:它在每个提交中查找一个特定的已更改文件,因为它会通过提交历史记录返回。它打印提交的提交,与该提交的父级相比,该提交会更改文件。如果文件 name 更改 - 如果提交重命名了文件 - 并且您已使用--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)

在单个存储库中,您可以编写&#34;替换&#34;提交对象(使用git replace),就像我们想要要替换的第二个根提交一样,除了一件事:它作为其父提交,具有{{{ 1}}点。

这个替换提交有效地将两个历史拼接在一起。

根据需要对您要添加的多个拼接重复此操作,因为您可以在单个存储库中使用多个单独的提交链。然后,您可以在此存储库上运行end,该存储库会复制每个提交,但会遵循替换。这具有将移植物固定在适当位置的效果。例如,请参阅What does git filter-branch with no arguments do?Rebase entire git branch onto orphan branch while keeping commit tree intact

答案 1 :(得分:1)

使用git的'graft'功能有一种简单的方法可以做到这一点。它是与@torek提到的git replace目标相同的功能,但在您的情况下更容易使用。

首先,导入同一存储库中的所有历史记录。在最新的存储库中,为另外两个存储库执行操作:

  1. git remote add c:/path/toward/other/repository
  2. git fetch
  3. 然后在帮助后创建git移植文件.git/info/graftshttps://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/

答案 2 :(得分:0)

基于Eric Lee's blog post

  
      
  1. 创建一个新的空存储库New。
  2.   
  3. 进行初始提交,因为我们在合并之前需要一个提交。
  4.   
  5. 将遥控器添加到旧存储库OldA。
  6.   
  7. 将OldA / master合并为New / master。
  8.   
  9. 创建一个子目录OldA。
  10.   
  11. 将所有文件移至子目录OldA。
  12.   
  13. 提交所有文件移动。
  14.   
  15. 为OldB重复3-6。
  16.