如何将嵌套的git repo合并到父repo中,保留历史记录?


How to merge nested git repo into parent repo, retaining history?

现在我知道大多数Git专家会立刻想到git rebase,但我使用的是更一般意义上的"rebase"一词:我的项目结构如下:

1
2
3
4
5
6
7
8
.
..
.git
tools
lib
src
    .git
build

../src目录显然都是git存储库,而且字面上都有很长的历史和大量的提交。.中的存储库忽略src目录(它是自己的repo)。

我刚刚意识到,我只想在.中有一个单一的repo来跟踪包括源文件在内的所有内容,因为坦率地说,构建系统随着源代码而发展,并且已经变得相当广泛。

我的问题是,我不知道如何让这个存储库保留历史,它现在是src中存储库的一部分。有可能吗?这就是我所说的"重新平衡"——如果./src/main.c中的更改被./src/.git跨一些n提交跟踪,那么我希望保留这些更改,并让它们成为新存储库./.git的一部分。相同的历史记录,重新设定文件路径。

更新

子树合并不是我想要的,而是我从中收集到的。简而言之,它比我需要的功能要强大得多。我只需要旧回购的内容,开发的所有分支以及所有提交、标记等将一起看起来好像它们始终是父回购的一部分。在Essense中,唯一的改变是文件本身的路径——在子repo跟踪./main.c之前,新repo现在将跟踪./src/main.c,而且正如我听说的那样,git跟踪内容,而不是文件,然后更改像上面这样的文件路径和对这些路径的引用,应该是非常简单的,正确的?


快速简便的方法:

重命名SRC中的所有文件,使其以src/开头。将src repo添加为remote,fetch&merge。放下旧的SRC回购,一切都在./中。

这将使您的操作记录在历史记录中。

历史重写:

要使这个合并不可见,您需要使用git filter-branch --tree-filter在SRC存储库中添加src/前缀。然后将其作为远程文件添加到./存储库中并获取它(还没有合并)。为了更好地混合历史,您需要重新排序提交。使用git log --date-order master src/master以正确的顺序检索这些承诺,然后选择它们:

1
2
git checkout -b new-master your-first-commit
git log --format='%H' --date-order --reverse master src/master | xargs git cherry-pick

这基本上是根据你的提交进行合并排序,并将它们排列成线性历史。

这不会保留您的合并,所以不要这样做,除非您有平坦的历史。在这种情况下,只使用过滤分支,然后进行正常合并。


我需要做同样的事情,这对我很有用:

从母公司回购,

1
2
3
4
git remote add -f subrepo [email protected]:sub/repo.git
git merge -s ours --no-commit subrepo/master
git read-tree --prefix=subrepo/ -u subrepo/master
git commit -m"Subtree merged"

这是来自一个Github的帖子,它也有更多的细节:https://help.github.com/articles/about-git-subtree-merges/


使用子树合并。

我将列出这些步骤,但它们是这个问题的答案:如何合并两个Git存储库?


如果这行得通,但值得一试,那就没什么用了。假设SRC在远程服务器上,父服务器在远程服务器上。您可以尝试以下操作。

  • git克隆到远程服务器的URL,以使用工具、lib和build克隆repo
  • 将远程SRC URL添加到SRC远程报告
  • 创建SRC远程回购的跟踪分支,然后在父回购上检查它。
  • 将远程跟踪分支合并到主分支中。
  • 删除第二个遥控器。