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跟踪内容,而不是文件,然后更改像上面这样的文件路径和对这些路径的引用,应该是非常简单的,正确的?
- 向谷歌请求"子树合并",这就是你想要的。
- 我至少花了一个小时,得出结论:子树合并和子模块都不适合我。子树合并不仅保留了历史,而且保留了旧回购和新回购之间的联系——而我的旧回购将被废弃和废弃。子模块是不可能的,因为我的回购协议是非常紧密的耦合。我发现下面的答案最适合我,但我真的想合并所有分支,而不仅仅是master:stackoverflow.com/questions/13040958/…
快速简便的方法:
重命名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 |
这基本上是根据你的提交进行合并排序,并将它们排列成线性历史。
这不会保留您的合并,所以不要这样做,除非您有平坦的历史。在这种情况下,只使用过滤分支,然后进行正常合并。
- 我对挑选樱桃不太确定——我想保留整个历史,没有例外。我还想保留所有的树枝,不仅仅是主人。你的解决方案有效吗?
- 如果您的历史较长且复杂,那么cherry-pick部分是一个坏主意,但是过滤分支和合并可以很好地工作。不过,只要运气好一点,您就可以在合并后使用交互式的REBASE(-i)重新安排提交。我所写的只是保持历史,但它总是关于一个分支。您需要根据自己的情况适当地处理每个分支。
- 谢谢你@Josef。那么,将我的嵌套存储库自动合并到父repo中,保留所有分支、提交和历史记录是不可能的?我必须在整个过程中照顾孩子,可以说?我想我会读"从下到上的Git",看看我是否会想出一种能自动完成所有工作的脚本。你怎么认为?
- 什么是your-first-commit?
- your-first-commit是存储库中的第一个提交,将重新构建历史记录。但是小心那只樱桃采摘,它会在错误/不熟练的手上造成很多混乱。
我需要做同样的事情,这对我很有用:
从母公司回购,
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的所有历史(包括所有分支)。除此之外,子树合并可能是我想要的。
- 我更新了我的问题,我担心子树合并对我来说有点太多了,尽管我承认它主要是出于恐惧和我发现的大量不同的其他策略,以及它(子树合并)不能准确保存历史的证据。
如果这行得通,但值得一试,那就没什么用了。假设SRC在远程服务器上,父服务器在远程服务器上。您可以尝试以下操作。
- git克隆到远程服务器的URL,以使用工具、lib和build克隆repo
- 将远程SRC URL添加到SRC远程报告
- 创建SRC远程回购的跟踪分支,然后在父回购上检查它。
- 将远程跟踪分支合并到主分支中。
- 删除第二个遥控器。