git多个存储库管理

时间:2012-10-03 00:58:24

标签: git project-management git-svn

我正在开发一个项目,我们使用git管理外部libs / headers和qa。以下是每个开发人员的目录结构:

~/dev/proj 
~/dev/ext 
~/dev/qa

proj,ext和qa是不同的 git存储库。在svn下,这些目录的同步很简单:〜/ dev下的单个更新将以递归方式更新所有这些更新。使用git,我们需要为每个目录单独执行'git pull'。这不好;有人会忘记更新(git pull)其中一个目录,他的项目将不同步(例如新的qa不会传递旧代码)。我查看了'git submodules'并且没有为'git pull'提供单点同时更新这三个单独的模块[更正:我在这里错了,但请阅读我的回答below]。< / p>

你可能会说我们应该将proj,ext和qa放在同一个git存储库中,但我认为这可能违背了将不同概念保存在不同存储库中的git哲学。

有没有人有一个解决方案(除了编写一个脚本来对〜/ dev下的每个目录进行git pull)这个琐碎的问题?

谢谢,

俺答

9 个答案:

答案 0 :(得分:3)

我的理念是:如果我总是需要将X和Y拉在一起,那么逻辑上它们属于同一个存储库。如果存在适当的隔离,使用子模块才有意义 - 想想外部供应商库,您不希望无法立即进行更新,并且您不希望您的团队能够直接编辑它们 - 这是有道理的。但是,无论你如何切片,它都会增加步数。我坚持“把它放在一个存储库中,如果它是一个项目”,不管理论上我怎么能把它分解为更像“git-like”。

答案 1 :(得分:3)

Herr Doktor,

您正在将苹果与橙子进行比较。 git-submodules类似于svn:externals,也就是svn-submodules。实际上,当您使用-r在特定版本上附加svn子模块时,行为几乎相同。要使用svn-submodules进行提交,您必须分别在每个子模块目录中提交,就像使用git-submodules一样。

但是有一个很大的不同:大多数开发人员,至少在开发的某个阶段,更喜欢附加到每个子模块的分支,git-submodule不支持。这对协调发展很有用。 (谷歌的 Repo 工具是 Git 的包装,意味着与 Gerrit 一起使用,这是一种代码审查工具,有点类似但请相信我:远离 Repo 。它解决了另一个问题。)巨大的缺点是你无法恢复代码库的精确轮廓。这似乎好一段时间,但我听说过讨厌的战争故事。

替代方案不是 Subversion ,而只是一个存储库,可以是 Git Subversion ,或者其他什么。但你真的想要一个单独的回购和多个回购的组合,对吗?你想要每个人的好处。所以你需要一个更复杂的解决方案。

一个想法是拥有一个项目仓库,在那里进行大部分开发,再加上几个单独的仓库,您可以从中分发模块:

proj/.git
proj/subA
proj/subB
subA/.git
subB/.git

您可以使用 rsync 在它们之间移动代码。美丽是你在发展和分配之间做出了明显的区分。您可以正常开发大型项目,包括分支,合并等。当您准备将子目录作为库分发时,您可以准确地确定所需库的哪个版本,然后将其复制到自己的存储库中。当您需要合并而不仅仅是复制时,有git subtree merge strategy

还有另一个基于子树合并策略的系统。它被称为git-subtrees,它是git-1.7.11的一部分。 Here是对其操作的一个很好的描述。你可以从图片中看到它的时间线看起来很混乱,但从功能上来说它正是你想要的。 Here是最近的一篇文章,提出了很好的建议。

如果你不介意额外的更新&#39; git-submodules的一步,但你对它如何处理冲突感到不安,你可以尝试giternal。作者已经包含了一个脚本,用于显示其行为与git-submodules和braid(用于销售子模块,但不合并它们)的比较。

就个人而言,我喜欢git-slave,这是围绕git的简单包装。基本上,它会将gits命令作为git命令应用于您的所有回购。这真的只是一种便利。它非常容易理解,对单个存储库没有任何影响,并且非常适合分支交换(git-subtrees尚不支持)。

答案 2 :(得分:2)

您仍然可以使用子模块。

git submodule update

将一次更新所有子模块。

答案 3 :(得分:1)

我们试过'git submodule',但效果不理想。似乎git子模块是为那些变化不大的模块而设计的。以下是制作和推送更改到任何模块的步骤:

