Git提取无法解决git checkout上的pathspec错误-*

时间:2018-08-08 14:28:56

标签: git git-checkout

在以前的项目中,我经常运行git checkout -- *来丢弃工作目录中的所有更改。

  1. 在我当前的项目中,我得到以下信息:

    $ git checkout -- *
    error: pathspec 'node_modules' did not match any file(s) known to git.
    
  2. 然后我做一个git status

    $ git status
    On branch <feature_branch>
    Your branch is ahead of 'origin/<feature_branch>' by 2 commits.
      (use "git push" to publish your local commits)
    
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git checkout -- <file>..." to discard changes in working directory)
    
        modified:   <relative_file_path_in_current_app_dir>
    
    no changes added to commit (use "git add" and/or "git commit -a")
    
  3. 我阅读了另一个StackOverflow post,其中说git fetch可以解决此pathspec错误。我试过了,它从远程启动了一个新的功能分支:

    $ git fetch
    remote: Counting objects: 67, done.
    remote: Compressing objects: 100% (67/67), done.
    remote: Total 67 (delta 55), reused 0 (delta 0)
    Unpacking objects: 100% (67/67), done.
    From https://bitbucket.org/<repo_name>
       b42b31e05..e7f3858ad  <unrelated_bug_branch>       -> origin/<unrelated_bug_branch>
       36b2cd4e9..ac87583fd  develop                      -> origin/develop
       61945b8ef..22a63fd7e  <unrelated_feature_1_branch> -> origin/<unrelated_feature_branch>
       322a39980..1f8752f2c  <unrelated_feature_2_branch> -> origin/<unrelated_feature_2_branch>
     * [new branch]          <unrelated_feature_3_branch> -> origin/<unrelated_feature_3_branch>
       5fe02b8b3..a27140571  <unrelated_feature_4_branch> -> origin/<unrelated_feature_4_branch>
    
  4. 我还要再做一次git status,与上面的#2一样。

  5. 我可以定位到特定文件,并且可以运行:

    $ git checkout -- <relative_file_path_in_current_app_dir>
    
  6. git status现在显示我有一棵干净的工作树。

我的pathspec错误的根本原因是什么?如何解决?在此期间,我可以检出特定文件,但是我对此错误感到好奇。

1 个答案:

答案 0 :(得分:2)

恐怕链接的问题Git: cannot checkout branch - error: pathspec '...' did not match any file(s) known to git是一团糟:正如您所指出的,它有很多答案,而且很少说明。同时ElpieKay's comment有一个正确的答案:node_modules是您要让Git忽略的文件或目录,因此当您要求Git更新它时,它说:嗯?立即更新吗?

详细说明

问题的根源在于Git将太多东西塞进一个命令中。 git checkout命令可以:

  • 根据一些现有的远程跟踪名称(例如develop)自动创建一个新分支(例如,新的分支 name 例如origin/develop);或
  • 检出现有分支(具有给定名称的分支,例如master);或
  • 检出现有的历史记录提交(例如,通过标记名,例如v1.2,或通过原始哈希ID),从而导致Git称为分离的HEAD

所有这些操作以某种方式移动了Git的HEAD概念。特殊名称HEAD(所有大写字母,这在Linux系统上通常是必需的,而Windows用户通常可以通过小写键入head来逃避)是Git记住您所在的分支的方式。因此,以上三种git checkout会更改您在哪个分支上,或者-听起来很吓人,但实际上在内部却很正常, 1 分离了HEAD情况,没有任何分支机构。


例如,当您处于冲突或交互基础时,

1 Git使用此分离的HEAD状态。将其用于正常开发不是一个好主意,但对于临时工作或这些内部状态到Git状态则很好。只需完成您的变基,或者导致HEAD临时分离的任何原因,Git就会重新连接HEAD,您可以继续进行头部固定的连接。 :-)


但是git checkout可以做很多涉及的事情,而根本不涉及更改HEAD,这就是git checkout --的目的。在这里,Git可以:

  • 从您的索引中提取一个或多个文件到您的工作树: git checkout -- filename(s),或
  • 从特定提交中提取一个或多个文件,先将其写入索引,然后再写入工作树:git checkout commit-specifier -- filename(s)

--从文件名中分隔提交说明符,例如masterdevelop1f3a907或其他名称。如果文件名为--,{em}通常是mastergit checkout master会将您的HEAD切换为master,而不是检查删除名为master文件。有时是可选的:如果您有一个名为master的文件,但您想从develop的尖端获取副本,则编写git checkout develop master可以使Git清楚(即使它离开普通人感到困惑)。

git checkout可以做更多的事情,但让我们从这三组明显不同的操作中停止:(1)将HEAD更改为另一个分支,( 2)将HEAD更改为要在特定的提交上分离,并且(3)根本不更改HEAD,只需从索引或文件中获取一个文件或多个文件即可具体提交

Git在the git checkout documentation中使用各种语法标记来表达这些不同的动作。引用它—我将引用其中包含的整个可怕的七个项目列表—我们看到:

  

