合并两个 Git 存储库而不破坏文件历史记录 [英] Merge two Git repositories without breaking file history

查看:23
本文介绍了合并两个 Git 存储库而不破坏文件历史记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将两个 Git 存储库合并到一个全新的第三个存储库中.我发现了许多关于如何使用子树合并来执行此操作的描述(例如 Jakub Narębski 的答案)://stackoverflow.com/questions/1425892/how-do-you-merge-two-git-repositories">你如何合并两个 Git 存储库?)并按照这些说明进行操作,大多数情况下,除了当我提交子树合并旧存储库中的所有文件都记录为新添加的文件.当我执行 git log 时,我可以看到旧存储库的提交历史记录,但是如果我执行 git log 它只显示该文件的一个提交 -子树合并.从对上述答案的评论来看,我并不是唯一看到这个问题的人,但我没有找到针对它的已发布解决方案.

I need to merge two Git repositories into a brand new, third repository. I've found many descriptions of how to do this using a subtree merge (for example Jakub Narębski's answer on How do you merge two Git repositories?) and following those instructions mostly works, except that when I commit the subtree merge all of the files from the old repositories are recorded as new added files. I can see the commit history from the old repositories when I do git log, but if I do git log <file> it shows only one commit for that file - the subtree merge. Judging from the comments on the above answer, I'm not alone in seeing this problem but I've found no published solutions for it.

有没有办法合并存储库并保持单个文件历史记录完整?

Is there any way do merge repositories and leave individual file history intact?

推荐答案

事实证明,如果您只是尝试将两个存储库粘合在一起并使其看起来像一直这样而不是管理外部依赖.您只需将遥控器添加到旧存储库,将它们合并到新主存储库,将文件和文件夹移动到子目录,提交移动,然后对所有其他存储库重复此操作.子模块、子树合并和花哨的变基旨在解决稍微不同的问题,不适合我尝试做的事情.

It turns out that the answer is much simpler if you're simply trying to glue two repositories together and make it look like it was that way all along rather than manage an external dependency. You simply need to add remotes to your old repos, merge them to your new master, move the files and folders to a subdirectory, commit the move, and repeat for all additional repos. Submodules, subtree merges, and fancy rebases are intended to solve a slightly different problem and aren't suitable for what I was trying to do.

这是将两个存储库粘合在一起的示例 Powershell 脚本:

Here's an example Powershell script to glue two repositories together:

# Assume the current directory is where we want the new repository to be created
# Create the new repository
git init

# Before we do a merge, we have to have an initial commit, so we'll make a dummy commit
git commit --allow-empty -m "Initial dummy commit"

# Add a remote for and fetch the old repo
# (the '--fetch' (or '-f') option will make git immediately fetch commits to the local repo after adding the remote)
git remote add --fetch old_a <OldA repo URL>

# Merge the files from old_a/master into new/master
git merge old_a/master --allow-unrelated-histories

# Move the old_a repo files and folders into a subdirectory so they don't collide with the other repo coming later
mkdir old_a
dir -exclude old_a | %{git mv $_.Name old_a}

# Commit the move
git commit -m "Move old_a files into subdir"

# Do the same thing for old_b
git remote add -f old_b <OldB repo URL>
git merge old_b/master --allow-unrelated-histories
mkdir old_b
dir –exclude old_a,old_b | %{git mv $_.Name old_b}
git commit -m "Move old_b files into subdir"

显然,如果您愿意,您可以将 old_b 合并到 old_a(成为新的合并存储库)中 - 修改脚本以适应.

Obviously you could instead merge old_b into old_a (which becomes the new combined repo) if you’d rather do that – modify the script to suit.

如果您还想引入正在进行的功能分支,请使用:

If you want to bring over in-progress feature branches as well, use this:

# Bring over a feature branch from one of the old repos
git checkout -b feature-in-progress
git merge -s recursive -Xsubtree=old_a old_a/feature-in-progress

这是该过程中唯一不明显的部分 - 这不是子树合并,而是正常递归合并的一个参数,它告诉 Git 我们重命名了目标并帮助 Git 正确排列所有内容.

That's the only non-obvious part of the process - that's not a subtree merge, but rather an argument to the normal recursive merge that tells Git that we renamed the target and that helps Git line everything up correctly.

我写了一个稍微详细一点的解释 这里.

I wrote up a slightly more detailed explanation here.

这篇关于合并两个 Git 存储库而不破坏文件历史记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