当前位置:  开发笔记 > 编程语言 > 正文

组合多个git存储库

如何解决《组合多个git存储库》经验,为你挑选了7个好方法。

假设我的设置看起来很像

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可以帮助我吗?



1> MiniQuark..:

这是我在这里给出的解决方案:

    首先对您的phd目录进行完整备份:我不想为您失去多年的辛勤工作负责!;-)

    $ cp -r phd phd-backup
    

    将内容移动phd/codephd/code/code,并修复历史记录,使其看起来一直存在(这使用git的filter-branch命令):

    $ cd phd/code
    $ 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' HEAD
    

    对于相同的内容phd/figuresphd/thesis(只需更换codefiguresthesis).

    现在您的目录结构应如下所示:

    phd
      |_code
      |    |_.git
      |    |_code
      |         |_(your code...)
      |_figures
      |    |_.git
      |    |_figures
      |         |_(your figures...)
      |_thesis
           |_.git
           |_thesis
                |_(your thesis...)
    

    然后在根目录中创建一个git存储库,将所有内容放入其中并删除旧存储库:

    $ cd phd
    $ git init
    
    $ git pull code
    $ rm -rf code/code
    $ rm -rf code/.git
    
    $ git pull figures --allow-unrelated-histories
    $ rm -rf figures/figures
    $ rm -rf figures/.git
    
    $ git pull thesis --allow-unrelated-histories
    $ rm -rf thesis/thesis
    $ rm -rf thesis/.git
    

    最后,你现在应该拥有你想要的东西:

    phd
      |_.git
      |_code
      |    |_(your code...)
      |_figures
      |    |_(your figures...)
      |_thesis
           |_(your thesis...)
    

这个过程的一个好处是它将保留非版本化的文件和目录.

希望这可以帮助.


只是一个字的警告不过的:如果你的code目录已经有一个code子目录或文件,事情可能会去非常错误的(同为figuresthesis的课程).如果是这种情况,只需在完成整个过程之前重命名该目录或文件:

$ cd phd/code
$ git mv code code-repository-migration
$ git commit -m "preparing the code directory for migration"

当程序完成后,添加最后一步:

$ cd phd
$ git mv code/code-repository-migration code/code
$ git commit -m "final step for code directory migration"

当然,如果code子目录或文件没有版本化,只需使用mv而不是git mv,并忘记git commits.


感谢这个片段 - 它完全符合我的需要(一旦我考虑到Mac OS X sed没有处理"\ t"(我不得不使用^ V ^ I代替).
我一开始无法工作,最终在另一个旧留言板上找到问题的解决方案.在最后一行,我不得不在文件名周围加上引号:`mv"$ GIT_INDEX_FILE.new""$ GIT_INDEX_FILE"'HEAD`然后效果很好!
小心!MacOS X不使用sed的GNU扩展,因此它不知道序列\ t.结果是混乱的历史!我的解决方案是将代码粘贴到脚本文件中,在其中写入一个真正的字符.在终端中,可以按ctrl + v输入一个选项卡,然后写入.我没有尝试过克雷格的解决方案
看完了(2)!另请注意,如果某些文件或目录包含连字符(' - '),则sed命令将失败.在这种情况下,你可以用's~\t~&code /〜'之类的东西替换它.在这里,应用相同的逻辑,注意名称中的"〜"
funky filter-branch命令来自git的filter-branch手册页.你应该说:a)它应该被正确归因b)我不会仅仅因为有人,即使声誉很高,也把它​​发布在StackOverflow上.知道它来自手册我会.
@CraigTrader考虑安装`gnu-sed`(例如使用`brew`).它平滑了不兼容性:)

2> Aristotle Pa..:

git-stitch-repo将处理git-fast-export --all --date-order命令行上给出的git存储库的输出,并创建一个适合于此的流git-fast-import将创建一个新的存储库,其中包含一个新的提交树中的所有提交,该提交树尊重所有源存储库的历史记录.


呃,这是第三方工具,不是git的一部分... :-)
这是一个外部脚本,答案太短,并没有真正帮助,这个脚本有合并提交的问题,没有多少人会处理Perl或CPAN,这在答案中没有得到很好的解释.所以... -1,抱歉.

3> imz -- Ivan ..:

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

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

然后你将保存你的历史,但将继续一个回购.



4> Leif Gruenwo..:

您可以尝试子树合并策略.它会让你将repo B合并到repo A中.优点git-filter-branch是它不需要你重写你的历史记录(打破SHA1总和).


@Tymek(对不起安全漏洞后,kernel.org的部分内容仍然失效).它打破了传入的回购B的SHA1.但A保持不变.
以下是该文档的镜像http://ftp.sunet.se/pub/Linux/kernel.org/software/scm/git/docs/howto/using-merge-subtree.html

5> Gareth..:

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

在这种情况下,您需要从filter-branch中排除初始修订版 - HEAD即将结尾处更改为[SHA of 2nd revision]..HEAD- 请参阅:

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


谢谢!我一直在摸不着为什么这不起作用!回购确实来自SVN.

6> MichK..:

@MiniQuark解决方案帮助了我很多,但不幸的是它没有考虑源代码库中的标签(至少在我的情况下).以下是我对@MiniQuark答案的改进.

    首先创建包含组合repo和merged repos的目录,为每个合并的目录创建目录.

    $ mkdir new_phd
    $ mkdir new_phd/code
    $ mkdir new_phd/figures
    $ mkdir new_phd/thesis

    拉动每个存储库并获取所有标记.(仅针对code子目录提供说明)

    $ cd new_phd/code
    $ git init
    $ git pull ../../original_phd/code master
    $ git fetch ../../original_phd/code refs/tags/*:refs/tags/*

    (这是改进点2 MiniQuark答案)移动的内容new_phd/codenew_phd/code/code,并添加code_每个前prefeix 标签

    $ 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 - .* - 代码_& - "'HEAD

    这样做之后,标签的数量将是过滤分支之前的两倍.旧标签保留在repo中,并code_添加带前缀的新标签.

    $ git tag
    mytag1
    code_mytag1

    手动删除旧标签:

    $ ls .git/refs/tags/*| grep -v"/ code_"| xargs rm

    对其他子目录重复2,3,4点

    现在我们有@MiniQuark anwser point 3中的目录结构.

    如同MiniQuark anwser的第4点那样,但是在执行拉动之后和删除.git目录之前,请获取标记:

    $ git fetch catalog refs/tags/*:refs/tags/*

    继续..

这只是另一种解决方案.希望它对某人有所帮助,它帮助了我:)



7> robinst..:

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

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

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

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

推荐阅读
无名有名我无名_593
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有