git checkout [-q [-f] [-m] [<branch>]
   git checkout [-q [-f] [-m] --detach [<branch>]
   git checkout [-q [[-f] [-m] [--detach] <commit>
   git checkout [{-q] [-f] [-m] [[-b | -B | --orphan] <new_branch> [<start_point>]
   git checkout [-f | --ours | --theirs | -m | --conflict=<style>] [<tree-ish>] [--] <paths>...
   git checkout [<tree-ish>] [--] <pathspec>...
   git checkout -p | --patch)[<tree-ish>] [--] [<paths>...]

其中三个是我们在此答案中讨论的操作(另外四个是git checkout可以做的更多操作,其中某些操作可能与Git命令不同)。让我们来看看它们。

按名称签出分支(或签出提交并分离HEAD)

从第一行开始:

  

git checkout [<branch>]

(我省略了简化选项)。这会在尖括号中显示分支名称,这意味着您应该填写一个。在方括号中也是如此,因此您可以忽略它,但是如果您 do 忽略它,则表示“保持当前分支”,这是一件很愚蠢的事情。将branch放在这样的尖括号中,将其标记为某些人所说的元变量,即您应该使用 name 填写的内容元变量告诉您​​什么种类会在这里:分支名称!

这是切换到某些现有分支的方法,或者根据某些现有的远程跟踪名称操作创建新的分支。您提供的分支名称是要切换到或自动创建的分支名称。 Git将查找具有该名称的现有分支,如果找不到该分支,将遍历您的所有远程跟踪名称-您的origin/masterorigin/develop等上-查看是否其中一个 名称可以删除origin/并成为您要求的名称。

(第二引号行与第一行类似,但是插入了--detach。第三行与前两行类似,但是不是<branch>,而是<commit>。第二个命令行是--detach,第三个是可选的。<commit>元变量意味着您可以使用任何可以命名提交的东西,而不仅仅是分支名称。产生分离的HEAD的变体:它们以与切换分支相同的方式签出一次提交,但是它们在此过程中将HEAD砍掉,因此您位于 no 分支上。 {1}}一个命名为提交但不是分支名称的参数,Git仅假定您 meant git checkout。如果要在使用分支名称时分离,则必须添加{ {1}}。这不是大多数人想要做的,但手册页面还是会介绍它。)

链接的问题及其答案主要是关于使用远程跟踪名称创建新分支即,他们回答了以下问题:

  

如果我说--detach时遇到错误,但是我运行--detach,然后再次执行git checkout feature-X,它可以正常工作。为什么?

这里的答案是,第一次运行git fetch时,您没有拥有git checkout feature-X,但是在git checkout develop完成后,您没有有一个origin/feature-X。反过来,这是因为git fetch创建了它,是因为其他人origin/feature-X上创建了git fetch的时间相对较近。 feature-X的Git在origin调用Git,并获取其所有分支和提交的列表。您的Git加载了您尚未使用的所有新提交,并创建或更新了您的所有git fetch名称,现在您有了origin

检出特定文件

倒数第二句语法行:

  

git checkout [origin/* [origin/feature-X] <tree-ish>

显示两个元变量。第一个拼写为--,它是Git的简写:您可以在此处使用分支名称,提交哈希或可以用来查找树对象的任何东西。 Git有很多 指定提交哈希ID的方法,这旨在涵盖所有这些ID,以及一些您不太可能遇到的更怪异的极端情况。这个第一个元变量是可选的,如果您忽略它,Git将从Git的 index 中检出文件(我们在这里没有详细描述,我不会在此赘述)已经足够长了。

第二个元变量为<pathspec>...。请注意,这不是 可选!这是Git所说的文件名或带有<tree-ish>的模式的缩写,或者是其他太长的内容也无法在此处使用。 {1}}部分意味着您可以列出其中多个。这些 pathspecs 命名您要Git在<pathspec>(您命名的提交,如果您命名的提交)中找到的特定文件或文件

哪里出错了

写时:

*

您的shell(可能是...)会扩展<tree-ish>,以匹配当前工作目录中的所有文件。 2 因此,如果您有文件git checkout -- * bash*等, Git 看到的是:

README

没有hello,因此Git在索引中查找名为node_modulesgit checkout -- README hello node_modules ... <tree-ish>等的文件。

如果没有找到 其中之一-并且找不到README-Git会抱怨:

hello

什么也不做。

如果您改用node_modules,则shell运行:

node_modules

并且Git将error: pathspec 'node_modules' did not match any file(s) known to git. 视为.参数。这意味着“当前目录中Git已知的所有文件”,这样就可以完成您想要的操作。您还可以写:

git checkout -- .

使用引号来保护.(或您正在使用的任何shell)不受<pathspec>的侵害。然后 Git 将看到git checkout -- '*' ,而 Git 将展开*到“当前目录中Git已知的所有文件”。但是编写bash更容易。


2 请注意,在Windows上,CMD.EXE 不会展开*,而是将其传递给Git,让 Git 展开*,此错误就永远不会发生!