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

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

其他回答

借助IntelliJ IDEA Community Edition中的git集成,我手动将3个git存储库合并为一个。

Create a new repo, add a new commit to the master branch with an empty README.md file. Add three remotes for the new repo, using the name of the 3 repositories and the remote URL of them respectively. Run Git Fetch. Create a new local branch named temp based on the master branch, so we can start over without pollute the master branch. Checkout the temp branch. Select to only show commits of one remote branch(one repository). Select all the commits and right click to Cherry-Pick them. Create directory structure for this repository, then move the files into it and commit. Repeat the step 4 to 6 for the other 2 remote branch(repository). When everything is OK, merge all the changes in the temp branch into master branch.

然后添加主分支的原始远程URL并推送到它。

这个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

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

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

这是另一个解。希望它能帮助别人,它帮助了我:)

你建议的顺序

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