git-pull调用中不同refspec之间的差异 [英] Difference between different refspecs in a git-pull call
问题描述
使用以下git命令有什么区别
Whats the difference between using the following git commands
git pull原始主机
git pull origin master:主控
git pull origin master
git pull origin master:master
一些观察
1)第一个告诉我是否有任何冲突,但另一个简单地说被拒绝-非快进"
1) First one tells me if there any conflicts but the other simply says "rejected - non-fast forward "
2)第二个失败时不会更新我的远程指针,即Origin/master.
2) Second one doesn't update my remote pointers i.e. origin/master if it fails
推荐答案
这有点棘手,所以让我们一次处理一下.
This is a bit tricky, so let's deal with it one bit at a time.
git pull
像这样滚动:
-
从以下位置获取给定的refs 1 (示例中的第二个参数,称为 refspec —参考规范"的写法).给定远程(示例中的第一个参数).
Fetches the given refs1 (the second argument in your examples, which is called the refspec — a portmaneu of "reference specification") from the given remote (the first argument in your example).
如果缺少远程参数,则Git尝试使用本地存储库中的branch.<name>.remote
配置变量来获取它,其中<name>
是当前检出分支的名称.
If the remote argument is missing, Git tries to obtain it using the branch.<name>.remote
configuration variable in the local repository, where <name>
is the name of the currently checked out branch.
如果缺少refspec参数,Git会尝试使用本地存储库中的branch.<name>.merge
配置变量来获取它,其中<name>
的含义与上述相同.
If the refspec argument is missing, Git tries to obtain it using the branch.<name>.merge
configuration variable in the local repository, where <name>
means the same thing as above.
将 all 全部合并到当前签出的分支,因此@ Oznerol256不正确.
Merges all the fetched refs to the currently checked out branch, so @Oznerol256 is incorrect.
现在让我们解释一下git pull
…
Now let's explain what's the difference between the refspecs master
and master:master
when it comes to git pull
…
git pull
将refspec直接传递到git fetch
,并以以下方式解析refspec:从远程获取与:
左侧和左侧的规范匹配的所有ref.它们可以更新本地存储库中匹配的引用,该引用由:
右侧的规范指定.关键点在于,如果refspec中没有:
,或者在它的右边没有任何内容,则git fetch
会将其解释为不更新".
git pull
passes the refspec directly to git fetch
, and it parses the refspec in the following way: "take from the remote all the refs matching the spec on the left side of :
and possibly use them to update matching refs in the local repository, which specified by the spec on the right side of :
". The crucial bit here is that if there's no :
in the refspec, or there's nothing to the right of it, this is interpreted as "update nothing" by git fetch
.
现在让我们深入研究.根据参考规范的解释规则,裸露" master"(在大多数情况下为 2 )解释为refs/heads/master
,表示名为« master»的分支".
Now let's dig deeper. According to the rules of interpretation of refspecs, bare "master" is (in most cases2) interpreted as refs/heads/master
, which means "the branch named «master»".
好的,现在应该清楚git pull origin master
:
-
调用
git fetch origin master
,从由origin
指示的遥控器中获取refs/heads/master
,并且仅将获取的对象存储在数据库中(并更新特殊的refFETCH_HEAD
).它不会更新本地存储库中的任何分支或标签.
Calls
git fetch origin master
whch fetchesrefs/heads/master
from the remote indicated byorigin
and just merely stores the fetched objects in the database (plus updates the special refFETCH_HEAD
). It does not update any branches or tags in your local repository.
调用git merge FETCH_HEAD
,该git merge FETCH_HEAD
尝试将从远程存储库获取的refs/heads/master
状态合并到当前已签出的分支中.
Calls git merge FETCH_HEAD
which attempts to merge the state of refs/heads/master
as fetched from the remote repository into the currently checked out branch.
很明显,这可能会导致冲突,这是您在第一种情况下要观察的.
Obviously, this might result in conflicts, and that's what you're observing in the first case.
现在让我们更深入地进行挖掘.现在应该很清楚,master:master
refspec(通常是 2 )扩展为refs/heads/master:refs/heads/master
,因此git pull origin master:master
的滚动方式如下:
Now let's dig yet more deeper. As should be clear by now, the master:master
refspec (usually2) expands to refs/heads/master:refs/heads/master
, and so git pull origin master:master
rolls like this:
-
它调用
git fetch origin master:master
其中
- 从遥控器和
- 获取
refs/heads/master
-
通过获取的对象更新本地
refs/heads/master
.
如果本地主机"未完全包含在远程服务器的主机"中,这可能会因非快进"错误而失败,这就是您正在观察的内容.
This might fail with the "non-fast forward" error, if the local "master" is not wholly contained in the remote's "master", and that's what you're observing.
在这一点上,由于第一步产生了错误,因此未尝试合并.
At this point no merging is attempted since the first step generated an error.
应该注意的是,您的两个示例均未正确地更新本地引用:第一个示例并未尝试更新,而第二个示例则尝试更新了据称错误的引用—.正确的调用是git pull origin +refs/heads/master:refs/remotes/origin/master
,它将强制 (因此+
)更新正确的 remote 分支,然后尝试将获取的内容合并到当前已签出的内容中分支.
It should be noted that neither of your examples properly updates local refs: the first one just does not attempt this, and the second one tries to update a supposedly wrong ref — the correct call would be git pull origin +refs/heads/master:refs/remotes/origin/master
which would forcibly (hence the +
) update the proper remote branch and then attempt to merge what was fetched into the currently checked out branch.
要了解为什么使用这种奇怪的" refspec,让我们看看在调用git fetch origin
时Git使用了什么refspec.因为在这种情况下,它将读取本地存储库中的remote.<remotename>.fetch
配置变量(此变量由git remote add
或git clone
创建):
To understand why such a "strange" refspec is used, let's see what refspec Git uses when you call git fetch origin
— since in this case it reads the remote.<remotename>.fetch
configuration variable in the local repository (this variable is created by git remote add
or git clone
):
$ git config --local --get remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*
如您所见,它告诉git fetch
强制更新并更新远程分支.
As you can see, it tells git fetch
to force updates and to update remote branches.
现在可以看到,git pull
经常被漫不经心地过度使用,而没有真正了解其内部工作原理.我认为,最好使用两步操作而不是拉动:
It could be seen by now that git pull
is frequently and mindlessly overused without actually understanding its inner workings. In my opinion, it's way better to use two step operation instead of pulling:
-
git fetch origin
—更新远程分支. -
git merge origin/master
—将最后出现在原始"上的主"状态合并到当前已签出的分支中.
git fetch origin
— to update remote branches.git merge origin/master
— to merge the state of "master" as last seen on "origin" into the currently checked out branch.
如果将当前签出的分支设置为跟踪要合并的远程分支,则Git调用将变得更加简单:
If the currently checked out branch is set to track a remote branch which you want to merge, the Git call becomes even simpler:
git merge @{u}
我还建议您阅读本文
1 在Git中,"ref"是一个以命名的实体,它指向一个提交(简单或直接引用)或另一个引用(符号ref—). HEAD
是符号ref).分支和标记是简单引用的示例,HEAD
可能两者都是:当您签出分支时,它是一个符号引用;当您签出其他任何内容时(因此处于分离头"状态),这很简单.参考
1 A "ref" in Git parlance is a named entity which points to a commit (simple or direct ref) or to another ref (a symbolic ref — HEAD
is a symbolic ref ). Branches and tags are examples of simple refs, HEAD
might be both: when you have a branch checked out it's a symbolic ref, when you have anything else checked out (and hence are in the "detached HEAD" state) it's a simple ref.
2 如果有标签和名为"master"的分支,则refspec将解析为标签的名称—.标签优先.在这种情况下,可以使用完整的ref名称来指定分支.
2 If there's a tag and a branch named "master", the refspec will be resolved as the name of the tag — tags have precedence. In a situation like this, a full ref name could be used to designate the branch.
这篇关于git-pull调用中不同refspec之间的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!