cd ~/dev/proj
git checkout master
git pull
... make changes to your files ...
git commit -a -m "comment"
git push
cd ..   
git commit -a -m "comment"
git push

必须在〜/ dev下为每个模块重复这个。对不起,我发现这很荒谬。在svn中,同样的事情由

完成
cd ~/dev
svn commit -m "done in one line"

我理解git比svn的好处但是缺乏适当的子模块支持和缺乏良好的大文件支持可能会让我们从git切换到svn(除非我们在这里得到一个解决方案 - 我宁愿留下用git)。老实说,我很惊讶这根本没有出现在git中。不同的项目一直共享[现场]的常用模块。

我反对将proj,ext和qa放在同一个存储库中,因为

  • ext将与其他项目(存储库)共享
  • qa应该能够在没有代码的情况下签出(克隆)

俺答

答案 4 :(得分:1)

答案 5 :(得分:0)

恕我直言,子模块是去这里的方式。

不要问你是否总是需要X和Y,你应该问问自己,你是否总是希望X和Y的完全相同的版本在一起。

Git Submodules为您提供了这个非常强大的工具,可以快速修复X中的错误,而无需同时更新Y.

例如,如果您正在开发一个在不同操作系统上运行的产品(例如,比如Mac OS X和Windows),那么将操作系统特定代码分成单独的子模块可能是有意义的。如果不同的人在这些不同的操作系统端口上工作,则尤其如此。使用git子模块可以轻松地将一个操作系统的修复程序部署到客户,而无需在另一个操作系统上完成QA过程。

另一个非常强大的用例是“工作区”模块。您只需要一些本地模块(例如/Workspace),然后添加您正在使用的所有依赖项。

git子模块的优点在于它不仅记录您使用的模块,还记录它们的特定修订版。在修复bug时,我经常要测试某些依赖项的特定版本 - git子模块允许我在工作区模块的历史记录中轻松记录这些,允许我稍后轻松回到那个确切的状态。

答案 6 :(得分:0)

我遇到了同样的问题并写了一个程序(bash脚本)来做到这一点:gws

大致的想法如下:

  1. dev/.projects.gws

    中创建项目路径和网址列表
    work/proj  | https://...
    perso/ext  | git@github.com:...
    perso/qa   | https://...
    
  2. 使用gws命令之一:
    • init :用于从当前文件夹树中的现有存储库自动创建.projects.gws文件。
    • 更新:克隆缺少的本地存储库,例如在.projects.gws中添加项目时。
    • 状态:显示所有存储库的状态(干净,未跟踪的文件,未经修改的更改,...)。
    • 获取:在所有存储库中执行git fetch(然后状态将能够检测与原始存储库之间的差异,如果它在中间进行了修改)。
    • ff :在所有存储库中执行git快进工具
    • 检查:验证工作区的状态(已知,未知,工作区中缺少存储库)
  3. 然后可以使用git对.projects.gws文件进行版本控制,并在许多计算机(工作,家庭,笔记本电脑......)上使用。还可以编写.ignore.gws文件以在本地忽略一些具有正则表达式的路径,例如:忽略家庭计算机上work/的{​​{1}}文件夹中的存储库。

    有关详细信息,请参阅Readme

    我每天都使用它,它符合我的需要(也许你的需要)。请注意,当我有时间时,我打算用Python重写它(在另一个名字下)。原因是代码开始难以在bash中管理,我想添加更多功能(例如添加对mercurial,darcs的支持......)。

答案 7 :(得分:0)

git-multi就是答案。 https://github.com/grahamc/git-multi

有git-multi设置,并且在&#39;〜/ dev&#39;文件夹克隆你需要的所有回购。

来自&#39;〜/ dev&#39;跑&#34; git multi pull&#34;或者&#34; git multi status&#34;和其他命令,实习生在所有子仓库中运行相应的命令。

答案 8 :(得分:0)

我编写了一个名为 gita 的命令行工具来管理多个存储库。它并排显示已注册存储库的状态,并从任何工作目录中委派 git 命令/别名。例如

enter image description here

颜色和额外符号显示本地/远程关系和编辑状态。

如果您有许多存储库,您可以将它们分组到不同的组并在组上执行操作,或为组设置上下文。