为 git 子模块指定分支?

2024-03-04

我已经将 git 子模块添加到我的 git 存储库中并且工作正常。

在我的“父”存储库中,我创建了一个功能分支:我的特征这需要对子模块进行一些更改。但我不想影响使用相同子模块的其他团队。因此我在子模块存储库上创建了相应的功能分支子模块功能有一些变化。然后,我添加/提交了子模块目录中的更改,然后在父存储库的根目录中添加/提交了相同的更改。

但是当我切换回master在我的“父”存储库中,子模块仍然位于子模块功能功能分支。这不是我所期望的。因为现在当我运行测试时master他们失败了,因为我在子模块中引入了一些重大更改子模块功能 branch.

是不是不可能lock子模块的分支到父存储库分支?

编辑: 基于:添加 Git 子模块时如何指定分支/标签? https://stackoverflow.com/questions/1777854/how-can-i-specify-a-branch-tag-when-adding-a-git-submodule

看起来我可以为子模块存储库指定一个分支.gitmodules

[submodule "mysubmodule"]
    path = mysubmodule
    url = https://bla.git
    branch = submodule-feature

并在 jenkins 中添加以下附加 git 行为:

and:

它克隆/签出submodule-feature运行构建时的分支parent 我的特征 branch.

但在本地工作时,这当然需要一些手动步骤。但从 CI 方面来看,它很容易实现。


The short answer is just mostly "no". While Jenkins has a checkbox, it may not be a good idea to use it here—whether it is or not, depends on who controls the name-to-ID-mapping. Other CI systems may or may not have similar checkboxes. To see what I'm getting at here, read on.

子模块的理念是超级项目控制其子模块。我认为这部分对任何人来说既不令人惊讶也不反感。但关键在于way超级项目控制每个子模块。这部分does人们感到惊讶,原因很简单。一般来说,这是对 Git 存储库的基本误解。

People think that what matters in Git repositories are branches, or more precisely, branch names like master and develop. That's simply not true. These branches, for the most part, are virtually irrelevant here. For humans, these branch names serve an enormous, overriding purpose. For Git, they serve a mostly-trivial point that's equally well covered by any other name, such as a tag name, or a remote-tracking name, or refs/stash, or HEAD@{17}.1

在 Git 中,commit,而不是分支名称(也不是标签名称,也不是任何其他名称),是核心、本质的东西。提交是 Git 的存在的理由 https://www.merriam-webster.com/dictionary/raison%20d%27%C3%AAtre。没有提交,Git 就没有任何功能。对于提交,Git 很有用。提交实际上是通过它们的哈希 ID 来识别的,它们的真实名称是那些又大又难看的字符串,比如b5101f929789889c2e536d915698f58d5c5c6b7a。愚蠢的事情就像readable名字,比如master or develop,是为了弱者,生物……人类。

当然,我们作为弱小的人类,like我们的名字。所以我们在我们的存储库中使用它们。但是,当我们有一个存储库(例如超级项目)控制另一个存储库(例如子模块)时,在这种情况下,没有人类参与。因此 Git 使用提交 ID 来控制在每个子模块中提取哪个提交哈希 ID。

So this is where the surprise comes in—except, once you understand where Git is coming from, it's not surprising at all. When you let the superproject choose the submodule commit, the superproject chooses the submodule commit by hash ID. Any branch names are irrelevant. The hash ID is precise and is always correct. Branch names are sloppy—they move, on purpose, from commit to commit, over time. One commit hash ID can have zero or more branch names that either point directly to it, or can reach it through the commit graph.2

Each and every commit you make in the superproject records the exact submodule hash ID that the submodule is expected to have checked out. Hence, when you git checkout some commit in the superproject, you should generally immediately have each submodule do its own separate git checkout by the hash ID specified in the superproject.3

请记住,每个子模块都是自己的 Git 存储库,因此它有自己的HEAD、索引和工作树。子模块中的索引记录了签出到子模块工作树中的文件,并且HEAD在每个子模块中分离头模式,记录当前签出的提交的哈希ID。这是超级项目的 Gitchooses此哈希 ID(通过将其存储在超级项目的提交中),并且子模块的 Git 负责检查此特定提交。在此过程中没有任何地方提及分支名称。分支名称无关紧要!


1The in-Git function of names, besides of course providing a crutch for weak humans, is to protect objects from being garbage collected. An object is vulnerable to collection if it is not reachable from some name. Since most commits are mostly chained together, one name tends to protect most of the commits in a repository. See also footnote 2.

