合并两个Git存储库而不会破坏文件历史记录

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

有什么办法可以合并存储库并保留个别文件历史记录吗?


事实证明,如果您只是试图将两个存储库粘合在一起并使其看起来像一直如此,而不是管理外部依赖关系,则答案会更简单。 您只需将遥控器添加到旧的回购站,将它们合并到新的主控室,将文件和文件夹移动到子目录,提交移动并重复所有额外的回购。 子模块,子树合并和花式重设旨在解决一个稍微不同的问题,并不适合我正在尝试做的事情。

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

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

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

如果您想要引入进行中的功能分支,请使用以下命令:

# 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正确排列所有内容。

我在这里写了一个更详细的解释。


这是一种不重写任何历史记录的方式,因此所有提交ID都将保持有效。 最终的结果是第二个repo的文件将以子目录结束。

  • 将第二个回购添加为远程:

    cd firstgitrepo/
    git remote add secondrepo username@servername:andsoon
    
  • 确保你已经下载了所有secondrepo的提交:

    git fetch secondrepo
    
  • 从第二个仓库的分支创建一个本地分支:

    git branch branchfromsecondrepo secondrepo/master
    
  • 将其所有文件移动到一个子目录中:

    git checkout branchfromsecondrepo
    mkdir subdir/
    git ls-tree -z --name-only HEAD | xargs -0 -I {} git mv {} subdir/
    git commit -m "Moved files to subdir/"
    
  • 将第二个分支合并到第一个回购的主分支中:

    git checkout master
    git merge --allow-unrelated-histories branchfromsecondrepo
    
  • 您的存储库将拥有多个根提交,但这不应构成问题。


    请看看使用

    git rebase --root --preserve-merges --onto
    

    在他们生命的早期将两个历史联系起来。

    如果你有重叠的路径,请修复它们

    git filter-branch --index-filter
    

    当你使用日志时,确保你“更难找到复制品”

    git log -CC
    

    这样你会发现路径中的任何文件移动。

    链接地址: http://www.djcxy.com/p/46967.html

    上一篇: Merge two Git repositories without breaking file history

    下一篇: Pull all commits from a branch, push specified commits to another