2016-12-05 33 views
2

我的情况是,我有两个Git仓库,我需要合并到一个仓库(实际上有更多仓库,但我可以从两个开始)。如何合并几个Git回购为一个并交织历史

两个储存有:

  • 的主要仓库,一个
  • 第二个存储库,B

在存储库中的代码在储存库(但反之亦然)上的代码的相关性,和两个库的历史彼此跟随以时间的方式 - 大致(即一个具体提交回购B通常需要提交回购A具有非常类似的提交时间)。

这两个存储库中存在冲突的分支和标签名称(不保证它们属于一起),但仅需要保留A的参考。

新库的要求,Ç,分别是:从一个

  1. 所有裁判(分支和标签),需要保留。
  2. 只有主分支承诺B需要保留(即由git log --first-parent master报告的提交)。
  3. 来自每个源库中的文件应该被放入新的存储库的子文件夹(即,从文件应当进入A/,并将这些文件形成应当进入B/)。
  4. 当检查出具体的承诺(包括合并之前的提交完成)在库Ç(例如某个发布标签)兼容的文件形成两个源库应在目录A/B/(内至少被发现提交或两个)。

到目前为止,我已经尝试了多种方法,包括thisgit-stitch-repo,没有成功(他们没有满足上述要求)。在每个回购的所有文件

  • 移动到使用Git滤波器分支的子目录:

    在这一点上,我已成功地。例如。回购

 
mkdir A 
mv * .gitignore A/ 2> /dev/null 
git commit -a -m 'DROPME' > /dev/null 
git filter-branch --tag-name-filter cat --index-filter 'git ls-files -s | sed "s-\t\"*-&A/-" | GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE" ||:' -- --all 
git reset --hard origin/master 
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d 
  • 导入回购成使用git fast-export/fast-import
  • 设备一种生成映射的方法,使得对于A中的给定SHA,存在应该从B插入的零个,一个或多个SHA的列表。

我现在所期待的,是的git filter-branch一些聪明的使用应使我从插入选定提交入一个主分支。但是如何?

回答

1

解决方案结果比我所希望的要多得多。它涉及操纵并合并两个(或更多)git fast-export流的输出,并使用git fast-import将它们导入到一个新的存储库中。

简而言之,新的fast-import流通过遍历两个输入流生成,并根据来自主分支的日期排序日志在它们之间来回切换。

我已经在一个名为join-git-repos.py的Python脚本中实现了解决方案,我把它放在一个GitHub存储库here中。

1

首先,将repo A中的所有内容都移动到子目录A /中。没什么特别的,只是git mv。这保留了A中的所有分支和标签并提交ID。

然后使用git subtree在目录B /中使B的主分支成为A的子树。

git subtree add -P B/ <remote for B> master 

你完成了。


如果您希望A上的旧版本标签也反映当时在B中的内容...... oy。您可以在每次发布标签之前将B合并到A,而不会让您的历史记录太糟糕。

你有这个。

  * - * - *   * - * - * branch 
    v1 /  \ v2 /
* - * - * - * - * - * - * - * - * - * master 
           /
    * -- * ---- * - * - * --------- * 

提交的底线是B. B的提交是按照与A的时间一致的方式排列的。

而你想要这样的东西。

  * - * - *   * - * - * branch 
    v1 /  \ v2 /
* * * - * - * - * - * * * - * - * - * master 
    |     |   /
    * -- * ---- * - * - * --------- * 

这已将B合并到每个发布标记之前的A中。这避免了构成A和B一起开发的人造历史。

我不知道如何以自动化的方式做到这一点。问题是rebase不保留标签,只合并。因此,将合并提交添加到v1将失去v2标记,我不知道如何确定基本提交的原始提交是什么。

祝你好运。

+1

我会尝试一下,但我不明白这个解决方案如何能够满足要求4的问题。或者我错过了什么? –

+0

@ m-bitsnbites你想从回购A的旧版本标签A猜测当时回购B中的内容?这会让你的历史糟糕透顶。我不知道它是否在逻辑上是可能的,同时还保留了A. – Schwern

+0

@ m-bitsnbites的分支历史记录我将汇总的存储库结构进行了说明,这是IMO最好的折衷方案,但我不知道如何执行以自动化的方式进行转换。 – Schwern