如何合并两个不相关的 git 存储库,保留历史

How to combine two unrelated git repositories, preserving history

我不太了解git。 :-/

背景

我有两个不相关的基于 git 的文档存储库,我想将它们合并到一个存储库中。我想保留原始时间戳(可追溯到 2005 年)和单个文件历史记录。两个仓库不包含分支,不包含文件夹,在文件命名方面也没有重叠。

在 ASCII 领域,它看起来像这样:

REPO A    |-------------------------|
REPO B                    |===============|

其中重叠表示时间。

目标

我的目标是 "zipper up" 重叠时间戳,以便两个回购协议看起来像一个完整的历史记录:

REPO A+B  |-------------------==--=---============|

我试过的

同样,我对 git 不是很了解,所以我可能搞砸了。

首先,我尝试将较新、较小的存储库添加为较大、较旧的存储库的远程存储库,获取更改并提交结果。最后,我将所有新的回购更改集中在旧回购之后的一个分支中:

MERGE  |-------------------------                 -|
                                 \===============/

接下来我尝试了变基(使用 --committer-date-is-author-date),我认为这会起作用,但我最终得到了一个很长的提交历史,它只是将两个 repos 堆叠在一起。

REBASE |-------------------------===============|

我没能找到 "replay" 合并历史记录的方法。我真的希望 rebase 会是答案。

我看过的答案

您将必须编写一个脚本来执行此操作。

怎么做

  1. 获取每个分支的所有提交时间戳的列表

    # print out the commits time stamp & sha-1 of each commit
    # do it for all your branches
    git log --oneline --format="%at %H"
    

  2. 将 2 个列表组合在一起,并使用任何排序工具(sublime、unix 排序等)按时间戳对它们进行排序

  3. 从文件中的第一个提交开始签出新分支

    git checkout <first commit id>
    

  4. 从此提交开始创建新分支

    git checkout -b <new_branch_name>
    
  5. 遍历所有其他提交并使用 cherry-pick 将它们带入您的分支(脚本)

    git cherry-pick <next commit id>
    

虽然@codeWizard 的回复很有帮助,但该方法并没有按照我想要的方式保留时间戳。它确实让我陷入了困境,但帮助我找到了解决方案...

  1. 创建一个新的空白存储库

    git init
    
  2. 添加和获取旧存储库作为遥控器

    git remote add -f oldRepoA ../oldRepoA
    git remote add -f oldRepoB ../oldRepoB
    
  3. 通过时间戳和哈希导出合并的提交历史,将输出通过管道传输到 sort,通过 cut 丢弃时间戳,然后将按时间顺序排序的哈希列表通过管道传输到xargs,它运行一个 shell 脚本来为每个单独的哈希导出补丁,然后立即将补丁应用到新的 repo。

    git log --all --oneline --format="%at %H" | sort | cut -c12- | 
        xargs -I {} sh -c 
            'git format-patch -1 {} --stdout | 
             git am --committer-date-is-author-date'
    

--committer-date-is-author-date 是保持原始时间戳的关键。可能有更好的方法来做到这一点,但这对我的用例来说已经足够好了!