2025-03-16 09:00:01

组合多个git存储库

假设我有一个这样的设置

phd/code/
phd/figures/
phd/thesis/

由于历史原因,这些都有自己的git存储库。但是我想把它们合并成一个,这样可以简化一些。例如,现在我可能要做两组更改,并且必须做一些类似的事情

cd phd/code
git commit 
cd ../figures
git commit

(现在)只要能表演就好了

cd phd
git commit

似乎有几种方法可以使用子模块或从我的子存储库中提取,但这比我想要的要复杂一些。至少让我满意的

cd phd
git init
git add [[everything that's already in my other repositories]]

但这似乎不是一句俏皮话。git中有什么可以帮助我的吗?


当前回答

你可以尝试子树合并策略。它可以让你将回购B合并到回购A。相对于git-filter-branch的优点是它不需要你重写回购A的历史记录(破坏SHA1和)。

其他回答

也许,简单地(类似于前面的答案,但使用更简单的命令)在每个单独的旧存储库中进行提交,将内容移动到一个适当命名的子目录中,例如:

$ cd phd/code
$ mkdir code
# This won't work literally, because * would also match the new code/ subdir, but you understand what I mean:
$ git mv * code/
$ git commit -m "preparing the code directory for migration"

然后将三个单独的回购合并为一个新的,通过这样做SMTH:

$ cd ../..
$ mkdir phd.all
$ cd phd.all
$ git init
$ git pull ../phd/code
...

然后您将保存历史记录,但将继续进行单个回购。

亚里士多德Pagaltzis回答的git-stitch-repo只适用于具有简单线性历史的存储库。

MiniQuark的答案适用于所有存储库,但它不处理标记和分支。

我创建了一个与MiniQuark描述的工作方式相同的程序,但是它使用一个合并提交(有N个父级),并且还重新创建了指向这些合并提交的所有标记和分支。

有关如何使用它的示例,请参阅git-merge-repos存储库。

你建议的顺序

git init
git add *
git commit -a -m "import everything"

将工作,但您将丢失提交历史。

git-filter-branch解决方案工作得很好,但请注意,如果你的git repo来自SVN导入,它可能会失败,并发出如下消息:

Rewrite 422a38a0e9d2c61098b98e6c56213ac83b7bacc2 (1/42)mv: cannot stat `/home/.../wikis/nodows/.git-rewrite/t/../index.new': No such file or directory

在这种情况下,你需要从过滤器分支中排除最初的修订——即将最后的HEAD更改为[SHA of second revision]。头部-见:

http://www.git.code-experiments.com/blog/2010/03/merging-git-repositories.html

我创造了一个工具来完成这项任务。使用的方法是类似的(内部做一些东西,如——filter-branch),但更友好。是GPL 2.0

http://github.com/geppo12/GitCombineRepo