多个git存储库的最佳实践 [英] Best practices for multiple git repositories

查看:134
本文介绍了多个git存储库的最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有大约20个不同的存储库。许多人都是独立的,并且作为图书馆进行编译,但其他人则依赖于他们。

假设我有一个只汇集所有其他存储库的超级项目。

  / superproject [master,HEAD] 
它仅用于运行测试 - 没有真正的开发进行到这里。 / a [master,HEAD]
/ b [master,HEAD]
/ c [master,HEAD]
/ ...
pre>

现在,为每个开发特定的功能或修复( a ),特别是那些需要( b v2.0 c 3.0 )的特定版本的项目,我必须创建一个新的分支:

  / superproject [branch-a,HEAD]<'a'项目的分支
/ a [master]< - 新提交
/ b [v2.0]
/ c [v3.0]

对于 b ,可能需要别的东西,比如 a v0.9 c v3.1

  / superproject [ b,HEAD]<  - 'b'项目的分支
/ a [v0.9]< - 旧版本n比'a'
/ b [master]< - 新提交到这里
/ c [v3.1]< - 比'a'更新的版本
git-submodules
git-subtree ,google的 git-repo , git-slave 等。



如何管理连续整合为这样一个复杂的项目?



编辑



真正的问题是如何运行测试而不必模拟所有其他依赖项目?尤其是当所有项目可能使用不同版本时。
在git子模块中提交后触发Jenkins测试

解决方案

要并行处理多个分支,请尽可能使用并行克隆。 cd 比checkout,clean和check-for-stale-detritus更容易,每次您想要切换时都会重新创建缓存。






就录制您的测试环境而言,您所描述的正是子模块所做的每一个细节。对于这样简单的事情,我将建议您不要使用submodule命令,并在适当时告诉它有关您的设置,并且子模块问题列表中的顶级项目是按键计数。



从您的问题中的设置开始,以下是您如何设置自己在子项目中记录干净构建:

  cd $ superproject 
git init。
git add abc etc
git commit -m为$ thistest录制测试状态

就是这样。您已经提交了一个提交ID列表,即每个回购站中当前签出的提交的ID。实际的内容是在这些回购协议中,而不是这一个,但就git而言,这就是文件和子模块之间的全部区别。 .gitmodules 文件具有帮助克隆的随机注释,主要是一个建议的回购,它应该包含必要的提交以及随机的命令默认注释,但是它的操作很简单,明显。



想检查路径 foo

 (commit =`git rev-parse:foo`; cd foo; git checkout $ commit)

rev-parse从索引中获取foo的内容标识,cd和checkout就是这样。



以下是您如何找到所有子模块以及应该检查哪些内容以重新创建阶段式索引环境:

  git ls-files -s | grep ^ 16 

检查当前索引列出的子模块以及实际检出的内容:

然后你就去了。检查所有子模块中的正确提交吗?

  git ls-files -s | grep ^ 16 |同时读取模式提交阶段路径;做
(cd$ path; git checkout $ commit)
完成

有时候你会在每次结账时携带本地补丁:

  git ls-files -s | grep ^ 16 |同时读取模式提交阶段路径;做
(cd $ path; git rebase $ commit)
完成

和等等。这里有 git submodule 命令,但它们没有做任何你没有看到的东西。对于其他所有的情况,你可以将他们所做的所有事情转化为上面那样的近线。



子模块没有什么神秘的。






持续集成通常通过任何的一大堆工具,我会让别人解决这个问题。


I have around 20 different repositories. Many are independent and compile as libraries but some others have dependencies among them. Dependency resolution and branching is complicated.

Suppose that I have a super project that only aggregates all other repositories. It is used exclusively to run tests -- no real development goes here.

/superproject  [master, HEAD]
    /a         [master, HEAD]
    /b         [master, HEAD]
    /c         [master, HEAD]
    /...

Now, to develop specific features or fixes for each one (a), especially one of those that require specific versions of projects to compile or run (b v2.0 and c 3.0) I have to create a new branch:

/superproject  [branch-a, HEAD]  <-- branch for 'a' project
    /a         [master]  <-- new commits here
    /b         [v2.0]
    /c         [v3.0]

For b, it might be required something else, like a v0.9 and c v3.1:

/superproject  [branch-b, HEAD]  <-- branch for 'b' project
    /a         [v0.9]   <-- older version than 'a'
    /b         [master] <-- new commits go here
    /c         [v3.1]   <-- newer version than 'a'

This becomes even more complex and complicated when implementing common git workflows involving feature branches, hotfix branches, release branches, etc. I was advised to (and advised against) using git-submodules, git-subtree, google's git-repo, git-slave, etc.

How can I manage continuous integration for such a complex project?

EDIT

The real question is how to run tests without having to mock all other dependent projects? Especially when all projects might use different versions. Trigger Jenkins tests after commits in git submodules

解决方案

For working with multiple branches in parallel, use paralleled clones if possible. cd is an awful lot easier than checkout and clean and check-for-stale-detritus and recreate-caches every time you want to switch.


So far as recording your test environments goes, what you're describing is exactly what submodules do, in every detail. For something this simple, I'm going to recommend setting yourself up without using the submodule command at all, and telling it about your setup once you're comfortable and the top item on your submodule-issues list is keystroke count.

Starting from the setup in your question, here's how you set yourself up to record clean builds in the subprojects:

cd $superproject
git init .
git add a b c etc
git commit -m "recording test state for $thistest"

That's it. You've committed a list of commit id's, i.e. the id's of the currently-checked-out commits in each of those repos. The actual content is in those repos, not this one, but that's the entire difference between files and submodules so far as git's concerned. The .gitmodules file has random notes to help cloners, mainly a suggested repo that's supposed to contain the necessary commits, and random notes for command defaults, but what it's doing is easy and obvious.

Want to check out the right commit at path foo?

(commit=`git rev-parse :foo`; cd foo; git checkout $commit)

The rev-parse fetches the content id for foo from the index, the cd and checkout do that.

Here's how you find all your submodules and what should be checked out there to recreate the staged aka indexed environment:

git ls-files -s | grep ^16

Check what your current index lists for a submodule and what's actually checked out there:

echo $(git rev-parse :$submodule; (cd $submodule; git rev-parse HEAD))

and there you go. Check out the right commits in all your submodules?

git ls-files -s | grep ^16 | while read mode commit stage path; do
        (cd "$path"; git checkout $commit)
done

Sometimes you're carrying local patches you want applied to every checkout:

git ls-files -s | grep ^16 | while read mode commit stage path; do
        (cd $path; git rebase $commit)
done

and so forth. There's git submodule commands for these, but they're not doing anything you don't see above. Same for all the rest, you can translate everything they do into near-oneliners like the ones above.

There's nothing mysterious about submodules.


Continuous integration is generally done with any of a whole lot of tools, I'll leave that for someone else to address.

这篇关于多个git存储库的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