【问题标题】:How to merge nested git repo into parent repo, retaining history?如何将嵌套的 git repo 合并到父 repo 中,保留历史记录?
【发布时间】:2013-01-28 00:28:44
【问题描述】:

现在我知道大多数 git 专家会立即想到 git rebase,但我在更一般的意义上使用“rebase”这个词:我的项目结构如下:

.
..
.git
tools
lib
src
    .git
build

../src 目录显然都是 git 存储库,并且每个都有很长的历史和大量的提交。 . 中的存储库会忽略 src 目录(这是它自己的存储库)。

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

我的问题是我不知道如何让这个存储库保留现在是src 中存储库一部分的历史记录。甚至可能吗?这就是我所说的“变基”的意思——如果./src/.git 在一些 N 次提交中跟踪./src/main.c 的更改,那么我想保留这些更改并让它们成为新存储库./.git 的一部分。相同的历史记录,重新定位文件路径。

更新

从我收集到的 SO 中,子树合并不是我想要的。简而言之,它比我需要的要多得多。我只需要旧存储库的内容,将 所有分支 的开发和所有提交、标签等一起看起来好像它们始终是父存储库的一部分。从本质上讲,唯一的变化是文件本身的路径 - 在子仓库跟踪 ./main.c 之前,新仓库现在将跟踪 ./src/main.c,因为正如我所听说的,git 跟踪内容,而不是文件,然后更改像上面这样的文件路径和对这些路径的引用,应该是相当简单的,对吗?

【问题讨论】:

  • 向谷歌询问“子树合并”,这就是你想要的。
  • 我至少花了一个小时,得出的结论是子树合并和子模块都不适合我。子树合并不仅保留了历史,还保留了新旧仓库之间的链接——而我的旧仓库将被淘汰和丢弃。子模块是毫无疑问的,因为我的 repos 是非常紧密耦合的。我发现以下答案最适合我,但我真的很想合并 all 分支,而不仅仅是 master:stackoverflow.com/questions/13040958/…

标签: git


【解决方案1】:

快速简便的方法:

重命名 src 中的所有文件,因此它们将以 src/ 开头。将 src repo 添加为远程,获取和合并。删除旧的 src repo,现在一切都在 ./.

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

历史重写:

要使这个合并不可见,您需要使用git filter-branch --tree-filter 在 src 存储库中添加 src/ 前缀。然后将此作为远程添加到./ 存储库并获取它(尚未合并)。为了很好地融合历史,您需要重新排序提交。使用git log --date-order master src/master 以正确的顺序检索这些提交并挑选它们:

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

这基本上会对您的提交进行合并排序并将它们排列到线性历史记录中。

这不会保留您的合并,所以除非您有平坦的历史记录,否则不要这样做。在这种情况下,只使用 filter-branch 然后进行正常的合并。

【讨论】:

  • 我不确定采摘樱桃 - 我想保留整个历史,没有例外。我还想保留 all 分支,而不仅仅是 master。你的解决方案会奏效吗?
  • 如果你的历史更长更复杂,cherry-pick 部分是个坏主意,但 filter-branch 和 merge 可以正常工作。但无论如何,如果运气好的话,您可以在合并后使用交互式 rebase (-i) 重新排列提交。我写的只是保留历史,但它总是关于一个分支。您需要根据自己的情况适当处理每个分支。
  • 谢谢@Josef。那么,将我的嵌套存储库自动合并到父存储库中,保留所有分支、提交和历史记录,是不可能的吗?我必须照看这个过程,可以这么说吗?我想我会阅读“自下而上的 git”,看看我是否想出了某种可以自动完成所有工作的脚本。你怎么看?
  • 什么是your-first-commit
  • your-first-commit 是存储库中的第一个提交,历史将被重建。但是要小心挑选樱桃,它会在错误/不熟练的手中造成很多混乱。
【解决方案2】:

使用子树合并。

我会列出这些步骤,但它们在这个问题的答案中:How do you merge two git repositories?

【讨论】:

  • 两个仓库中名称相同的分支会怎样?而且,据我所知,合并涉及一个分支,而我想要 src 的所有历史记录(带有 all 分支)。除此之外,子树合并可能是我想要的。
  • 我已经更新了我的问题,我担心子树合并对我来说有点太多了,尽管我承认这主要是出于恐惧和我发现的大量不同的其他策略,并证明它(子树合并)不会准确地保留历史记录。
【解决方案3】:

如果这行得通,则没有真正的用处,但值得一试。假设 src 在远程服务器上,而父级在远程服务器上。您可以尝试以下方法。

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

【讨论】:

    【解决方案4】:

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

    来自父仓库,

    git remote add -f subrepo git@github.com: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/

    【讨论】:

      猜你喜欢
      • 2021-06-19
      • 1970-01-01
      • 1970-01-01
      • 2022-06-14
      • 2021-09-19
      • 2013-10-23
      • 1970-01-01
      • 2015-06-04
      • 1970-01-01
      相关资源
      最近更新 更多