假设我有一个这样的设置
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中有什么可以帮助我的吗?
也许,简单地(类似于前面的答案,但使用更简单的命令)在每个单独的旧存储库中进行提交,将内容移动到一个适当命名的子目录中,例如:
$ 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
...
然后您将保存历史记录,但将继续进行单个回购。
合并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
@MiniQuark解决方案帮助了我很多,但不幸的是,它没有考虑到源存储库中的标记(至少在我的情况下)。以下是我对@ mini夸克答案的改进。
First create directory which will contain composed repo and merged repos, create directory for each merged one.
$ mkdir new_phd
$ mkdir new_phd/code
$ mkdir new_phd/figures
$ mkdir new_phd/thesis
Do a pull of each repository and fetch all tags. (Presenting instructions only for code sub-directory)
$ cd new_phd/code
$ git init
$ git pull ../../original_phd/code master
$ git fetch ../../original_phd/code refs/tags/*:refs/tags/*
(This is improvement to point 2 in MiniQuark answer) Move the content of new_phd/code to new_phd/code/code and add code_ prefeix before each tag
$ git filter-branch --index-filter 'git ls-files -s | sed "s-\t\"*-&code/-" | GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' --tag-name-filter 'sed "s-.*-code_&-"' HEAD
After doing so there will be twice as many tags as it was before doing filter-branch. Old tags remain in repo and new tags with code_ prefix are added.
$ git tag
mytag1
code_mytag1
Remove old tags manually:
$ ls .git/refs/tags/* | grep -v "/code_" | xargs rm
Repeat point 2,3,4 for other subdirectories
Now we have structure of directories as in @MiniQuark anwser point 3.
Do as in point 4 of MiniQuark anwser, but after doing a pull and before removing .git dir, fetch tags:
$ git fetch catalog refs/tags/*:refs/tags/*
Continue..
这是另一个解。希望它能帮助别人,它帮助了我:)
Actually, git-stitch-repo now supports branches and tags, including annotated tags (I found there was a bug which I reported, and it got fixed). What i found useful is with tags. Since tags are attached to commits, and some of the solutions (like Eric Lee's approach) fails to deal with tags. You try to create a branch off an imported tag, and it will undo any git merges/moves and sends you back like the consolidated repository being near identical to the repository that the tag came from. Also, there are issues if you use the same tag across multiple repositories that you 'merged/consolidated'. For example, if you have repo's A ad B, both having tag rel_1.0. You merge repo A and repo B into repo AB. Since rel_1.0 tags are on two different commits (one for A and one for B), which tag will be visible in AB? Either the tag from the imported repo A or from imported repo B, but not both.
git-stitch-repo helps to address that problem by creating rel_1.0-A and rel_1.0-B tags. You may not be able to checkout rel_1.0 tag and expect both, but at least you can see both, and theoretically, you can merge them into a common local branch then create a rel_1.0 tag on that merged branch (assuming you just merge and not change source code). It's better to work with branches, as you can merge like branches from each repo into local branches. (dev-a and dev-b can be merged into a local dev branch which can then be pushed to origin).