git:将一个存储库的历史记录复制(cherry-pick)到另一个存储库的目录中


git: copy (cherry-pick) history of one repository into a directory of another

我有两次休息。第一次回购(我们称之为A)是不久前开始的;第二次回购(B)是最近开始的。现在我们认为我们宁愿把B作为A的一个子目录,所以我想这样做,但要保留B的提交历史。

  • 我想要完整的提交历史。也就是说,我不想仅仅把B的历史压缩成一个补丁,然后将其作为新的提交放到A中。
  • 我不想保留b的精确sha1(我知道这可能是不可能的)。
  • 我不在乎保留B的承诺的时间戳(尽管这样做很好)。
  • 我不想保留作者身份。
  • 我只想保留B提交的每个提交的差异/补丁。
  • 我不想保留任何关于两个独立存储库的概念。事实上,我只想有一个前进的方向。
  • 我不需要b是a的git子模块,它有自己的.gitdir或类似的东西。

在任何操作结束时,我希望满足三个标准:

  • 在b的HEAD中看到的文件和目录位于a的子目录中,即/path/to/repoB/somefile.js位于/path/to/repoA/B/somefile.js中。
  • B的所有提交消息都按时间顺序出现在A的提交结束时。
  • 每个提交的差异都是可用的(可由git log等查看)。
  • 一些例子可以阐明我的意图:

  • 在回购B中,承诺1是增加file.txt
  • commit 2是编辑file.txt
  • 因此,在回购协议A中,我需要两个新的承诺:
  • 回购A承诺98:增加B/file.txt
  • repo a commit 99:编辑B/file.txt
  • 编辑:

    子目录中的合并Git存储库已被提议为我问题的副本。我承认这与我的要求非常接近,并且有几个很好的答案。我在那里试过了subtree的答案,还有rebase --onto的答案。两者都非常接近,但都不令人满意:subtree不允许git log不提及path/to/file/without/repo-subdir(我将b移入repo-subdir)而通过存储库历史查看历史;rebase --onto不允许b的历史从a的HEAD中可见。


    这就是我最后做的。多亏了来自自由节点(IRC)的#gitatrus引导我朝正确的方向前进。

  • 在回购B中,建立一个新的分支机构:git checkout -b indir
  • 在repo b中,mkdir b-subdir,其中b-subdir是dir,我希望b以a的dir树结束。
  • 在repo b中,git mv [...] b-subdir将所有东西(.git/b-subdir/本身除外)移入b-subdir
  • 向回购B承诺这一行动。
  • 推到原点(push -u origin HEAD)。
  • 回购A:git remote add repo-b ssh://......../repo-b.git
  • 江户十一〔11〕。
  • 埃多克斯1〔12〕
  • 这允许我查看来自repo b的任意文件的完整历史记录(使用git log--follow开关),而不需要从文件路径中去掉b-subdir/前缀。使用git subtree,如果去掉它,您只会在b中看到文件的历史(如果不去掉,您会在a中看到历史)。