遥控器/原点/ HEAD应该设置什么?

问题描述 投票:-1回答:1

如果开发人员正在develop分支机构工作,那就是新项目

1) Clone

git clone <git_url>应该能够在不使用develop选项的情况下在本地自动克隆-b分支,这样

$ git branch -a # after clone should give
* develop
  remotes/origin/HEAD -> origin/develop
  remotes/origin/develop

2) Push

当开发人员使用命令develop将本地分支(origin/develop)更改推送到远程存储库(git push origin develop)时,我的理解是,如果origin/master指向remotes/origin/HEAD,则更改被推送到origin/master,与此comment中提到的不同


题:

1)在执行上述两项任务之前,是否建议运行git remote set-head origin develop并在远程存储库中设置HEAD指针?由任何开发人员

2)git push origin develop是否推动改变origin/develop而不考虑远程存储库中的remotes/origin/HEAD值?

3)我们在GitLab和Jenkins之间使用webhook。 Qazxswpoi提供的env.gitlabSourceBranch是否给出了GitLab plugin指向的分支名称?如果是,如何获取推送事件发生的分支名称?通过webhook。

下面是在GitLab中完成的设置,用于检索发生新提交的分支名称:

remotes/origin/HEAD以下是Jenkins中的代码:

enter image description here
git jenkins gitlab jenkins-plugins git-remote
1个回答
2
投票

