gpt4 book ai didi

git - 为什么在起源不是远程名称的情况下使用 “git push origin master”?

转载 作者:行者123 更新时间:2023-12-02 08:32:11 24 4
gpt4 key购买 nike

我在一个教程中看到有人使用git push origin master,但是远程分支名为o/master。没有名为origin的远程文件,只有o。是他犯了一个错误,还是origin有特殊含义?

This is the tutorial.(如果弹出窗口,请单击红色按钮)。键入级别,转到“远程”选项卡,然后在第二行上单击显示“推入参数”的第四个按钮。继续前进,直到获得第一个视觉演示。

最佳答案

这并不完全是所提问题的答案。如果我使用注释中的链接转到页面,并允许通过NoScript进行足够的操作来运行脚本等,那么它似乎是从一个中等复杂的git rebase操作的演示开始的,我很快就迷失了方向。高级项目,而不是从头开始。但是,如果问题重新构成,我们将得到...

Remote 和“远程分支机构”

“远程”只是一个名称,例如originupstreambob,它作为“远程”部分进入.gitconfig.git/config文件中:

[remote "bob"]
url = git://name.in.some.domain/path/to/bob.git
fetch = +refs/heads/*:refs/remotes/bob/*

remote-name是用双引号引起来的东西。 url行提供了 fetchpush操作的URL。 fetch =行也很重要。我们将立即恢复。

首次运行 git clone时, clone命令设置“远程”部分。尽管您可以使用 origin-o选择其他名称,但默认情况下使用的名称是 --origin

远程分支机构(又名远程跟踪分支机构)

git的所有引用(分支,标签和“远程分支”)实际上都是本地的,这意味着它们存储在本地的自己的 .git目录中。分支和标签可能已经很熟悉了,“远程分支”似乎也很简单。但是这里有一两个转折点。

第一次克隆某个​​存储库时,源存储库具有一堆分支。好吧,它可能至少有一个分支。例如,某些存储库仅具有 master分支。 (您甚至可以拥有一个完全没有分支的存储库; git clone为此发出警告,但允许这样做。)

为了讨论起见,我们假设原始源中有两个分支,分别称为 masterdevelop。在任何情况下,git都会复制所有远程分支。但是,即使必须将它们存储在本地,它也不只是使它们成为普通的本地分支。它使它们成为“远程分支”。

还要说您没有使用 -o更改任何名称,因此您的克隆具有名为 origin的远程。在这种情况下, git clone要做的是将“远程分支”命名为 origin/masterorigin/develop

它是怎么得到这些名字的?这就是 fetch =行的所在。

裁判和裁判规格
fetch =行的内容是“refspec”。 refspec倒数第二,只是一对用冒号分隔的ref名称,例如 master:masterdevelop:develop。但是等等,首先,引用名称到底是什么?

ref-name只是人类可读的名称,例如 masterorigin/master;但是每个都有几种形式。有一个“全名”形式,通常以 refs/开头,还有一个“短”形式,例如 master。简称 master只是写全名 refs/heads/master的一种便捷方法。全名不仅包含名称本身,还包含该名称的“ namespace ”,它实际上告诉您名称的种类。 refs/heads/命名空间是您所有常规分支所在的位置。 refs/tags/命名空间带有您的所有标签,并且 refs/remotes/带有您的所有远程跟踪分支。

这实际上几乎就是它的全部: “本地”分支是refs/heads/中的引用名,而“远程”分支是refs/remotes/中的引用名。 git在本地存储在您自己的存储库中的远程分支的目的是跟踪“分支在远程上的位置,这是我最后一次(git)有机会查看远程并看到它”。
fetch =行包含一个refspec

再次,refspec的一种简单形式就是 ref:ref -左侧的refname和右侧的refname。 fetch =行使用了此功能,但添加了两个星号和一个加号: +refs/heads/*:refs/remotes/origin/*

加号具有相对简单的含义:它是“force”标志。我们将回到这一点。

星号也做一件很明显的事情。上面我们说过,当我们克隆存储库时,原始存储库具有 masterdevelop。这些是本地分支,实际上是 refs/heads/masterrefs/heads/develop。星号会匹配所有内容,因此左侧 refs/heads/*会匹配这两个分支。在右侧,星号表示“放入左侧匹配的所有内容”。

换句话说,这匹配 refs/heads/master(左侧)并生成 refs/remotes/origin/master(右侧)。它还匹配 refs/heads/develop并生成 refs/remotes/origin/develop

在前面,加号表示“强制”或“进行强制更新”。这告诉git即使更新不是“快进”也要更新参考(并且我将在此答案中方便地忽略快进:-))。然后,所有这些操作使每次运行 git fetch时, git fetch始终更新远程跟踪分支。这就保留了我们想要的属性:git连接到远程存储库,与该服务器上的gitty副本进行了交谈,并找出了所有分支的位置,因此现在应该更新我们的“远程分支”副本。

(请稍等,我们是如何从 git clone转到 git fetch的?嗯, clone实际上只是第一次获取:它初始化存储库,添加其第一个“远程”,然后进行获取,所有这些都是一回事。因此,遵守与 git fetch相同的规则。)

当您 checkout 一个与远程跟踪分支同名的(新的,本地的)分支时,git使您的新本地分支与远程跟踪分支的提交相同,并且还将您的本地分支设置为引用远程分支,以便 git status可以打印类似 1 ahead, 3 behind的内容。令人困惑的是,一些git文档喜欢说该本地分支“跟踪”了远程分支,而其他git文档则将“远程分支”称为“远程跟踪分支”,并指出该分支“跟踪”了远程分支。 (实际上,只要我们让本地git与远程服务器联系,它就会更新。)

起初,这种重命名的原因有点模糊。但是,一旦使用git一段时间,它就会变得显而易见。假设您克隆了该存储库,然后自己在分支 masterdevelop或两者上进行了一些提交。然后,您执行与远程服务器联系的操作,并且远程分支将得到更新。如果git要更改您自己的(本地) master和/或 develop,这将丢失您已经完成的工作。因此,它仅更新远程跟踪分支。

远程跟踪分支不必按名称匹配远程

在上面的示例中,我有 [remote "bob"],然后是 fetch = +refs/heads/*:refs/remotes/bob/*。但是 fetch =行不必在refspec的右侧使用与远程相同的字符串。如果 fetch行读取 +refs/heads/*:refs/remotes/robert/*,那么我所有用于远程 bob的远程分支都将命名为 robert/branch

[(显然)是这里原始难题的答案:无论出于何种原因(显然是窗口的宽度),教程作者都将 originfetch =行设置为包含 refs/remotes/o/*。但是,让我们以其他方式结束这个更大的答案。]

无论如何, git push的这些参数是什么?

经典的推入命令示例是 git push origin developgit push origin master。但是,如果检查 the git push documentation,则会看到两个参数分别显示为“repository”和“refspec”。当 origin是远程数据库的名称时,它是如何存储的;如果它没有冒号,因此没有左右两侧,那么 master如何成为refspec?

第一部分的答案是 git push随时间而发展。某些古老版本的git中可能不允许使用远程存储库参数 origin。相反,您必须编写实际的URL,该URL现在存储在 Remote 定义的 url =行中。您今天仍然可以执行此操作,因此文档不能将该参数限制为仅一个“远程”名称。因此,在 git push origin中, origin部分是远程服务器的名称,这是编写完整URL的一种简短方法。 (为此,您实际上可以在配置文件中列出一个单独的“pushurl”,以便将获取转到一个URL,将推送转到另一个URL。)

对于第二部分,好吧,当我说refspec是一对用冒号分隔的ref名称时,我也说这是第二简单的形式。最简单的形式只是一个引用名称!以这种方式编写时, git push会将其视为重复的引用名,中间加一个冒号。所以在这里, master只是 master:master。 (由于各种原因, git fetch handles no-colon refspecs differently。)

如果您最终设法“理解”了git为什么要重命名 git fetch上的引用,这将引发另一个问题。

为什么我们推送 master:masterdevelop:develop

使用 fetch,我们更新了远程跟踪分支, origin/master(或者也许是 o/master),等等。为什么不更新服务器上的“推送跟踪分支”?例如,我可以将工作推送到 refs/me/master

实际上,我们可以做到;有些系统可以处理这种事情(某些类型的请求和某些自动测试系统使用对 refs/for/...的推送等)。但是git“开箱即用”不能做到。我们只是直接推送到 Remote 上的原始分支。

这意味着 git push的最后一个参数( master中的 git push origin master)将我们的 master直接推到其 master。该推送必须是“快进”,否则将被“拒绝”(或者我们必须使用带 --force的force标志,或者-您应该从 fetch行识别出来-加号 git push origin +master:master)。

[[这也导致一些小缺陷(实际上是最近修复的),在git中,对于“安全撤回”工作,包括以人们可以使用的方式“倒退”已发布的分支。强制标志是全有或全无,但是在某些情况下,能够告诉远程服务器很好:“我认为您的ref <ref>位于 <raw commit ID>;如果是这样,请将其更改为 <new ID>。”本质上,这是对引用名称的比较和交换:它启用了原本不可能的原子更新形式。但这是另一个话题,这个答案花了太长时间写。 :-)]

关于git - 为什么在起源不是远程名称的情况下使用 “git push origin master”?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25473657/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com