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

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

问题描述

我需要将两个Git存储库合并到一个全新的第三个存储库中。我发现了很多关于如何使用子树合并来完成此操作的说明(例如 JakubNarębski的 git log 时,我可以看到旧版本库的提交历史记录,但是如果我执行 git log< file> 它只显示该文件的一个提交 - 子树合并。从上述答案的评论来看,我并不孤单看到这个问题,但我没有发现任何已发布的解决方案。



有什么办法可以合并存储库,并保留单个文件历史记录不变? 解决方案

原来,如果你只是试图粘贴,答案就简单多了两个存储库放在一起,使它看起来像它一直是这样,而不是管理外部依赖。您只需将遥控器添加到旧的回购站,将它们合并到新的主控室,将文件和文件夹移动到子目录,提交移动并重复所有额外的回购。子模块,子树合并和花式重定义是为了解决一个稍微不同的问题,并不适合我正在尝试做的事情。



以下是Powershell脚本示例将两个存储库粘贴在一起:



 #假设当前目录是我们希望创建新的存储库
#创建新的存储库
git init

#在我们进行合并之前,我们必须先进行一次提交,我会做一个虚构的提交
dir> deleteme.txt
git add。
git commit -m初始虚拟提交

#添加远程并获取旧的回购
git remote add -f old_a< OldA repo URL>

#将old_a / master中的文件合并到新的/ master
中git merge old_a / master --allow-unrelated-history

#清理我们的虚拟文件因为我们不再需要它
git rm .\deleteme.txt
git commit -m清理初始文件

#将old_a回购文件和文件夹放到一个子目录中,以便它们不会与后来的其他回购产生冲突
mkdir old_a
dir -exclude old_a | %{git mv $ _。name old_a}

#提交移动
git commit -m将old_a文件移动到子目录中

#执行相同的操作for old_b
git remote add -f old_b< OldB repo URL>
git merge old_b / master --allow-unrelated-history
mkdir old_b
dir -exclude old_a,ol​​d_b | %b




$ b

显然,如果你愿意这么做,你可以将old_b合并到old_a(它成为新的组合回购) - 修改脚本以适应。



如果你也想引入进行中的功能分支,使用这个:


$ b

 #带过来来自旧回购之一的功能分支
git checkout -b功能进行中
git合并-s递归-Xsubtree = old_a old_a /功能正在进行中


$ b

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



我写了一个稍微更详细的解释 here

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.

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
dir > deleteme.txt
git add .
git commit -m "Initial dummy commit"

# Add a remote for and fetch the old repo
git remote add -f old_a <OldA repo URL>

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

# Clean up our dummy file because we don't need it any more
git rm .\deleteme.txt
git commit -m "Clean up initial file"

# 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"

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

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天全站免登陆