在 refspec 中使用 git pull 不会影响 pull 命令的合并部分。您可能知道,git pull 本质上只是git fetch 和git merge 的组合;首先,它将从远程获取最新的更改并更新远程跟踪分支,然后将远程跟踪分支合并到当前分支。
现在,正如我所说,refspec 不会影响合并部分,但它只会影响git pull 内部的获取。现在要了解这最终意味着什么,您首先必须了解 refspec 是什么。
refspec 基本上只是远程分支映射到远程跟踪分支的配置。远程分支在这里是远程实际存在的分支,远程跟踪分支是为了跟踪远程分支的状态而创建的分支;对于名为“origin”的远程,其远程跟踪分支都以origin/开头。
如果您没有明确指定 refspec,它会从配置文件中获取。默认表单通常如下所示:
+refs/heads/*:refs/remotes/origin/*
这告诉 Git 获取位于 refs/heads/* 的远程分支并将它们映射到位于 refs/remotes/origin/* 的远程跟踪分支。所以对于远程分支master,refs/heads/master 将映射到refs/remotes/origin/master。领先的 + 还告诉 Git 覆盖远程跟踪分支,无论更改是否可以快进:毕竟,您通常希望远程跟踪分支与 完全远程状态,所以如果历史记录在那里被重写(应该避免)或分支被重命名,你会希望远程跟踪分支仍然尊重这一点。
现在,当您指定 refspec(使用 git fetch 或 git pull)时,默认映射将被覆盖。而是使用您的映射。例如,当您使用git fetch origin master:foo 时,本地分支foo 将被快速转发(如果可能)以指向远程分支master。所以这实际上是更新本地分支的好方法,而不必检查它:如果你遗漏了领先的+,那么如果它不是快进合并,那么更新本地引用(分支)将失败,所以你也可以安全地避免冲突。
但是回到git pull——当你运行命令时发生了什么?正如我所说,拉动只是获取和合并,因此您的 git pull 命令首先执行此操作:
git fetch origin <remote-branch>:<local-branch>
所以从远程获取远程分支,并更新本地分支——如果是快进合并的话。这已经完全符合您的要求:更新<local-branch>。
然后,git pull 的合并部分发生了;为此,Git 通常会运行 git merge FETCH_HEAD。 FETCH_HEAD 是对最后获取的分支的引用。在这种情况下,它指向<local-branch>。所以在获取到<local-branch> 之后,正在执行的命令是git merge <local-branch>。并且运行git merge 将合并到当前分支。
因此,当您在 <different-branch> 并运行 git pull origin <remote-branch>:<local-branch> 时,您将正确更新 <local-branch> 以匹配远程分支,但随后您还将这些更改合并到当前分支 <different-branch>。这就是为什么你会在当前分支的日志中看到那个分支的变化;它们只是简单地合并了。
如果您想避免这种情况,按照我上面的解释,只需将git fetch 与 refspec 一起使用。它已经正确地更新了本地分支(如果可以的话)而不影响当前分支。