如何合并两个不相关的 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 会是答案。
我看过的答案
- Merge two Git repositories without breaking file history (#1)
- git rebase without changing commit timestamps(上面#2,没有"zipper"历史)
- How to combine two separate unrelated Git repositories into one with single history timeline
- combining unrelated git repositories retaining history/branches
您将必须编写一个脚本来执行此操作。
怎么做
获取每个分支的所有提交时间戳的列表
# print out the commits time stamp & sha-1 of each commit
# do it for all your branches
git log --oneline --format="%at %H"
将 2 个列表组合在一起,并使用任何排序工具(sublime、unix 排序等)按时间戳对它们进行排序
从文件中的第一个提交开始签出新分支
git checkout <first commit id>
从此提交开始创建新分支
git checkout -b <new_branch_name>
遍历所有其他提交并使用 cherry-pick 将它们带入您的分支(脚本)
git cherry-pick <next commit id>
虽然@codeWizard 的回复很有帮助,但该方法并没有按照我想要的方式保留时间戳。它确实让我陷入了困境,但帮助我找到了解决方案...
创建一个新的空白存储库
git init
添加和获取旧存储库作为遥控器
git remote add -f oldRepoA ../oldRepoA
git remote add -f oldRepoB ../oldRepoB
通过时间戳和哈希导出合并的提交历史,将输出通过管道传输到 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
是保持原始时间戳的关键。可能有更好的方法来做到这一点,但这对我的用例来说已经足够好了!
我不太了解git。 :-/
背景
我有两个不相关的基于 git 的文档存储库,我想将它们合并到一个存储库中。我想保留原始时间戳(可追溯到 2005 年)和单个文件历史记录。两个仓库不包含分支,不包含文件夹,在文件命名方面也没有重叠。
在 ASCII 领域,它看起来像这样:
REPO A |-------------------------|
REPO B |===============|
其中重叠表示时间。
目标
我的目标是 "zipper up" 重叠时间戳,以便两个回购协议看起来像一个完整的历史记录:
REPO A+B |-------------------==--=---============|
我试过的
同样,我对 git 不是很了解,所以我可能搞砸了。
首先,我尝试将较新、较小的存储库添加为较大、较旧的存储库的远程存储库,获取更改并提交结果。最后,我将所有新的回购更改集中在旧回购之后的一个分支中:
MERGE |------------------------- -|
\===============/
接下来我尝试了变基(使用 --committer-date-is-author-date
),我认为这会起作用,但我最终得到了一个很长的提交历史,它只是将两个 repos 堆叠在一起。
REBASE |-------------------------===============|
我没能找到 "replay" 合并历史记录的方法。我真的希望 rebase 会是答案。
我看过的答案
- Merge two Git repositories without breaking file history (#1)
- git rebase without changing commit timestamps(上面#2,没有"zipper"历史)
- How to combine two separate unrelated Git repositories into one with single history timeline
- combining unrelated git repositories retaining history/branches
您将必须编写一个脚本来执行此操作。
怎么做
获取每个分支的所有提交时间戳的列表
# print out the commits time stamp & sha-1 of each commit # do it for all your branches git log --oneline --format="%at %H"
将 2 个列表组合在一起,并使用任何排序工具(sublime、unix 排序等)按时间戳对它们进行排序
从文件中的第一个提交开始签出新分支
git checkout <first commit id>
从此提交开始创建新分支
git checkout -b <new_branch_name>
遍历所有其他提交并使用 cherry-pick 将它们带入您的分支(脚本)
git cherry-pick <next commit id>
虽然@codeWizard 的回复很有帮助,但该方法并没有按照我想要的方式保留时间戳。它确实让我陷入了困境,但帮助我找到了解决方案...
创建一个新的空白存储库
git init
添加和获取旧存储库作为遥控器
git remote add -f oldRepoA ../oldRepoA git remote add -f oldRepoB ../oldRepoB
通过时间戳和哈希导出合并的提交历史,将输出通过管道传输到
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
是保持原始时间戳的关键。可能有更好的方法来做到这一点,但这对我的用例来说已经足够好了!