2For more about reachability, see Think Like (a) Git http://think-like-a-git.net/.

3This doesn't actually happen automatically by default. You have to use git checkout --recurse-submodules or set submodule.recurse in your configuration. Depending on what you're doing—especially, if you're trying to update the submodules—having it happen automatically is either convenient, or extremely annoying.


那么,为什么可以首先设置分支名称呢?

正如您所指出的,.gitmodules文件可以记录分支名称。您也可以将其复制到.git/config (the .git/config设置覆盖.gitmodules设置,如果两者都设置了。)但通常,子模块根本不在分支上;它被置于分离的 HEAD 模式,如上所述。那有什么好is这个分行名称?

第一个但有些不太令人满意的答案是:这一点都不好。大多数操作只是不使用它。

第二个更令人满意的答案是:一些特殊用途的操作确实会使用它。具体来说,如果您正在更新超级项目,并且想要进行一个新的超级项目提交来记录new子模块哈希 ID,您需要某种方法来挑选新的子模块提交哈希 ID。有多种方法可以解决此问题,该名称旨在用于one这些方式。

例如,假设子模块是您无法控制的公共存储库(可能在 GitHub 上)。你刚才use它。也许每年两次,或者每天 50000 次,有人更新 GitHub 存储库。他们提交的新提交master或他们的develop或者其他什么,破坏你使用的一堆东西,但这不是问题,因为你的超级项目不会say“给我他们最新的master or develop提交”,你的超级项目说“让我提交a123456...", and a123456...总是相同的提交,永远,直到宇宙热寂,或者我们停止使用 Git,以先发生者为准。但是,在破坏您自己的一堆软件的同时,他们还引入了您必须拥有的一项很酷的新功能。

此时您想要做的是让您的 Git(也控制您的子模块)告诉您的子模块 Git:去给我拿他们最新的master or develop或者我之前记录的任何名字。自从你did记录该名称,您可以使用以下命令指示 Git 指示子模块执行此操作:

git submodule update --remote

(您可以添加一些额外的标志,例如--checkout or --rebase or --merge,但我不会深入讨论这些细节 - 我现在假设您只是直接使用他们的最新版本)。您的 Git 已运行子模块 Gitgit fetch然后按照子模块分支名称副本的指示将子模块存储库更新为最新提交。 (现在有at least所有这一切都涉及三个 Git——你的超级项目、你的子模块和 GitHub 上的 Git 存储库——所以它有点复杂。无论他们是谁,他们都可能拥有一个或多个 Git 存储库,用于控制 GitHub 存储库,但至少您不必处理这一问题。嗯,还没有。)

现在您的子模块已更新,您必须修复自己的代码,既要使用新功能,又要处理它们对您已经使用的内容所做的所有重大更改。因此,您完成所有这些工作,构建和测试您的软件 - 全部在您的本地计算机上:这里还没有涉及 CI - 并使其全部正常工作。Now你可以git add你的改变和git add子模块的名称。您的超级项目的索引和工作树现在全部匹配,您已准备好在超级项目中进行新的提交。

注意git add submodule-path只是告诉你的 Git 在你的索引中记录hash ID当前在子模块 Git 存储库中签出的提交。再次,分支名称(如果有)是无关紧要的。您的子模块存储库是否位于分支上并不重要master or develop,或者有一个分离的 HEAD;重要的是原始提交哈希 ID.

你现在跑git commit进行新的提交。索引中的哈希 ID(控制哪个提交将被视为子模块的“正确”提交)是您通过运行记录的提交哈希 IDgit add submodule-path. 在这种情况下,该提交 ID 得到selected因为你跑了git submodule update --remote早些时候。但唯一重要的是索引中的哈希 ID,它会进入新的提交。

Now你可以git push您在超级项目 Git 存储库中进行的此提交到其他系统,例如 CI 系统。它可以git checkout这个提交,这个提交记录了right子模块哈希 ID。

如何将其与 CI 系统结合起来,以便 CI 系统选择哈希 ID?

This is, obviously, a lot harder may be harder, depending on whether your CI system offers it as a feature.

现在您已经了解了这一切是如何构建的,您已经拥有了所需的工具。您必须让 CI 系统更新(或获取)其超级项目的克隆。该超级项目包含.gitmodules文件、CI 系统还必须克隆的任何子模块的 URL 和路径。它可能包含也可能不包含这些子模块的某些分支名称。

