主存储库的不同分支如何使用子模块的不同分支? TL; DR 长详细信息,或者何时{em> branch设置很重要?

如何解决主存储库的不同分支如何使用子模块的不同分支? TL; DR 长详细信息,或者何时{em> branch设置很重要?

假设我有一个带有某些子模块的主仓库y,例如sub/x

还假设对于主模块和子模块存储库,master是活动分支,并且主存储库的.gitmodules文件指定branch = master

现在,假设除了主存储库master的分支y之外,还有主仓库yA的分支master x分支,子模块仓库(xA)有一个分支yA

我希望y仓库的xA分支“查看” /使用x仓库的master分支。

这意味着在主存储库中的yAmaster分支之间进行切换将导致子模块中的xAyA分支之间进行相应的切换。 / p>

git是否对此提供任何支持?


我尝试了以下操作:

  1. 切换到主存储库上的xA分支;
  2. 切换到子模块存储库上的master分支;
  3. xA替换为.gitmodules作为主存储库master文件中branch参数的值;
  4. 在主存储库中,提交了(2)和(3)导致的所有更改。

这没有我希望的那样工作:如果我切换到主存储库上的master分支,那么这对子模块存储库的活动分支设置(因此,{{1} }分支没有清除状态。

解决方法

git对[我想要的东西]有什么支持吗?

我认为排序。您需要确保.git/modules(在超级项目中)没有获取设置。

TL; DR

.gitmodules中使用不同的设置(在超级项目提交中),并根据需要使用git submodule update --remote。我尚未对此进行测试,但请参见详细说明。

我的总体一般建议:子模块的branch设置通常是无用且无关紧要的。只是忽略它。不过,我们将稍作介绍 most 部分,然后看看是否可以使用它。

一个子模块被定义为一个Git存储库,其中一些 other Git有时会进入该子模块并运行一些Git命令。另一个Git被称为超级项目。

超级项目Git的主要操作是:

(cd $path && git checkout $hash)

在此序列中,任何分支名称都不会出现。这就是为什么 branch设置不相关的原因。

$path$hash部分来自超级项目Git的 index ,它们是从超级项目中的提交中提取出来的。该提交记录了子模块的路径以及原始哈希ID。这里也没有分支名称。

当您在超级项目中运行git checkoutgit switch时,为了选择一些分支名称并因此选择某个特定的提交,超级项目Git将提取提交给其(超级项目)索引和工作的提交,该超级项目的树。这样会将正确的($ path,$ hash)对放入超级项目的索引中。

不幸的是,默认情况下它调用$(cd $path && git checkout $hash)部分来更新子模块。为此,您有几种选择:

  • 运行git submodule update。该命令正是这样做的(嗯,默认情况下:请参阅下面的详细信息)。
  • 运行git checkout --recurse-submodules(或与git switch相同的标志)。此命令使git checkout运行更新,并且并且传播到子模块Git中,以便在子模块运行git checkout(或git switch)时,如果子模块为另一个子模块的超级项目,该子模块将以其超级项目角色调用更新。对于所有嵌套的子模块,这将(递归)重复。 (我通常不使用它,但是我不必过多地处理递归子模块。由于递归,它非常强大。)
  • submodule.recurse设置为true。这将在多个命令(包括签出/切换)上启用--recurse-submodules选项,在git fetchgit pull上也会启用。 (我不喜欢这个:我认为它太强大了。但是,您可以设置它,然后使用push.recurseSubmodules设置显式禁用递归推送。)

详细信息,或者何时{em> branch设置很重要?

The git submodule documentation有几个很长且相当难以理解的段落来描述git submodule update子命令。 (我认为这表明子模块的整体设置存在缺陷,但是我们必须使用已有的东西,至少要等到提出更好的东西为止。)让我在这里引用一下:

update [--init] [--remote] [-N|--no-fetch] [--[no-]recommend-shallow] [-f|--force] [--checkout|--rebase|--merge] [--reference <repository>] [--depth <depth>] [--recursive] [--jobs <n>] [--[no-]single-branch] [--] [<path>...​]
通过克隆丢失的子模块,在子模块中获取丢失的提交并更新子模块的工作树,来更新已注册的子模块以符合超级项目的期望。根据命令行选项和submodule.<name>.update配置变量的值,可以用几种方式完成“更新”。 ...

如您所见,有很多选择。为了使答案不再更长,我们只关注其中三个:--checkout--rebase--merge没有选项还有两个,但您可以使用submodule.name.update变量进行设置,在这里我们将忽略它们。这些选项---checkout--rebase--merge-设置更新将使用哪种操作,与没有前导双连字符的选项名称相同。

checkout模式是默认默认设置。也就是说,如果您没有设置显式的submodule.name.update设置,而未指定--rebase--merge,则会得到checkout。这就是每个人都使用的-主要是!因此,这就是答案顶部的总体建议中的通常字。

现在,进入三种模式。我将再次引用该文档,随后进行一些小的格式更改和评论:

  • checkout
    记录在超级项目中的提交将在独立的HEAD的子模块中检出。

  • rebase
    子模块的当前分支将重新基于超级项目中记录的提交。

  • merge
    超级项目中记录的提交将合并到子模块中的当前分支中。

因此,在默认模式下,任何分支名称都不会在任何地方输入图片。实际上,只有rebasemerge模式使用分支名称。所以现在我们要问一个问题:哪个分支名称?

文档说明得很清楚:子模块中的当前分支。那不是子模块的branch =设置 ;这是子模块中的当前分支

但是子模块中当前有哪个分支?如果愿意,您可以查找

(cd $path && git rev-parse --abbrev-ref HEAD)

会告诉您,对于每条经过的路径,当前是哪个分支。如果子模块正在使用分离头模式,则它将打印HEAD,如果您运行过git submodule update --checkout或使用git submodule update模式的任何checkout,则它将打印。 >

如果要预测当前分支,或者子模块是否位于分离的HEAD上,并因此位于任何分支上,那么您将如何预测?好吧,您运行过git submodule update吗?除非您进行了递归模式签出,否则您必须首先进行git submodule update --init,在这种情况下,Git会为您执行git submodule update --init --checkout。因此,您的子模块很可能处于HEAD分离模式,因此没有当前分支。

换句话说,我们仍在海上。我们如何首先将子模块Git放在分支上?

有一个简单而显而易见的方法:我们可以自己做(cd $path; git checkout $branch),我们自己提供$path$branch。这样,无论提交什么内容,子模块都在我们想要的分支上。但是由于我们提供了$branch,所以我们不需要设置。我们只是这样做:

(cd path/to/submodule; git checkout feature/foo)

直接。所以也不是。

如果我们向下滚动到文档中的 OPTIONS 部分,然后再向下滚动到--remote选项,我们最终找到一个实际使用设置的地方:

--remote
此选项仅对update命令有效。不用使用超级项目的记录的SHA-1来更新子模块,而是使用子模块的远程跟踪分支的状态。使用的遥控器是分支机构的遥控器(branch.<name>.remote),默认为origin。使用的远程分支默认为远程HEAD,但是可以通过在submodule.<name>.branch.gitmodules中设置.git/config选项(使用.git/config来覆盖分支名称。优先)。

这适用于任何受支持的更新过程(--checkout--rebase等)。唯一的变化是目标SHA-1的来源。例如,submodule update --remote --merge将上游子模块更改合并到子模块中,而submodule update --merge将超级项目gitlink更改合并到子模块中。

Alllllll-righty then!

严重的是,这段文本确实很难阅读-但是它表示git submodule update --remote不仅会使用超级项目中的原始SHA-1哈希ID。相反,它将使用从其他位置获取的原始SHA-1哈希ID。恰好在其他地方?

为了确保当前跟踪分支状态,update --remote在计算SHA-1之前先获取子模块的远程存储库。如果您不想提取,则应使用submodule update --remote --no-fetch

因此:当您在--remote命令中使用git submodule update时,超级项目将:

  • 步骤1:(cd $path; git fetch),除非您添加--no-fetch
  • 第2步:(cd $path; git rev-parse $(complicated))获取哈希ID。

$(complicated)部分很复杂,但是它从branch =branch = master的{​​{1}}设置中获取分支名称,例如.gitmodules。它将其转换为远程跟踪名称,例如.git/config,即第一步已更新。另请参见VonC's answerHow can I specify a branch/tag when adding a Git submodule?

特殊名称origin/master表示在超级项目中使用分支名称,但是:

我希望.仓库的yA分支“查看” /使用y仓库的xA分支。

除非拼写完全匹配,否则无法使用x技巧来实现。并且,如果子模块的分支名称已复制到超级项目的.中,则它将保持设置为设置的任何值,如果没有,则超级项目Git将从{{ 1}}文件。

如果分支名称.git/config中记录的在主存储库中提交的branch =文件提交.gitmodules表示.gitmodules,那么在您运行{{1} }(有或没有$SHA_YA),假设子模块yA的{​​{1}}作为其远程对象,超级项目Git应该在branch = xA上进行git submodule update --remote。这将成为超​​级项目--no-fetch运行git rev-parse时超级项目origin/xA传递给子模块x的原始哈希ID的来源。

当您切换到其他提交时,请注意分支名称与此处无关。重要的是 commit哈希ID ,以及属于该提交的origin文件-在超级项目中,超级项目中的y文件可以具有其他一些{{ 1}}设置。您的x命令将找到 that 设置,并让子模块Git执行不同的y,以便在超级项目告诉子模块什么时,将哈希ID传递给子模块Git。签出。

这非常复杂,有很多活动部件。这些零件都必须在正确的时间排好队。超级项目最终实际上实际上只是使用原始哈希ID。仅使用正确的原始哈希ID会减少头痛的事情。一旦提交,便无法更改,通常这是正确的选择,因此您只需在提交之前确保它们是正确的即可。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-