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中有什么可以帮助我的吗?


当前回答

这个bash脚本可以解决sed制表符问题(例如在MacOS上)和丢失文件的问题。

export SUBREPO="subrepo"; # <= your subrepository name here
export TABULATOR=`printf '\t'`;
FILTER='git ls-files -s | sed "s#${TABULATOR}#&${SUBREPO}/#" |
  GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
  git update-index --index-info &&
  if [ -f "$GIT_INDEX_FILE.new" ]; then mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE; else echo "git filter skipped missing file: $GIT_INXEX_FILE.new"; fi'

git filter-branch --index-filter "$FILTER" HEAD

这是迷你夸克,马里乌斯-布图克和瑞恩的哨子的组合。为他们干杯!

其他回答

你建议的顺序

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

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

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

$ 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
...

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

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

合并mainProject中的secondProject:

A)在第二个项目中

git fast-export --all --date-order > /tmp/secondProjectExport

B)在主项目中:

git checkout -b secondProject
git fast-import --force < /tmp/secondProjectExport

在这个分支中完成你需要做的所有繁重的转换并提交它们。

C)然后回到主分支和两个分支之间的经典合并:

git checkout master
git merge secondProject

我把解也写在这里。它基本上是一个围绕git过滤器分支的相当简单的bash脚本包装器。像其他解决方案一样,它只迁移主分支,而不迁移标签。但是完整的主提交历史被迁移了,它是一个简短的bash脚本,因此用户应该相对容易检查或调整。

https://github.com/Oakleon/git-join-repos