min*_*hua 2 git git-pull git-remote git-branch
假设远程br1
仓库上有远程分支机构检查,master
本地仓库上有分支机构.
命令1:如果我做了一个" git pull origin br1:br1
"它将远程拉br1
入本地br1
,并显示:
9188a5d..97d4825 br1 -> br1
9188a5d..97d4825 br1 -> origin/br1
命令2:如果我只做一个" git pull
",它会将远程拉br1
入本地master
,但它只显示以下内容:
9188a5d..97d4825 br1 -> origin/br1
我期待它也会显示" br1 -> master
" 这样的东西.为什么没有表现出来?
" br1 -> br1
" 是否意味着将远程拉br1
入本地br1
?
这是什么br1 -> origin/br1
意思?
更新:在VonC的帮助下,我发现了以下内容:
git pull
更新所有跟踪分支.遥控器上的br1 -> origin/br1
装置br1
被拉入本地跟踪分支origin/br1
.
git pull origin br1:br1
将远程拉br1
入本地br1
并进入origin/br1
.然后,之后的消息意味着相同的更改集也被拉入当前签出的分支(消息是Updating ...
,它没有显示br1 -> master
):
$ git pull origin br1:br1
beb48a4..b344dd1 br1 -> br1
beb48a4..b344dd1 br1 -> origin/br1
Updating cca5a9b..b344dd1
Fast-forward
file2 | 0
file3 | 0
4 files changed, 0 insertions(+), 0 deletions(-)
以前我以为git pull
拉进了当地的主人.事实并非如此.就是git pull origin br1:br1
这样.
更新2:随着由托雷克说明,具体的问题是,该命令git pull origin br1:br1
远程拉br1
入FETCH_HEAD
其他动作序列后,随后将合并FETCH_HEAD
到当前分支.
警告:很久.TL; DR版:你是在寻找git fetch
输出和git fetch
不影响你的master
所有,它是git merge
你的一部分git pull
,影响你的master
.但是,您git fetch
正在更新远程跟踪分支origin/br1
,在一种情况下更新甚至创建本地分支br1
.
git pull
是一个方便的脚本永远记住,这git pull
只是一个为您运行两个其他git命令的便捷脚本:首先,git pull
将您的参数传递给git fetch
.一旦完成,git pull
运行git merge
(或者,如果指示git rebase
),但原始问题中的所有引用操作都是纯粹发生的git fetch
.("更新"部分中的一部分来自git merge
,我稍后会介绍.)
如果未提供远程参数git pull
,则pull
脚本将从当前分支的配置中提取一个参数.在这种情况下,它提取的那个是清楚的origin
.因此,如果您在git pull
未指定的情况下运行origin
,则实际上正在运行git pull origin
.
如果你没有提供refspec参数git pull
,pull
脚本会从当前分支的配置中提取一个非常简单的参数- 在这种情况下,无论你看到什么git config --get branch.master.merge
,显然是br1
.所以这意味着如果你跑git pull origin
,你实际上在运行git pull origin br1
.1
此外,所有这一切都是那么就转嫁到git fetch
,所以无论你跑git pull
,git pull origin
或者git pull origin br1
,所有这些只是拉闸调用:
git fetch origin br1
Run Code Online (Sandbox Code Playgroud)
(你也可以手动完成,你会看到上面的内容).
我们将git fetch origin br1:br1
在下面稍后介绍.
让我们再次简要介绍一下您的安装声明:
假设远程
br1
仓库上有远程分支机构检查,master
本地仓库上有分支机构.
目前在遥控器上签出的分支(如果有的话)通常是无关紧要的fetch
.第一个(或第一个足够的)事情fetch
是连接到远程并询问它是否包含所有引用及其相应SHA-1的列表(您可以看到git fetch
运行时可以看到的内容git ls-remote
).遥控器上的HEAD
被列入该名单,这可以让你指挥你fetch
使用它,但如果你不这样做,你fetch
只是忽略它(遥控器上的HEAD
大多只是用于控制在初始默认的初始分支git clone
).
但是,当地仓库中的当前分支很重要,原因有两个:
git pull
,它会根据你当前的分支找到它们; 和fetch
成功,git pull
运行或者git merge
还是git rebase
,它采用当前分支.同样,当前的分支master
,以便pull
将使用branch.master.remote
和branch.master.merge
作为默认的远程和的Refspec参数.2 这就是我们如何从原始输出中推断出这些是origin
和br1
.
git fetch
回过头来git fetch
,它做的是与远程git服务器进行一些比较,以找出哪些引用(主要是分支和标签)可用以及它们对应的SHA-1值是什么.一旦有了这些信息,它就会查看你要求它带来哪些参考资料.如果你列出了一个特定的引用br1
,那就是它将带来的一个引用.
当然,除了每个引用之外,它还必须带来任何新对象(提交本身及其关联的树和文件,以及任何父提交及其所需的树和文件),以便从中获取所有历史记录.特别指向后退.无论你已有的历史,当然,它可以跳过.3
正如VonC已经指出的那样,git的行为在git 1.8.4及更高版本中发生了变化.过去的情况是,如果你运行,你的refspec会覆盖你的git配置条目中的那个遥控器的规则,但现在它只是从中选择.默认情况下,名为remote 的规则集是,因此refspec会从此规则集中选择一个项目.git fetch remote refspec
git fetch remote refspec
origin
+refs/heads/*:refs/remotes/origin/*
br1
让我们停下来看看如果git fetch
只运行三个参数会发生什么,如下所示:
$ git fetch origin
Run Code Online (Sandbox Code Playgroud)
在这里,您指示您的本地git连接到遥控器,找出它有什么,并带来所有分支机构.它的方式(和原因)如上所述:它连接,获取列表,然后查询输出git config --get-all remote.origin.fetch
.4 这是"refspecs"列表,每git config --get-all
行一个.
由于该标准线(一个单行)remote.origin.fetch
是+refs/heads/*:refs/remotes/origin/*
,你的本地git会采取相匹配的所有引用名refs/heads/*
.也就是说,它将占用所有分支origin
,因为分支只是"名称以refs/heads/
" 开头的引用".它是什么做用这些分支是由该的Refspec的右侧确定的:它代替refs/heads/
用refs/remotes/origin/
.
结果是"远程跟踪分支".如果遥控器有一个分支master
,你的本地git会将其转换为origin/master
.如果遥控器有a br1
,你的本地git会将其转换为origin/br1
.对于遥控器上的每个分支,您将获得一个名称以(本地)远程跟踪分支开头的分支origin/
.五
回到我们的情况git fetch origin br1
,我们现在可以看到会发生什么:我们的本地git带来了br1
,结果是一个分支,所以它的全名是refs/heads/br1
.因此,它匹配标准remote.origin.fetch
行并被refs/heads/br1
转换为refs/remotes/origin/br1
,这导致git打印出来origin/br1
:
Run Code Online (Sandbox Code Playgroud)9188a5d..97d4825 br1 -> origin/br1
这个名字br1
左边的是遥控器上的参考的短名称,该名称origin/br1
右边是参考的短名称git fetch
已更新.
在过去你会看到类似的东西 - 你仍然可以看到它:
* branch name -> FETCH_HEAD
Run Code Online (Sandbox Code Playgroud)
这表明在遥控器上git fetch
找到了一个名为name
(即表格的引用refs/heads/name
)的分支,并将其带到您的本地仓库并将其放入FETCH_HEAD
.什么是FETCH_HEAD
?这是一个特殊的文件,几乎只存在于git pull
脚本中.(它的工作原理很像参考,但它有一个特殊的格式,可能包含多个SHA-1.)
现在我们(终于)准备好解决这个问题了br1:br1
.在这里,你告诉当地人git fetch
带来参考br1
.它通常调用遥控器,发现它br1
真的refs/heads/br1
,并带来引用和任何需要的对象 - 但这次,除了咨询该remote.origin.fetch
行之外,它还将新的SHA-1写入您指定的引用中.
在这种情况下,您指定br1
没有资格:不refs/heads/br1
,不refs/remotes/origin/br1
,只是br1
.在这种情况下,git看到它是refs/heads/
遥控器的引用,这意味着它是一个分支; 所以git refs/heads/
也会在你的最后添加,并创建或更新你自己的refs/heads/br1
.
换句话说,这会创建或更新您的本地分支br1
.
此外,git仍然应用该remote.origin.fetch
行,它仍然是+refs/heads/*:refs/remotes/origin/*
,因此它仍然更新您的远程跟踪分支origin/br1
(全名refs/remotes/origin/br1
). 这就是你获得Command 1输出的原因.
git merge
怎么样FETCH_HEAD
?好吧,这是其余部分git pull
重新出现的地方:执行该git fetch
步骤后,pull
脚本运行git merge
或者git rebase
.它合并的内容(或转换为)是文件中留下的任何内容git fetch
FETCH_HEAD
(有一些特殊的外壳和其他注意事项,我不会在这里讨论).
如果当前的分支master
,但您指示git pull
拉origin br1
,它是git merge
带来一步master
了解最新的br1
. 更确切地说,合并让您能更新您的副本origin/br1
作为时间的git fetch
结束,它可能是刚过你git fetch
完了,别人做了git push
该更新的br1
遥控器上.
如果可能的话,合并是一个"快进"合并,但我再也不会在这里详细介绍.我会注意到它是可能的,所以它已经完成了; 这是Fast-forward
更新中的一行.
在任何情况下,合并都会引入当前分支(master
)自当前分支和目标提交的合并基础以来的更改(文件中git fetch
剩余的原始SHA-1,FETCH_HEAD
也是新的SHA-1)origin/br1
,在一种情况下,新的或更新的本地分支的新SHA-1 br1
).
在1.8.4之前版本的git中,origin/br1
远程跟踪分支不会更新.FETCH_HEAD
尽管如此,一切仍然可以在文件中运行,如果有的话,它甚至比在新的gits中更令人困惑,在那里我们可以说你现在是最新的,origin/br1
而不必非常严格和挑剔" br1
因为它是在你跑的时候在遥控器上git fetch
".
眼尖的读者可能已经注意到了+
在+refs/heads/*:refs/remotes/origin/*
.此+
符号表示"强制更新".通常,在更新分支引用时 - 以refs/heads/
-git 开头的任何引用都不允许更新,除非它是"快进"标签更新.在refspec中设置force标志允许进行特定更新.使用--force
命令行还允许更新,和所有其他参考的更新.换句话说,加号只是一个更具针对性(单个refspec)的版本--force
.
1这是夸大其辞:有时它使用三个参数git fetch
.
2对于远程位始终为true,但refspec位可能为空,pull
脚本在git fetch
完成后确定要在以后应用哪个refspec .
3默认情况下,该fetch
操作还将引入与其引入的任何提交ID匹配的任何标记名称引用.如果你git fetch
自己运行,你可以改变fetch
处理这些的方式,但如果你只是让它git pull
运行,git fetch
你将得到这种默认行为.请注意,做出这些决定的是你的本地git:远程git只是向你的本地git显示所有内容,然后你的git决定是否向你的存储库添加标签.
4从技术上讲,git fetch
只调用执行此操作的C代码,而不是实际运行git config --get-all
.在任何情况下,如果有多个配置条目remote.origin.fetch
,git fetch origin
确实应用所有这些条目.它的做法虽然有点复杂,但我会在这里略过一些血腥的细节.
5远程跟踪分支实际上只是名称以其开头的引用refs/remotes/
,就像本地分支是名称以其开头的引用一样refs/heads/
.这是git中的一般内容:您的标记是名称以其开头的引用refs/tags
.该git stash
脚本使用单个特殊引用refs/stash
.Git的"注释"存储在refs/notes/
,你可以创建自己的引用:只需选择一个不同的起始字符串,并希望将来没有其他人选择相同的新git功能.:-)
归档时间: |
|
查看次数: |
879 次 |
最近记录: |