git - 如果在分支中工作,为什么 git push 需要额外的参数?
问题描述
我做了
git checkout -b NEW_BRANCH
到处都提到,为了将它推送到远程,要么告诉推送命令一些额外的信息
git push origin NEW_BRANCH
,或者必须将本地分支与远程分支相关联
git branch --set-upstream origin NEW_BRANCH
我也不明白两者的必要性。换句话说,我不明白附加命令的效果?这些是什么?或者会发生什么,如果有人说
git 推送
? 在上述任一命令中,NEW_BRANCH 是指本地分支名称还是远程分支名称(如果有差异)?
解决方案
正确答案有多个部分,这就是为什么如此令人困惑的原因。为了正确理解这一点,让我们从定义一些术语开始:
遥控器是一个简单的名称,例如
origin
orupstream
。这个名称让 Git 可以存储一个 URL——从技术上讲,是一个或多个 URL,但通常只有一个——这样https://user@host.dom.ain/some/fairly/long/path/to/some/other/repo.git
你就可以输入origin
.Git 有一个内置的,或多或少标准的远程命名
origin
,它由创建git clone
并自动记住您在运行时使用的 URLgit clone
。引用或ref是您用来引用提交的东西,例如分支名称或标记名称,例如
master
ordevelop
。引用有很长的形式:例如master
is reallyrefs/heads/master
。大多数时候你可以只使用短格式而不用担心这个,但是长格式就在那里,这是 Git 内部使用的,用于处理棘手的情况,比如你不小心制作了一个tagmaster
。(不要故意这样做,但如果你做错了,长格式总是让你解决问题。)refspec本质上是一对用冒号分隔的引用
:
。例如,master:master
是一个 refspec,就像refs/heads/develop:refs/heads/develop
. 但这是 refspec 的一种更复杂的形式:在很多情况下,您可以删除冒号和第二个名称,在这种情况下,它看起来像一个引用。
需要git push
的是,按顺序,一个遥控器后跟一个或多个refspecs。
这反过来意味着您的问题的答案:
git push origin NEW_BRANCH
... NEW_BRANCH 是指本地分支名称还是远程分支名称(如果有区别)?
实际上有点复杂,因为这毕竟NEW_BRANCH
不是分支名称,而是refspec。它只是看起来像一个分支名称!
什么git push
是调用另一个Git。另一个 Git 在 URL 上“活着”(或至少回答您的 Git 拨打的 Internet 电话),您的 Git 通过查找遥控器找到该 URL。然后两个 Git 进行对话,你的 Git 找出他们的 Git 有哪些提交,如果需要,提供他们的 Git新提交,最后,要求他们的Git 设置他们的一些分支名称以记住在你的Git 存储库中找到的一些提交. (此时,他们也有这些提交,如果他们以前没有的话,这要归功于中间的对话。)
因此,您在此处给出的NEW_BRANCH
refspec实际上是两个名称。当您使用其中包含冒号的表单时,您可以使用两个不同的名称,甚至在您身边使用原始哈希 ID:
git push origin master:somebranch
它让您的 Git 提供您的新提交,然后将它们 somebranch
设置为指向您指向的相同提交master
,或者:
git push origin a123456:refs/heads/somebranch
这让你的 Git 确保他们已经提交a123456...
,然后将它们 somebranch
设置为指向那个特定的提交。1
我不明白需要 [remote 和 refspec]
好吧,事实上,您通常不需要它们。您可能认为这意味着always,但由于多种历史原因,事实并非如此。
首先,Git 并不总是有远程,所以你可以写出一个 URL 来代替远程名称。2 如果您不使用远程或 URL,Git 将找出默认值(通常origin
)。但是,如果您需要列出 refspec,则必须提供远程或 URL,因为远程或 URL 必须位于参数中的那个位置。
其次,Git过去默认使用过于热情的默认 refspec 一次推送多个分支。今天,它默认使用理智的 refspec 推送一个分支。这应该 - 并且确实! - 使它不需要 refspec,但只有在满足某些条件时才需要。而且,您可以更改此默认值,使用push.default
; 如果你这样做了,那会改变你可以省略 refspec(s) 的条件,从而改变远程名称。
使用今天的默认值push.default
,simple
Git 将自动找出并使用正确的远程和 refspec ,如果:
- 当前分支有一个上游集,并且
- 上游命名远程上同名的分支。
这里的遥控器可以是你的任何遥控器:如果分支xyz
有一个上游foo/xyz
,遥控器是foo
并且分支foo
是xyz
所以条件1和2都满足并且git push
会做正确的事情。
当您第一次创建新分支时,其上游设置(如果有)取决于您创建该分支的方式。Using为您提供了一个默认情况下没有上游的新分支。Using为您提供了一个新分支,该分支作为其上游,并且还有各种其他选项可以设置一些上游。git checkout -b name
name
git checkout --track remote/name
name
remote/name
1如果您使用此表格,您通常必须拼出完整的参考名称。原因是当你使用缩短的名称时,git push origin x234
Git 会扫描你的引用以确定x234
是分支名称还是标签名称。这让你的 Git 告诉他们的 Git:设置你的 refs/heads/x234(分支)或设置你的 refs/tags/x234(标签)。
2在那些真正旧版本的 Git 中,您总是必须提供一个 URL。正如您可能想象的那样,这有点痛苦。这导致了几次实验,最终产生了remote的想法,并且一旦有一个标准的remote 命名origin
,它就允许你完全省略 remote,只要你也可以省略所有的 refspecs。
这些实验也仍然得到支持。您可以使用work:foo
plusinsteadOf
条目映射work:
到其中的主机名和可选路径。
推荐阅读
- amazon-web-services - AWS RDS:未设置新的主密码
- java - XML ItemWriter 以 XML 格式写入数据
- r - 如何通过ggplot2在笛卡尔坐标系中绘制矢量?
- c# - Azure devops 错误在端口上启动 ChromeDriver 2.36.540470。只允许本地连接
- eclipse - 搜索时如何让我的代码在 Eclipse 中可见?
- r - 识别包含“/”两次的单元格 - R
- java - 错误的 arraylist 输出在 2 个 cicle 中具有重复的结果
- conda - 无法进入 conda 下载页面
- android - onClick 事件不会在 TextInputEditText android 上触发
- c# - 如何在 C# 中检测文件中的任何非 UTF8 字符?