5

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

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

proj、ext 和 qa 是不同的git 存储库。在 svn 下,这些目录的同步很简单:~/dev 下的单个更新将递归地更新所有这些目录。使用 git,我们需要为每个目录分别执行“git pull”。这不好;有人总是会忘记更新(git pull)这些目录之一,他的项目将不同步(例如,新的 qa 不会与旧代码一起通过)。我查看了“git submodules”,它没有为“git pull”提供一个点来同时更新这三个单独的模块[更正:我在这里错了,但请阅读下面的答案]

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

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

谢谢,

阿尔坦

4

9 回答 9

4

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

于 2012-10-03T01:02:16.100 回答
3

博士先生,

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

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

您的替代方案不是Subversion,而只是一个单一的存储库,可以在GitSubversion或其他任何地方。但是您实际上想要单个回购和多个回购的组合,对吗?你想要每个人的好处。所以你需要一个更复杂的解决方案。

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

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

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

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

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

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

于 2012-10-04T05:40:34.213 回答
2

您仍然可以使用子模块。

git submodule update

将一次性更新所有子模块。

于 2012-10-03T01:01:30.510 回答
2

我们尝试了“git submodule”,但并不令人满意。似乎 git submodule 是为变化不大的模块设计的。以下是对任何模块进行更改和推送更改的步骤:

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 应该能够在没有代码的情况下被检出(克隆)

阿尔坦

于 2012-10-03T19:40:48.957 回答
1

使用 git-repo

https://github.com/android/tools_repo http://source.android.com/source/using-repo.html

android 开发者使用它来管理多个存储库

https://github.com/android/tools_repo/blob/master/docs/manifest_xml.txt

和 android repo 清单存储库

https://android.googlesource.com/platform/manifest/+/master

于 2014-03-13T18:39:04.233 回答
1

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

有 git-multi 设置,并在 '~/dev' 文件夹下克隆你需要的所有 repos。

并从 '~/dev' 运行“git multi pull”或“git multi status”等命令,实习生在所有子仓库中运行相应的命令。

于 2014-07-07T18:14:08.730 回答
0

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

大致思路如下:

  1. 在以下位置创建项目路径和 url 列表dev/.projects.gws

    work/proj  | https://...
    perso/ext  | git@github.com:...
    perso/qa   | https://...
    
  2. 使用以下gws命令之一:
    • init:用于.projects.gws从当前文件夹树中的现有存储库自动创建文件。
    • 更新:克隆缺少的本地存储库,例如当一个项目添加到.projects.gws.
    • status:显示所有存储库的状态(干净,未跟踪的文件,未提交的更改,...)。
    • fetch:在所有存储库中执行 git fetch (如果在两者之间进行了修改, status将能够检测与原始存储库的差异)。
    • ff:在所有存储库中执行 git 快进拉取
    • check:验证工作空间的状态(工作空间中已知、未知、缺失的存储库)

然后.projects.gws可以使用 git 对文件进行版本控制,并在许多计算机(工作、家庭、笔记本电脑......)上使用。也可以编写一个.ignore.gws文件以使用正则表达式在本地忽略某些路径,例如忽略家庭计算机上work/文件夹中的存储库。^work/.*

有关详细信息,请参阅自述文件

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

于 2014-05-11T17:41:09.057 回答
0

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

在此处输入图像描述

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

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

于 2021-07-06T13:11:24.847 回答
-1

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

与其问你是否总是需要 X 和 Y 一起使用,不如问自己是否总是希望完全相同版本的 X 和 Y 一起使用。

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

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

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

git submodules 的伟大之处在于它不仅记录了您使用的模块,还记录了它们的具体修订。在修复错误时,我经常需要测试某些依赖项的特定版本 - git 子模块让我可以轻松地将这些记录在我的工作区模块的历史记录中,让我可以在以后轻松地回到那个确切的状态。

于 2012-10-03T05:30:26.127 回答