来自Loeliger 2ed的Git版本控制,
如果你没有在git push命令中指定refspec怎么办?Git如何知道该做什么或在哪里发送数据?
首先,如果没有给出命令的显式远程,Git假定您想要使用origin.
如果没有refspec, git push 会将您的提交发送到您的存储库和上游存储库之间通用的所有分支的远程 .上游存储库中尚未存在的任何本地分支都不会向上游发送; 分支必须已存在且匹配名称.
"存储库和上游存储库之间通用的所有分支"是否与本地存储库中的所有远程跟踪分支以及远程存储库中相应的跟踪分支相同?
报价是为了git push
.它(特别是没有refspec的情况下的部分)是否适用git fetch
于git pull
?
torek.. 5
(我担心这个问题的答案会再次变长,因为这些问题的假设至少在今天是不正确的.跳转到粗体部分以获得实际答案,但之前的所有内容也很重要.)
你引用的书籍文本已经过时,而且(现在)只是完全错误(这对于不断发展的软件来说是危险的,书籍已经过时了):
首先,如果没有给出命令的显式远程,Git假定您想要使用origin.
我没有,通过git自己的git历史进行相对快速的扫描,确切地发现行为发生了变化,但文档在git 1.8.2.1中发生了变化,现在说:
当命令行未指定使用
参数推送的位置时 ,
branch.*.remote
将查询当前分支的配置以确定推送的位置.如果缺少配置,则默认为origin.
(这种行为git fetch
也很不合意,因为他们使用相同的源代码来获得该结果.)这没有提到可选设置,它会覆盖.在所有情况下,这里代表您当前的分支,如输出所示.(如果你处于"超级HEAD"模式,那么失败,通常会给你一个"致命的:你当前不在分支上"的错误,我认为自2.0版以来默认值发生了变化.)branch.$branch.pushremote
branch.$branch.remote
$branch
git symbolic-ref --short HEAD
git symbolic-ref
git push
这仍然不是全部故事; git-config文档还增加了一个怪癖:
remote.pushDefault
默认情况下推送到的遥控器.覆盖branch.
所有分支,并被.remote branch.
特定分支覆盖..pushRemote
(幸运的是,截至今天,我认为这涵盖了所有内容.也就是说,git首先查找pushremote
当前分支的设置.如果没有这样的设置,它接下来会查找remote.pushdefault
.如果没有设置,它会回退关于remote
当前分支的设置.旧版本的git中的行为可能会有所不同.请注意,配置项不区分大小写:pushremote
并且pushRemote
是相同的配置名称[这让我想知道分支名称部分是否也不区分大小写;我必须在某个时候测试它.)
关于refspecs的下一部分更加错误,因为git随着时间的推移已经获得了一些变化,其中一些甚至在git的内置文档中都没有很好地记录.你的引用如下:
如果没有refspec,git push会将您的提交发送到您的存储库和上游存储库之间通用的所有分支的远程.
在新的文件说:
当在命令行中没有指定,可以把什么
参数或
... --all
,--mirror
,--tags
选项,该命令将查找默认通过咨询
remote.*.push
配置,如果没有找到它,荣誉push.default
配置来决定推什么(见的git-配置的意思push.default
) .
该push.default
设置是在git的1.8版本附近添加的,但其默认值在git 2.0中更改.如果您尚未配置,push.default
则会收到此警告:
warning: push.default is unset; ...
自配置项可用以来.咨询git-config文档,您现在可以找到:
push.default
定义在git push
未明确给出refspec的情况下应采取的操作.不同的值非常适合特定的工作流程......
共有五个选项,我会简单地列出这里(详见链接文档): ,nothing
,current
,simple
,upstream
和matching
.您引用的书籍文本描述了matching
,这是git 2.0版之前的默认行为.新的默认值是simple
.
git push
,如果您配置"匹配"行为"存储库和上游存储库之间通用的所有分支"是否与本地存储库中的所有远程跟踪分支以及远程存储库中相应的跟踪分支相同?
没有.
我建议您尝试运行git ls-remote origin
(或替换origin
为任何其他遥控器的名称):
$ git ls-remote origin 28274d02c489f4c7e68153056e9061a46f62d7a0 HEAD 1ff88560c8d22bcdb528a6629239d638f927cb96 refs/heads/maint 28274d02c489f4c7e68153056e9061a46f62d7a0 refs/heads/master 0ac5344e619fec2068de9ab2afdb99d1af8854be refs/heads/next 5467631257c047b16d95929559dd1887d27b0ddc refs/heads/pu 68a0f56b615b61afdbd86be01a3ca63dca70edc0 refs/heads/todo d5aef6e4d58cfe1549adef5b436f3ace984e8c86 refs/tags/gitgui-0.10.0 3d654be48f65545c4d3e35f5d3bbed5489820930 refs/tags/gitgui-0.10.0^{} [snip -- lots more omitted]
然后,尝试git for-each-ref refs/heads
:
$ git for-each-ref refs/heads
你会看到类似的输出,但是有不同的SHA-1,并且这个词commit
夹在中间.
这里的要点是每个"头"都列在refs/heads
-in输出中,来自ls-remote
和来自for-each-ref
- 表示git push
在进行"匹配"时考虑的(本地)分支.匹配的头被添加到推送列表中,给出一组refspecs(内部形式但很容易表示为name:name
或,如果您使用了--force
标志).+name:name
即使没有为这些本地分支配置上游,也会发生这种情况.因此,如果他们(遥控器)有一个refs/heads/bob
用于Bob Roberts的用途,并且你有一个refs/heads/bob
用于获取有关你的管道bob或钓鱼浮子或其他什么的信息,git将尝试匹配那些即使你bob
是不打算上游.
push
vsfetch
报价是为了
git push
.它(特别是没有refspec的情况下的部分)是否适用git fetch
于git pull
?
没有.
这种行为git fetch
更容易解释,因为它并没有对你做所有奇怪的事情git pull
.该git pull
命令应该是方便的,但是git pull
试图将基本上存储库范围的"获取"操作与基本的分支约束"合并"操作混合在一起.这两个不能很好地融合在一起.1 (充其量,我认为git pull
在某些时候可以修改为更简单,存储库范围内的"获取全部",然后检查并合并,成对,基于跟踪配置和参数的一些分支"序列.我认为这它会使它的行为与大多数人所期望的一样.它也会主要是向后兼容的,并且它现在的行为方式只适用于最简单但默认情况:fetch all,然后仅合并当前分支.但是无论如何,这都是猜测.)
如果省略所有refspecs,请git fetch
读取配置行.remote.$remote.fetch
(请注意,这个"省略所有refspecs"子句意味着您还必须避免使用旧的"命名文件$GIT_DIR/branches
"方法.)
名为remote的默认配置行(单数)origin
通常如下所示(查看本地存储库配置文件以查看它):
[remote "origin"] +refs/heads/*:refs/remotes/origin/*
这是"远程跟踪分支"出现的实际机制.
该fetch
过程从相同的git ls-remote origin
步骤开始,该步骤获取远程的每个参考分支,标记或有什么内容的列表.该fetch
代码接着与每个匹配这些了fetch =
下线路[remote "origin"]
.refspec左侧的星号具有明显的含义; 右侧的星号将替换为左侧星号匹配的任何内容.(在当前版本的git中,*
必须匹配"整个部分",松散地定义为"斜杠之间的东西",但是在即将到来的git中,这个约束将被放宽 - 尽管我不确定哪个有用的结尾.)
您可以拥有任意数量的fetch =
线条.每个原始引用都通过每一行来获得一个新的(替换)引用:如果左侧匹配,则右侧提供替换.(如果右侧缺失或为空,由于历史原因,行为有点奇怪,部分是为了继续git pull
工作,部分原因是因为所需的行为在git 1.8左右发生了变化.)
所有这些替换的结果形成重命名的引用,并确定复制哪些引用; 但每个原始引用必须至多有一个结果:例如,你不能将"他们的"refs/heads/foo映射到"你的"refs/remotes/origin/bar 和你的refs/remotes/origin/zoink.
要使存储库充当镜像,您可以使用+refs/*:refs/*
不带重命名的所有引用(但这会破坏每个引用的本地分支,fetch
因此这大部分只对其有意义--bare
).
("修剪" - 基于另一方在启动协商期间为获取或推送发送的内容而删除的"死"引用是单独完成的,并且仅在您设置--prune
标志时.)
1它没有这样开始.实际上,原始pull
脚本完全取决于遥控器和远程跟踪分支.提交7ef76925d9c19ef74874e1735e2436e56d0c4897
分裂pull
成pull
和fetch
,然后将两个随时间不同的方向演变; 一旦"远程跟踪"和"远程跟踪分支"出现,他们就会发展到试图混合它们的地步,我认为,这只是一个坏主意,现在情况更糟.:-)
(我担心这个问题的答案会再次变长,因为这些问题的假设至少在今天是不正确的.跳转到粗体部分以获得实际答案,但之前的所有内容也很重要.)
你引用的书籍文本已经过时,而且(现在)只是完全错误(这对于不断发展的软件来说是危险的,书籍已经过时了):
首先,如果没有给出命令的显式远程,Git假定您想要使用origin.
我没有,通过git自己的git历史进行相对快速的扫描,确切地发现行为发生了变化,但文档在git 1.8.2.1中发生了变化,现在说:
当命令行未指定使用
参数推送的位置时 ,
branch.*.remote
将查询当前分支的配置以确定推送的位置.如果缺少配置,则默认为origin.
(这种行为git fetch
也很不合意,因为他们使用相同的源代码来获得该结果.)这没有提到可选设置,它会覆盖.在所有情况下,这里代表您当前的分支,如输出所示.(如果你处于"超级HEAD"模式,那么失败,通常会给你一个"致命的:你当前不在分支上"的错误,我认为自2.0版以来默认值发生了变化.)branch.$branch.pushremote
branch.$branch.remote
$branch
git symbolic-ref --short HEAD
git symbolic-ref
git push
这仍然不是全部故事; git-config文档还增加了一个怪癖:
remote.pushDefault
默认情况下推送到的遥控器.覆盖branch.
所有分支,并被.remote branch.
特定分支覆盖..pushRemote
(幸运的是,截至今天,我认为这涵盖了所有内容.也就是说,git首先查找pushremote
当前分支的设置.如果没有这样的设置,它接下来会查找remote.pushdefault
.如果没有设置,它会回退关于remote
当前分支的设置.旧版本的git中的行为可能会有所不同.请注意,配置项不区分大小写:pushremote
并且pushRemote
是相同的配置名称[这让我想知道分支名称部分是否也不区分大小写;我必须在某个时候测试它.)
关于refspecs的下一部分更加错误,因为git随着时间的推移已经获得了一些变化,其中一些甚至在git的内置文档中都没有很好地记录.你的引用如下:
如果没有refspec,git push会将您的提交发送到您的存储库和上游存储库之间通用的所有分支的远程.
在新的文件说:
当在命令行中没有指定,可以把什么
参数或
... --all
,--mirror
,--tags
选项,该命令将查找默认通过咨询
remote.*.push
配置,如果没有找到它,荣誉push.default
配置来决定推什么(见的git-配置的意思push.default
) .
该push.default
设置是在git的1.8版本附近添加的,但其默认值在git 2.0中更改.如果您尚未配置,push.default
则会收到此警告:
warning: push.default is unset; ...
自配置项可用以来.咨询git-config文档,您现在可以找到:
push.default
定义在git push
未明确给出refspec的情况下应采取的操作.不同的值非常适合特定的工作流程......
共有五个选项,我会简单地列出这里(详见链接文档): ,nothing
,current
,simple
,upstream
和matching
.您引用的书籍文本描述了matching
,这是git 2.0版之前的默认行为.新的默认值是simple
.
git push
,如果您配置"匹配"行为"存储库和上游存储库之间通用的所有分支"是否与本地存储库中的所有远程跟踪分支以及远程存储库中相应的跟踪分支相同?
没有.
我建议您尝试运行git ls-remote origin
(或替换origin
为任何其他遥控器的名称):
$ git ls-remote origin 28274d02c489f4c7e68153056e9061a46f62d7a0 HEAD 1ff88560c8d22bcdb528a6629239d638f927cb96 refs/heads/maint 28274d02c489f4c7e68153056e9061a46f62d7a0 refs/heads/master 0ac5344e619fec2068de9ab2afdb99d1af8854be refs/heads/next 5467631257c047b16d95929559dd1887d27b0ddc refs/heads/pu 68a0f56b615b61afdbd86be01a3ca63dca70edc0 refs/heads/todo d5aef6e4d58cfe1549adef5b436f3ace984e8c86 refs/tags/gitgui-0.10.0 3d654be48f65545c4d3e35f5d3bbed5489820930 refs/tags/gitgui-0.10.0^{} [snip -- lots more omitted]
然后,尝试git for-each-ref refs/heads
:
$ git for-each-ref refs/heads
你会看到类似的输出,但是有不同的SHA-1,并且这个词commit
夹在中间.
这里的要点是每个"头"都列在refs/heads
-in输出中,来自ls-remote
和来自for-each-ref
- 表示git push
在进行"匹配"时考虑的(本地)分支.匹配的头被添加到推送列表中,给出一组refspecs(内部形式但很容易表示为name:name
或,如果您使用了--force
标志).+name:name
即使没有为这些本地分支配置上游,也会发生这种情况.因此,如果他们(遥控器)有一个refs/heads/bob
用于Bob Roberts的用途,并且你有一个refs/heads/bob
用于获取有关你的管道bob或钓鱼浮子或其他什么的信息,git将尝试匹配那些即使你bob
是不打算上游.
push
vsfetch
报价是为了
git push
.它(特别是没有refspec的情况下的部分)是否适用git fetch
于git pull
?
没有.
这种行为git fetch
更容易解释,因为它并没有对你做所有奇怪的事情git pull
.该git pull
命令应该是方便的,但是git pull
试图将基本上存储库范围的"获取"操作与基本的分支约束"合并"操作混合在一起.这两个不能很好地融合在一起.1 (充其量,我认为git pull
在某些时候可以修改为更简单,存储库范围内的"获取全部",然后检查并合并,成对,基于跟踪配置和参数的一些分支"序列.我认为这它会使它的行为与大多数人所期望的一样.它也会主要是向后兼容的,并且它现在的行为方式只适用于最简单但默认情况:fetch all,然后仅合并当前分支.但是无论如何,这都是猜测.)
如果省略所有refspecs,请git fetch
读取配置行.remote.$remote.fetch
(请注意,这个"省略所有refspecs"子句意味着您还必须避免使用旧的"命名文件$GIT_DIR/branches
"方法.)
名为remote的默认配置行(单数)origin
通常如下所示(查看本地存储库配置文件以查看它):
[remote "origin"] +refs/heads/*:refs/remotes/origin/*
这是"远程跟踪分支"出现的实际机制.
该fetch
过程从相同的git ls-remote origin
步骤开始,该步骤获取远程的每个参考分支,标记或有什么内容的列表.该fetch
代码接着与每个匹配这些了fetch =
下线路[remote "origin"]
.refspec左侧的星号具有明显的含义; 右侧的星号将替换为左侧星号匹配的任何内容.(在当前版本的git中,*
必须匹配"整个部分",松散地定义为"斜杠之间的东西",但是在即将到来的git中,这个约束将被放宽 - 尽管我不确定哪个有用的结尾.)
您可以拥有任意数量的fetch =
线条.每个原始引用都通过每一行来获得一个新的(替换)引用:如果左侧匹配,则右侧提供替换.(如果右侧缺失或为空,由于历史原因,行为有点奇怪,部分是为了继续git pull
工作,部分原因是因为所需的行为在git 1.8左右发生了变化.)
所有这些替换的结果形成重命名的引用,并确定复制哪些引用; 但每个原始引用必须至多有一个结果:例如,你不能将"他们的"refs/heads/foo映射到"你的"refs/remotes/origin/bar 和你的refs/remotes/origin/zoink.
要使存储库充当镜像,您可以使用+refs/*:refs/*
不带重命名的所有引用(但这会破坏每个引用的本地分支,fetch
因此这大部分只对其有意义--bare
).
("修剪" - 基于另一方在启动协商期间为获取或推送发送的内容而删除的"死"引用是单独完成的,并且仅在您设置--prune
标志时.)
1它没有这样开始.实际上,原始pull
脚本完全取决于遥控器和远程跟踪分支.提交7ef76925d9c19ef74874e1735e2436e56d0c4897
分裂pull
成pull
和fetch
,然后将两个随时间不同的方向演变; 一旦"远程跟踪"和"远程跟踪分支"出现,他们就会发展到试图混合它们的地步,我认为,这只是一个坏主意,现在情况更糟.:-)