git-pull调用中不同refspec之间的差异 [英] Difference between different refspecs in a git-pull call

查看:78
本文介绍了git-pull调用中不同refspec之间的差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用以下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像这样滚动:

  1. 从以下位置获取给定的refs 1 (示例中的第二个参数,称为 refspec —参考规范"的写法).给定远程(示例中的第一个参数).

  1. 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参数,G​​it会尝试使用本地存储库中的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:

  1. 调用git fetch origin master,从由origin指示的遥控器中获取refs/heads/master,并且仅将获取的对象存储在数据库中(并更新特殊的ref FETCH_HEAD).它不会更新本地存储库中的任何分支或标签.

  1. Calls git fetch origin master whch fetches refs/heads/master from the remote indicated by origin and just merely stores the fetched objects in the database (plus updates the special ref FETCH_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:

  1. 它调用git fetch origin master:master其中

  1. 从遥控器和
  2. 获取refs/heads/master
  3. 通过获取的对象更新本地 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/masterwhich 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 addgit 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:

  1. git fetch origin—更新远程分支.
  2. git merge origin/master—将最后出现在原始"上的主"状态合并到当前已签出的分支中.

  1. git fetch origin — to update remote branches.
  2. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