为什么Git无法重置以拉取请求

时间:2019-03-05 05:32:54

标签: git pull-request

有时候,我登录到云实例,提取一个仓库,然后想尝试一个提取请求。我现在使用的命令是

::-webkit-scrollbar {
  width: 5px;
}
::-webkit-scrollbar-track {
  background: #f1f1f1; 
}
::-webkit-scrollbar-thumb {
  background: #888; 
}
::-webkit-scrollbar-thumb:hover {
  background: #555; 
}

很长。我还尝试了更短的方法

git fetch origin pull/<ID>/head && git checkout FETCH_HEAD

出现以下错误

git reset --hard origin/pull/<ID>
git reset --hard origin/pull/<ID>/head
git reset --hard origin/pull/<ID>/HEAD

为什么$ git reset --hard origin/pull/27 fatal: ambiguous argument 'origin/pull/27': unknown revision or path not in the working tree. Use '--' to separate paths from revisions, like this: 'git <command> [<revision>...] -- [<file>...]' 起作用,但请求请求分支无效?

我注意到在

的输出中
git reset --hard origin/<some-branch>

常规分支与拉取请求分支之间存在差异。例如

  

c31a55 refs / heads / fix-async-stdout-order

     

615f5a refs / pull / 10 / head

$ git ls-remote origin heads有何区别? (我在这里缩短了哈希值,因此在外观上更加简洁)

2 个答案:

答案 0 :(得分:1)

每个Git存储库都有自己的名称副本。每个名称都精确地映射到一个哈希ID,例如在您的示例中:

  
c31a55 refs/heads/fix-async-stdout-order
615f5a refs/pull/10/head
  

您建议refs/heads/fix-async-stdout-order映射到哈希ID c31a55,而refs/pull/10/head映射到哈希ID 615f5a 1

名称是Git称为 refs references 的东西。 (哈希ID是您现在应该非常熟悉的哈希。)

在大多数情况下,当给Git命名时,Git会立即将其转换为基础哈希ID。哈希ID才是真正重要的:提供这些名称主要是为了让我们(仅仅是人类)能够处理作为哈希ID的 real 名称。哈希ID永远不会改变:它们始终唯一地标识该特定内容,例如,一个特定的提交。提交及其哈希ID是永久的,而一个或多个名称可以随意创建或销毁。 2

当名称标识提交时,我们可以直接使用该名称查找提交:例如,refs/heads/fix-async-stdout-order标识提交c31a55。但是,提交还使我们能够找到其直接的 parent 提交:从c31a55我们可以向后追溯到其父级,然后从该父级向后进行另一步提交,再到另一个提交,依此类推,一直到存储库中的时间开始。因此,这样的名称不仅可以找到它存储其哈希ID的提交,而且还可以找到其链中的所有早期提交

当这个名字是一个 branch 名称时(就像这个名字一样),Git还允许我们专门将其与git checkout一起使用。 git checkout命令将另一个特殊名称HEAD附加到分支名称。 Git现在认为我们在分支上,因此,如果我们提交 new 提交,Git将自动更改存储在该分支名称下的哈希ID

也就是说,在之后:

git checkout fix-async-stdout-order

如果我们做了一些工作然后提交了一个 new 提交,名称fix-async-stdout-order(实际上是refs/heads/fix-async-stdout-order,我们只是出于显示目的将其缩写了)停止指向提交c31a55,而是开始指向我们的新提交。我们的新提交将以c31a55作为父提交。

只能在分支名称中使用此属性(能够“进入”分支)。 Git有许多名称:分支名称,标签名称,远程跟踪名称等等。它们都是引用,但是只有拼写以refs/heads/开头的引用才是分支名称。

引用refs/tags/v1.2(如果存在)是名为v1.2标签

引用refs/remotes/origin/master(如果存在)是远程跟踪名称 origin/master

每个前缀refs/heads/refs/tags/refs/remotes/代表namespacerefs/heads/名称空间中的引用是分支名称

除了允许git checkout以上述方式使用它们之外, branch 名称的另一个特殊功能还发生在客户端Git时,例如您自己的Git —连接到服务器Git。服务器Git为客户端显示其所有名称,包括分支名称,以及这些名称代表的哈希ID。 client Git 向下复制服务器的分支名称,但同时更改它们,以便服务器呼叫refs/heads/master,客户端呼叫refs/remotes/origin/master

此过程是您的 Git首先使用远程跟踪名称的过程。服务器Git有分支,当您运行git fetch时,您的Git就会出现,然后看到并记住其分支作为您的远程跟踪origin/*名称。它们位于refs/remotes/名称空间的Git中。

此过程仅对分支名称进行 3 由于refs/pull/10/head并非以refs/heads/开头,因此它不是分支名称。该过程不适用于refs/pull/10/head。这就是headspull不同的原因和原因。


1 这两个都是缩写哈希ID;当前,实际的哈希ID始终为40个字符。

2 需要注意的是,没有名称可以让您找到一个提交或其他Git对象,该提交或其他对象现在不受保护来自Git的垃圾回收过程。因此,名称不仅可以使我们在链中找到 last 提交,而且还可以保护该提交的所有前身免遭垃圾回收。

3 该过程是可编程的,通过Git称为 refspecs 。上面的描述仅适用于运行git clone时得到的 default refspec。如果您自己编写参考规范,则可以更改此处的操作。请参见the git fetch documentation,并注意remote.origin.fetch累积设置; remote.origin.fetch的每个实例都提供一个参考规范。

克隆时的默认设置是Git创建一个remote.origin.fetch设置,该设置可以将其分支的全部复制到您的远程跟踪名称,或者复制一个--single-branch,则将其分支的em>更改为一个远程跟踪名称。

答案 1 :(得分:0)

GitHub suggestsgit fetch origin pull/ID/head:BRANCHNAME:通过这种方式,您可以控制本地分支命名约定,而不是创建(由于GitHub上PR的默认refspec)

但是您有more advance techniques here

[alias]
copr = "!f() { git fetch -fu ${2:-origin} refs/pull/$1/head:pr/$1 &&
                    git checkout pr/$1; }; f"

然后:

$ git copr 1234            # gets and switches to pr/1234 from origin
$ git copr 789 upstream    # gets and switches to pr/789 from upstream

hub 也因包装PR导入而闻名。