协慌网

登录 贡献 社区

你如何合并两个 Git 存储库?

请考虑以下情形:

我在自己的 Git 仓库中开发了一个小型实验项目 A. 它现在已经成熟,我希望 A 成为更大的项目 B 的一部分,它有自己的大型存储库。我现在想添加 A 作为 B 的子目录。

如何将 A 合并到 B 中,而不会丢失任何一方的历史记录?

答案

如果要将project-a合并到project-b

cd path/to/project-b
git remote add project-a path/to/project-a
git fetch project-a --tags
git merge --allow-unrelated-histories project-a/master # or whichever branch you want to merge
git remote remove project-a

取自: git 合并不同的存储库?

这种方法对我来说效果很好,它更短,在我看来更清洁。

注意: - --allow-unrelated-histories参数仅在 git> = 2.9 时存在。请参阅Git-git merge Documentation / --allow-unrelated-histories

更新 :添加--tags--tags所建议,以保留标记。

这有两种可能的解决方案:

子模块

将存储库 A 复制到较大项目 B 中的单独目录中,或者(可能更好)将存储库 A 克隆到项目 B 中的子目录中。然后使用git 子模块将此存储库作为存储库 B 的子模块

这是松耦合的仓库,其中一个仓库继续发展一个很好的解决方案,以及发展的主要部分是在 A 的单独的独立发展,也见SubmoduleSupportGitSubmoduleTutorial上的 Git 维基网页。

子树合并

您可以使用子树合并策略将存储库 A 合并到项目 B 的子目录中。 Markus Prinz 在Subtree Merging 和 You 中对此进行了描述。

git remote add -f Bproject /path/to/B
git merge -s ours --allow-unrelated-histories --no-commit Bproject/master
git read-tree --prefix=dir-B/ -u Bproject/master
git commit -m "Merge B project as our subdirectory"
git pull -s subtree Bproject master

(Git> = 2.9.0 需要 Option --allow-unrelated-histories 。)

或者你可以使用 apenwarr(Avery Pennarun)的git 子树工具( GitHub 上的存储库 ),例如在他的博客文章中公布了一个新的替代 Git 子模块:git 子树


我认为在你的情况下(A 是大项目 B 的一部分)正确的解决方案是使用子树合并

另一个存储库的单个分支可以轻松放置在保留其历史记录的子目录下。例如:

git subtree add --prefix=rails git://github.com/rails/rails.git master

这将显示为单个提交,其中 Rails 主分支的所有文件都添加到 “rails” 目录中。但是,commit 的标题包含对旧历史树的引用:

从 commit <rev>添加'rails /'

其中<rev>是 SHA-1 提交哈希。你仍然可以看到历史,指责一些变化。

git log <rev>
git blame <rev> -- README.md

请注意,您无法从此处看到目录前缀,因为这是一个完整的旧分支。您应该将此视为通常的文件移动提交:到达时需要额外的跳转。

# finishes with all files added at once commit
git log rails/README.md

# then continue from original tree
git log <rev> -- README.md

有更复杂的解决方案,例如手动执行此操作或重写历史记录,如其他答案中所述。

git-subtree 命令是官方 git-contrib 的一部分,一些数据包管理器默认安装它(OS X Homebrew)。但除了 git 之外,您可能需要自己安装它。