是否建议在远程存储库中运行node('worker_node'){ stage('stage1'){ def repoName = env.gitlabSourceRepoName println "Repository Name: " + repoName // gives correct repo name def branchName = env.gitlabSourceBranch println "Branch name: " + branchName // gives always 'master' as value } } 并设置git remote set-head origin develop指针...

这可能是一个语言问题,但值得指出的是,这并没有在远程存储库中设置HEAD。它对任何其他人的HEAD命令都没有影响。

Git的术语非常令人困惑。让我们分解一下:

  • 远程是您在Git存储库中使用的短名称,用于引用其他一些Git存储库。因此git clone是一个遥控器:它代表一些URL。如果你的Git拨打该URL,其他一些Git会回答这个“电话”。请注意,这里的单词remote是一个名词:它本身就是一个东西。
  • 远程存储库是您自己的存储库。当你让你的Git拨打一些URL并调用其他一些Git时,那个其他Git就是一个远程存储库。这里的远程词是一个形容词。
  • 在Git中,分支这个词很模糊。 (参见origin)我更喜欢使用短语分支名称,其中分支是形容词修改名称,远程跟踪名称(Git称之为远程跟踪分支名称),其具有修改单词名称的整个形容词短语,分别指What exactly do we mean by "branch"?master之类的东西。 分支这个词也意味着一系列含糊不清的提交。在这个特殊情况下 - 我们使用origin/master将Git存储库从某个URL复制到我们自己的机器,或者git clone将我们机器上的Git存储库中的提交发送到其他地方的某个其他Git存储库(可能在另一台机器上) - 我们不需要这个意思。但请注意它存在!

我们还需要一两个或更多的Git术语:

  • 引用(或引用)是分支名称,标记名称或其他类似名称。实际上,引用只是对它们的概括:分支名称,标记名称和远程跟踪名称都只是特定类型的引用。引用具有以git push开头的完整拼写。 通常紧接着是它的分类:例如,所有分支名称都以refs/开头。事实上,这就是Git知道refs/heads/是一个分支。所有标签名称都以refs/heads/master开头,这就是Git知道refs/tags/是一个标签的方式,所有远程跟踪名称都以refs/tags/v1.2开头。 在大多数情况下,您可以删除参考的refs/remotes/refs/heads/refs/tags/部分。例如,如果您只是说refs/remotes/,Git将搜索您的所有参考文献。如果你有一个master而没有refs/heads/master,那么名字refs/tags/master必须是那个分支名称,所以Git会把它当作一个分支来对待它。同样地,如果你只是说master,并且Git搜索并找到一个名为v2.1但没有别的标签,那么refs/tags/v2.1必须是那个标签名称,所以Git会将其视为标签。 Git用来记住Git的所有远程跟踪名称你的Git调用v2.1origin开始。也就是说,你的Git记得他们的refs/remotes/origin/是你的master。这是如此,如果你有另一个遥控器,你的意思是其他origin/master并不含糊。例如,假设您添加了第二个远程 - 第三个Git存储库 - 您可以简称为master。如果您调用upstream的URL上的Git有一个upstream分支,那么你的Git会调用master,并且很容易将这个区别于你的Git称之为upstream/master的东西。
  • refspec以其第二种最简单的形式,是一对引用origin/master卡在它们之间的引用。因此,:是一个refspec,例如。 master:master也是如此。冒号左边的东西是源,冒号右边的东西是目的地。

refs/heads/master:refs/remotes/origin/mastergit fetch命令使用refspecs,我们将在稍后看到。当你问git push而不是git clone时,git fetch的一个重要部分是运行git clone

考虑到所有这些,接下来让我们看看Git如何解析一个符号名称,以及当Git解析一个符号名称时。这部分有点棘手,因为git fetchgit fetch使用位置参数。

删除了很多细节(例如标志参数),git pushgit push的参数在文档中以这种方式拼写出来:

git fetch [git fetch] [repository [refspec ...] refspec [git push] [repository [refspec ...]

也就是说,在refspecpush子命令之后,根据定义,下一个项目是fetch。根据定义,repository参数之后的任何项目都是repository参数。您可以将原始URL放入存储库部分,但通常,您应该使用远程名称,原因有两个:

  • 打字和做对更容易;和
  • 它实现了有用的特殊功能。

要输入任何refspec参数,你必须插入一个refspec参数,因为没有一个,Git只会认为你输入的是repository参数。也就是说,如果你不小心运行repository,Git就不会发现你打算输入git push master。它只会尝试将git push origin master视为远程,或者将其视为URL。可能它不会以任何方式工作,你会得到这个令人费解的输出:

master

所以使用$ git push master fatal: 'master' does not appear to be a git repository fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. ,您可以选择以下选项:

git push

当你把东西留下来时,就像在前两个例子中一样,Git为你挑选远程和refspec(第一个例子),或为你选择refspec(第二个例子)。当您包含refspec(第三个示例)或多个refspecs(第四个示例)时,您可以控制所有部件。

在我们回到第一个问题之前,让我们继续你的第二个问题:

git push git push origin git push origin somebranch git push origin branch1:branch1 branch2:branch2 branch3 tag1:tag1 是否会推动更改git push origin develop而不管远程存储库中的origin/develop值?

这包含多个术语错误(同样可能只是语言问题)。我认为,总的想法很清楚,答案是肯定的:这完全无视remotes/origin/HEAD

明确一点,这个:

  • remotes/origin/HEAD指定为遥控器,并且
  • 指定origin作为refspec。

请记住,我们说第二种最简单的refspec形式是一对带有冒号的名称。这使用最简单的形式,省略了第二个名称。省略第二个名字的行为在developpush中有所不同。我们在这里只担心fetch

对于push,省略refspec的第二部分意味着第一部分和第二部分是相同的。也就是说,git push意味着develop。名字develop:develop本身很短 - 它不是以develop开头 - 但是你的Git和他们的Git可能都有一个名为refs/的分支而且没有名为develop的标签。所以develop实际上是develop的缩写。

请记住,他们的Git存储库是一个Git存储库。因此它有自己的refs/heads/develop:refs/heads/develop-它自己的分支名称拼写refs/heads/develop。您的develop标识了您的存储库中的一些提交。他们的refs/heads/develop在他们的存储库中识别出一些提交。

当你运行refs/heads/develop时,你告诉你的Git:连接到其他一些Git。然后确保他们有足够的提交和其他内部Git对象来实现最后一部分,通过给予他们任何他们不需要的提交。最后,你已经完成了,要求他们 - 或命令他们 - 设置他们的一些分支和/或标记名称以指向某些特定的提交或其他适当的Git对象。

您要求他们设置的分支和/或标记名称来自refspec的目标部分。因此,如果你说git push,分支或标签名称你将让你的Git要求他们的Git改变是git push ... develop:develop。您要求他们设置为develop的提交是源名称标识的提示 - 右侧的提交。因此,您将要求他们设置他们的develop以识别您的develop识别的相同提交。


1如果你有一个分支develop和一个标签refs/heads/develop,一些不太好的事情发生。 Git有这方面的规则,但Git的规则有点奇怪和令人不安。最好的办法是完全避免这种情况:永远不要为标签和分支使用相同的短名称。


They can say either yes or no

如果他们对此请求说“是”,那么您的Git现在知道他们的refs/tags/develop代表该提交。你的Git通过更新你自己的develop记得他们的develop。因此,您的Git会更新您的origin/develop - 您的origin/develop,使用其全名 - 来保存该提交哈希ID。

请注意,在这个过程中没有任何地方让你的Git看看你自己的refs/remotes/origin/develop。你没有把refs/remotes/origin/HEAD放在refspec的左侧。如果你愿意,你可以这样做。例如,你可以写:

refs/remotes/origin/HEAD

这将让你的Git将你的git push origin refs/remotes/origin/HEAD:refs/heads/develop 解析为提交哈希ID,在refs/remotes/origin/HEAD调用Git,并要求Git将他们的origin设置为该提交哈希ID。它可能已经设置为该ID,因此这可能只是浪费时间,但如果您愿意,它可以运行。

你也可以运行:

refs/heads/develop

它将你的git push origin HEAD:refs/heads/develop 解析为一个提交哈希ID,在HEAD调用Git,并要求他们根据它设置他们的分支origin;你可以运行:

develop

如果git push origin a123456:refs/heads/develop 是您的存储库中的一些有效提交。这些形式中的大多数需要两部分refspec,其中包含冒号,因为冒号左侧的东西根本不一定是分支名称,并且您将要求他们的Git设置一个他们的分支名称。

但是,一般情况下,当使用a123456时,您将从您自己的分支名称(如git push和/或develop)开始,并且要求他们将相同名称的分支名称设置为相同的提交哈希ID。偶尔 - 例如在您刚制作新标签名称后 - 您将希望让Git调用他们的Git并要求他们将相同名称的新标签设置为相同的哈希ID。因此,master将一个名称镜像为两个的默认值很适合你,因为你可以写:

git push

从而要求他们设置两个分支,并一次创建一个新标签。

如果他们拒绝,他们可以零碎地做。假设你要求他们设置所有这三个名字,并且他们接受你更新他们的git push origin master develop v1.3 并创建一个新的develop的请求,但拒绝你更新他们的v1.3的请求。你将获得两次成功,一次失败,你的Git将更新你的master以记住分支成功,但不更新你的refs/remotes/origin/develop,因为分支失败意味着你不知道他们的refs/remotes/origin/master究竟是什么。 (没有远程标记这样的东西,因此要求他们创建master的成功或失败对存储库中的任何名称都没有影响。)

Back to v1.3: what is it and what good is it?

简而言之(也许有点过于激进),origin/HEAD毫无用处。

它是Git的象征性参考。你可以随时使用refs/remotes/origin/HEAD设置它。它最初是在git remote set-head origin期间创建的。但据我所知,它没有任何实际目的。

我在上面提到你可以缩短参考文献:你可以说git clone意思是masterrefs/heads/master意思是v2.1。在你自己的Git存储库中尝试这种事情:运行refs/tags/v2.1并为分支和标签指定短名称和长名称。 (使用git rev-parse列出你的分支,并使用git branch列出你的标签。)你会看到这样的事情:

git tag

rev-parse命令从符号名称(如$ git rev-parse master b5101f929789889c2e536d915698f58d5c5c6b7a $ git rev-parse v2.1.0 7452b4b5786778d5d87f5c90a94fab8936502e20 )转换为哈希ID,如master。 (它也可以从短哈希ID转换为完整哈希ID,或者执行许多其他技巧,但这是其主要工作之一:将名称转换为哈希ID。)

一般来说,当你给Git一个简短的名字时,Git会搜索你所有的引用,以找出长的名字。 b5101f929789889c2e536d915698f58d5c5c6b7a命令执行此操作,然后吐出哈希ID。大多数其他Git命令也这样做,但接着以某种方式继续使用哈希ID。然而,在几乎所有情况下,这个搜索过程都在git rev-parse中概述,值得仔细研究。但现在快速浏览一下,然后向下滚动一下,找到一个六步列表。

这里的六步列表是Git如何将一个简短的名称变成一个长名称。请注意,第3步尝试将the gitrevisions documentation作为标记名称:如果v2.1存在,则refs/tags/v2.1是标记名称,这就是v2.1知道并找到其哈希ID的方式。这是第4步,它将git rev-parse作为分支名称:如果master存在,那么refs/heads/master是一个分支名称,这就是master所知道的。

在六步列表的底部,有一个步骤6.最后一步采用你输入的任何字符串 - 例如git rev-parse,并将其作为origin。如果存在,那一定是你的意思。所以虽然refs/remotes/string/HEAD通常是一个遥远的 - 你输入的是originrepositorygit fetch参数 - 它也是一个有效的提交短名称,如果你把它放在某个Git命令,如git push,将使用它的地方作为提交。

有可能删除git rev-parserefs/remotes/origin/HEAD就是这样做的。如果你已经删除它,git remote origin set-head -d将不匹配第6步,origin将失败。可以使用git rev-parse origin将存储在git remote origin set-head中的名称更改为任何其他refs/remotes/origin/HEAD分支名称,以便步骤6成功但使用其他名称。在origin/*,这一切都没有回到另一个Git!


2我在这里掩饰了象征性的参考。当像origin这样的名称包含另一个名称而不是某个Git对象的哈希ID时,会出现符号引用。 Git使用的机制是一般性的,但充满了奇怪的怪癖和缺陷,实际上只适用于HEAD,并且 - 在较小程度上 - 与这些远程跟踪HEAD样式名称。

例如,您可以在分支名称空间中创建自己的符号引用。使用origin/HEAD创建名称git symbolic-ref refs/heads/INDIR refs/heads/master作为符号引用分支。不幸的是,如果你这样做然后尝试删除名称INDIR,Git会删除名称INDIR!整个事情还没有真正为这种用途做好准备(滥用?)。不要这样做!

3我说几乎所有的情况都是因为某些Git命令知道他们的名字参数是分支或标签名称,而其他人则怀疑它。例如,master知道你将给它一个分支名称,而不是标签名称,作为下一个参数。因此,它不使用六步解析过程,事实上,它要求您在创建新分支时不要使用完整的git branch表单拼写分支名称。

refs/heads/命令是最奇怪的,因为git checkout(和任何标志)之后的位置参数被允许是分支名称,标记名称或解析为有效提交的任何内容。所以它似乎应该使用六步过程。如果您创建一个名为checkout的分支和标记,但指向两个不同的提交,您可能希望X检查标记的git checkout X。实际上,它会检查分支。因此,虽然X将尝试所有六个步骤,但它会比步骤3更早地尝试第4步。

(从技术上讲,当它尝试将名称作为分支名称时,它不会经历六步过程。相反,它只是首先尝试将其作为分支名称。如果可行,git checkout会将您放在分支上并完成。如果它失败了,那么代码会调用六步名称到ID解析器,只要提交哈希值回来,git checkout就会在你提交的时候把你放在一个独立的HEAD上。所以它实际上尝试了两次步骤4,如同它是 - 但如果它第一次失败,它也很可能第二次失败。)


How git checkout works

当你运行git clone时,你有Git:

  1. 创建一个新的空目录(或接管一些现有的空目录)。其余步骤都发生在该目录中。
  2. 运行git clone url以创建一个空的Git存储库。
  3. 运行git init来创建一个遥控器。这个遥控器的名字是你用git remote add旗帜选择的任何东西,但是如果你没有选择它,那就是-o。此新遥控器的URL是您为origin提供的URL。
  4. git clone设置一些默认的refspecs。实际的refspecs取决于命令行标志,但典型的标准是git fetch。请注意这与我们用于+refs/heads/*:refs/remotes/origin/*的refspec类似。配置此远程的符号HEAD,就像git push一样。运行由其他命令行标志指定的任何其他git remote set-head命令。
  5. 运行git config。这使用在步骤3中创建的远程和在步骤4中设置的refspec。
  6. 运行git fetch。此步骤的name参数取决于命令行标志和从其他Git获取的信息。请参阅下文了解详情。

第6步将你的新克隆放在git checkout name上,或者也许放在master上,如果你在这里选择像develop这样的话,甚至根本就没有分支。如果第6步让你进入你的v2.1分支,这就是创建你的master分支的原因。如果第6步让你拥有你的master分支,这就是创建你的develop分支的原因。如果第6步让你有一个独立的HEAD,你的Git不会创建任何分支!

如果您愿意,可以使用develop指定最后一个克隆步骤应使用的名称。如果你这样做,其他Git说什么都不重要,当然除了git clone -b name必须匹配其中一个名字。但是如果你不使用name论证,那么 - 只有那时 - 其他Git说的很重要。

另一个Git存储库是一个Git存储库。这意味着其他Git存储库 - 为了简单起见,我们将其称为服务器存储库 - 具有-b。服务器存储库中的HEAD告诉在服务器存储库中检出哪个分支。如果服务器存储库是HEAD存储库,它没有工作树,所以它的--bare有点无关紧要。但它仍然有一个,这意味着服务器仍处于打开状态,除非服务器的Git处于分离的HEAD模式(这是可能的)。

当你的Git调用服务器Git时,你的Git可以向服务器询问的一件事是:你在哪个分支?也就是说,你的Git可以向服务器询问服务器的HEAD。如果你在HEAD期间未能为-b指定一个选定的分支,那么这就是你的Git将用于你的git clone的名称。

这也是你的Git将用于你的git checkout的名字,以及你的git remote set-head origin --auto将自动设置为你的git clone的名称。因此,服务器的origin/HEAD设置是HEAD时间origin/HEAD副本的默认设置,也是最后一步克隆git clone命令的默认设置。

这就是它真正的好处。如果你在git checkout时用-b覆盖它,那意义无关紧要,因为git clone无论如何都是无用的,这个意义也无所谓。

Conclusion

不要担心origin/HEAD。这毫无用处。它对你没有任何好处。

不要担心服务器存储库中的origin/HEAD。它确实会影响新的克隆,但前提是克隆的人不会选择分支。如果你想设置它,你可以这样做,但服务器允许。 (不同的Web服务有不同的方法来设置或更改它。)

最后,关于这个问题:

我们在GitHub和Jenkins之间使用webhook

我对您使用的特定插件一无所知。詹金斯的文档有所不同:其中一些有点用处,大部分都似乎缺失了,其中一些似乎是完全错误的。一般来说,Jenkins从您使用的任何托管服务器获取通知,发生了某些事情,然后您编写了解码发生的事件的代码。但是这部分:

如何获取推送事件发生的分支名称

这是一个根本不好的问题,因为没有必要的分支名称 - 例如我们可能只将HEAD添加到标记中 - 如果有分支名称,可能会有许多分支名称,并且它们可能已经更改了哈希ID,或不。要问的正确问题是让Jenkins启动一些管道是否合适。我无法回答这个问题,但这是您提出正确问题的指南。

© www.soinside.com 2019 - 2024. All rights reserved.