CI 系统现在必须指示某个 Git(超级项目 Git 或子模块 Git)以拥有子模块 Gitgit checkout一些提交以外已经记录为correct提交,以便超级项目不再使用 CI 系统签出的提交。换句话说,你是不再构建您提交给 CI 系统的内容。你让 CI 系统用身体部位构建了一个新的弗兰肯斯坦怪物:你的提交的主体,但从其他提交中取出的肢体你没有直接指定:相反,您允许其他人指定那里的提交。你给了你的 CI 系统一个name并告诉它询问他们,无论他们是谁,这个名字对应的哈希ID是什么。

您的 CI 系统现在可以尝试构建和使用这个弗兰肯斯坦的怪物。如果一切顺利,您的 CI 系统将需要制作一个new提交,这很像your提交,但它记录了哈希 IDit来自them——无论他们是谁,再一次——针对有问题的子模块。您的 CI 系统现在可能还需要权限才能将此提交推送到某处,除非您的 CI 系统也是您的主存储库的真实来源。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为 git 子模块指定分支? 的相关文章

  • 来自 eclipse 的部分 git 提交 (egit)

    假设我有一个有 2 个更改的文件 如何使用 egit 只提交其中之一 命令行版本可以在以下位置找到this https stackoverflow com questions 1085162 commit only part of a fi
  • “git rm --cached”、“git Restore --staged”和“git reset”之间有什么区别

    我遇到了以下三种方法来取消暂存由命令 git add 暂存的文件 git rm cached
  • 在 git 提交消息中使用任何 utf-8 字符是否安全?

    我发现使用 UTF8 字符 例如 很有用 请参阅here http www utf8icons com subsets dingbats 在提交消息中 重构 NewService 添加了更好的服务 OldServiceA 据我所见 它see
  • 如何让 git 和 copSSH 在正确的目录中查找密钥?

    我刚刚安装了 Windows 版 copSSH 当我启动它时 我得到一个目录C copSSH home Nick ssh其中有我的酒吧和私钥 当我通过 Cygwin bash 窗口访问此目录时 使用 ssh 用户 主机 我很高兴地登录了 但
  • 如何使用 git hook pre-merge-commit 获取原始合并分支名称

    我正在尝试使用新的 git hook pre merge commit 创建一个特定的脚本 但它没有参数 有什么解决方法可以让我获得正在合并的分支的名称吗 例子 在分支 myBranch 上 我调用 git merge testingBra
  • 主存储库和本地存储库在同一台机器上

    我是 Git 新手 我已经在 Linux 服务器中创建了一个主存储库 同一个服务器将由 5 组 每组 3 个用户 使用 我想为每个组创建一个本地存储库 小组成员又应该为每个人创建一个本地存储库 使用内容并将修改提交到小组的本地存储库 我该怎
  • 从 master 更改为新的默认分支 git

    这是一个场景 我们有一个默认的分支 Master 我们以此为基础 创建分支并向上推等等 我们现在创建了一个Develop分支Master并将其设置为默认开发分支 我想知道的是 我现在如何知道我的 git pull 命令是否通过命令行请求默认
  • 在 GitHub 上执行拉取请求时避免不需要的合并提交和其他提交

    我在 Github 上分叉了一个项目 令远程上游为upstream我的远程存储库是origin 我当地的master分支设置为跟踪远程master分支 然后我在本地添加了一些东西master 时不时与上游汇合 直到今天我想发出pull re
  • Git 中的“分支提示”是什么?

    我正在学习 Git 并阅读专业 Git 书籍 https git scm com book en v2 书中和 Stack Overflow 上有时会使用术语 分支提示 但我找不到它的含义 分支提示是分支上的最后一次提交或最近一次提交 基本
  • 合并之间的 git rebase 会导致完全不相关的文件发生冲突

    我有一个大型 Git 存储库 几个月前引入了一个错误 我想bisect它 首先引入一个过去的提交 存储库 然后重播合并 做rebase到新的 commit 如下图所示 据我了解 由于合并 Git 似乎无法正常工作 预期的 但我想更好地了解为
  • 如何在本地快速拉取拉取请求

    在合并拉取请求之前 我想在本地快速拉取请求并运行测试并测试一些内容 我还不想点击 gihub 合并拉取请求 我以为滑轮会有帮助http ejohn org blog pulley http ejohn org blog pulley 但我收
  • 如何使用 sourceTree 进行推送?

    我正在使用 sourceTree 管理 Unity 项目 版本 4 6 3 我只是想返回到上一次提交 右键选择 将当前分支重置到此提交 在使用模式中选择 硬 然后放回上一次提交 之后 我尝试去推 但没有成功 抱歉 当时我忘记了错误 之后 我
  • 当出现错误时如何删除远程分支?

    我尝试过以下命令 但失败了 git push origin next remote error denying ref deletion for refs heads next To blah git remote rejected nex
  • 如何解决 VS Code 中变基拉取的合并冲突?

    当我做一个git pull rebase 并且我的提交中存在合并冲突 我得到冲突差异视图 解决所有冲突并暂存文件 然后呢 我可以打开终端并运行git rebase continue但是 VS Code 中不应该有一个按钮来完成变基吗 只需使
  • 在centos上设置jenkins:ssh密钥和git的问题

    经历了很多问题 但似乎没有什么能解决我的问题 或者更准确地说 我不确定我是否正确地完成了整个事情 所以这里是 已安装centos 6 3操作系统 然后我按照以下指南安装詹金斯 https wiki jenkins ci org displa
  • 我在哪里? *(无分支)

    我已经熟悉了创建 合并和删除分支 我想知道我在哪里 这样我就不会将工作提交到错误的分支 我用git branch a看看我有哪些分支 我认为星号 显示我当前所在的分支 当我得到以下信息时 这意味着什么 no branch master or
  • 在 Azure DevOps 中为 Wix MSI 文件生成 GUID

    我正在为 Web 服务器应用程序和 Sitecore 前端应用程序设置 Wix 安装程序 我的问题并非特定于 Web 服务器或 Sitecore 我的问题是 Wix 以及如何使用它进行持续交付 1 Wix 需要每个文件和产品本身的 GUID
  • 在 .gitconfig 中隐藏 GitHub 令牌

    我想将所有点文件存储在 GitHub 上 包括 gitconfig 这需要我将 GitHub 令牌隐藏在 gitconfig 中 为此 我有一个 gitconfig hidden token 文件 这是我打算编辑并放在隐藏令牌的 git 下
  • 清理远程 Git 分支

    我已经将 SVN 存储库移至 Git 可能由于多次克隆 我现在只剩下一堆看起来像这样的分支 BranchA origin BranchA remotes BranchA remotes origin BranchA remotes orig
  • 为什么 git-svn 应该积极搜索旧历史?

    当我运行 git svn clone s 时发生了一些奇怪的事情 尽管以下信息告诉我们不要惊慌 但我想知道为什么会出现这种 svn 错误 为什么这个路径不存在 是被别人删除了吗 如果是 为什么 git svn 应该积极搜索旧历史记录 Ini

随机推荐

  • 生成 parquet 文件 - R 和 Python 之间的差异

    我们已经生成了一个parquet文件输入Dask Python 并与Drill R 使用Sergeant包 我们注意到几个问题 的格式Dask i e fastparquet has a metadata and a common meta
  • 将由空格分隔的字符串中的单词分配给变量? C++ [qt] [重复]

    这个问题在这里已经有答案了 我只是想知道将空格分隔的字符串中的单词分配给变量的技术术语叫什么 这样我就可以查找它的教程 任何术语 链接或解释将不胜感激 你可以这样做 QString lineText some sample words QS
  • 在 Sitecore MVC 中的视图中获取媒体 url

    我有一个存储在媒体库中的 mp3 文件 它在项目的媒体字段中被引用 我可以通过在 Web 表单或类中执行 Sitecore Resources Media MediaManager GetMediaURL 来获取 URL 但是如何在 MVC
  • 在 smartGWT 中打开/保存文件

    我已经实现了 RPCService RPCServiceAsync 和 RPCServieImpl 单击按钮后 将调用服务器端的服务 它将从数据库中获取数据并创建文件 创建文件后 我需要在客户端打开该文件 并需要提示一个包含打开 保存选项的
  • ServiceStack - 依赖关系似乎没有被注入?

    我有以下存储库类 public class Repository
  • 微服务架构中的数据库位置

    我们有一个整体应用程序 现在正在使用容器将其转换为微服务架构 我们的微服务是stateful 即他们需要从数据库插入 检索数据 根据微服务架构 每个微服务应该有自己的数据 即我们案例中的数据库 我的问题是where应该部署每个微服务的数据库
  • 实体框架数据库优先与 Oracle 数据库

    我正在开发一个 ASP NET WebForms 应用程序 其中实体框架数据库优先与 SQL Server 连接 并且我想将相同的实体数据模型与 Oracle 数据库连接 我的担忧是 如何在我的开发机器上安装 Oracle 数据库引擎进行测
  • 使用用户定义的运行时属性的 UIView Shadow

    当我使用 用户定义的运行时属性 时 我很难显示阴影 如果我使用代码 它似乎工作完全正常 如下所示 func formatView view UIView cornerRadius Bool if cornerRadius view laye
  • Python Selenium Javascript链接点击无法执行

    我将 Selenium for Python 与 PhantomJS Ghost 驱动程序一起使用 以便单击 href 中包含 Javascript 的链接 例如来自this https structuredginniemaes ginni
  • MongoDB 根据 _id 统计每分钟新文档数

    我想创建每分钟存储多少新文档的统计数据 由于具有标准 ObjectID 的 id 字段已经包含文档创建的时间戳 我认为应该可以以某种方式使用它 在 Stackoverflow 上 我发现了以下映射归约代码 可以在有用于创建数据的专用字段时完
  • 从具有特定窗口坐标的命令行启动 Google Chrome

    我正在尝试找到一个 shell 命令 该命令将使用特定的 x 和 y 坐标打开 Google Chrome 以便我可以在窗口打开时设置窗口的位置 是否可以使用命令行参数来执行此操作 我需要修改以下命令才能实现此目的 google chrom
  • python中不均匀的子图

    在 python 中创建 3 3 子图矩阵的最佳方法是什么 第一列包含 3 个子图 第二列包含 3 个子图 第三列包含2 个次要情节 最后两个子图应具有相同的大小 这意味着它们将在其他两列的中间图的中间相遇 我尝试使用 gridspec 来
  • 当应用程序未处于焦点或位于另一个选项卡中时,WaitForSeconds 停止工作

    我用 Unity 制作了 WebGL 游戏 不需要每个帧都进行一些计算 因此我将它们放在协程中 但当游戏在后台运行时 协程的工作速度会比平时慢 并且会额外等待 5 10 秒 例如 士兵跑向我 我向他们发射子弹以杀死他们 当他们进入射程时 他
  • 引导程序上的下拉子菜单不起作用

    我只是想问为什么引导程序上的下拉子菜单不起作用 我只是按照此链接中的说明操作 http getbootstrap com 2 3 2 components html http getbootstrap com 2 3 2 component
  • 从 shell 脚本将密码输入 openssl 命令

    我正在尝试将 p12 从 shell 脚本转换为 pem 无需任何用户输入 我可以将密码作为脚本中的变量 所以当我打电话时 openssl pkcs12 in p12 out cert pem nodes 终端打印 输入导入密码 并等待输入
  • Jersey 2.x 自定义注入注释与属性

    我正在从 DropWizard 0 7 1 迁移到 0 8 1 这包括从 Jersey 1 x 迁移到 2 x 在我的 使用 Jersey 1 18 1 的实现 我有一个MyProvider 为了简单起见 更改了所有类名 实现Injecta
  • 如何避免SRP混乱?

    通过应用 SRP 原则 您必然会有很多课程 如果这对于小型项目来说效果很好 那么您如何处理和组织大型项目中的类数量 你如何组织文件夹结构 你怎么记得你建造了什么 你怎么知道其他人是否没有在其他类中构建相同的功能 这适用于所有类型的图书馆 不
  • 在 VBA 中滚动网页时等待窗口重新加载

    我编写了一个 VBA 宏来计算 Google 搜索特定术语时返回的 大约 图像数量 我的意思是 程序应该计算返回的图像数量 向下滚动以加载更多图像 如果适用 最多可计算 400 个图像 这是 简化的 代码 Sub GoogleCount C
  • 如何在 C# 中运行同步计时器?

    我正在编写一个应用程序 它使用计时器在屏幕上显示某些事件发生时的倒计时 我想重用计时器 因为它对于应用程序中的一些操作会很方便 因此我指定了要环绕计时器的单词 例如 以下函数调用 CountdownTimer 90 You have unt
  • 为 git 子模块指定分支?

    我已经将 git 子模块添加到我的 git 存储库中并且工作正常 在我的 父 存储库中 我创建了一个功能分支 我的特征这需要对子模块进行一些更改 但我不想影响使用相同子模块的其他团队 因此我在子模块存储库上创建了相应的功能分支子模块功能有一