每当我[使用] ... git checkout 050aa9f
... git 立即分离头部
那是因为这种git checkout
是专门的 detach 请求HEAD
。
每当您使用不是分支名称但可以解析为提交哈希 ID 的东西时,git checkout
都会将您置于 detached-HEAD 模式。但是任何时候你使用一个分支名称,都会git checkout
让你进入正常模式。(Git 没有将此称为“attached-HEAD”模式,但这显然是该模式的正确名称。)
这里有几个棘手的地方,其中一些可以通过使用VonC 推荐git switch
的新命令(在 Git 2.23 及更高版本中)得到部分帮助。我将在这里介绍它们,但请记住其中一些是高级 Git,您不会立即了解所有内容。
Git 可以创建一个新分支,然后按名称检查该分支,从而生成一个附加的 HEAD。
--detach
即使您提供了分支名称,您也可以使用分支名称来强制 Git 进入分离 HEAD 模式。
使用该-b
选项,Git 将始终尝试创建一个新的分支名称(然后附加到它)。这在某些情况下可能会失败,但我不会在这里详细介绍。
使用该--track
选项,您可以命名远程跟踪名称,origin/develop
Git 将使用该名称来确定要创建的分支名称。Git 在这里选择的名称是通过剥离远程部分形成的,因此 running与 runninggit checkout --track origin/develop
大致相同git checkout -b develop --track origin/develop
。我说的大致相同,因为其他选项可以修改此行为。
该git checkout
命令本身实现了在 Git 2.23 及更高版本中被拆分为两个单独命令的内容:git switch
和git restore
. 在某些情况下,当您期望git checkout
执行我将要描述的操作时,Git 会发现您有一个名为的文件或文件夹dev
,并实现现在拆分为git restore
的内容,而不是现在的内容git switch
。这......不是一件好事,我们只是说,从 Git 2.23 开始,git checkout
现在告诉你它不确定你在这里的意思,并且不只是做错事。
给出一个不存在但可以创建的分支的名称,有时会导致创建该分支。例如,如果您还没有一个名为 的分支dev
,但确实有一个origin/dev
,并且您运行了git checkout dev
,那么您可能希望 Git 说:Huh ... there's no branch nameddev
和 no file-or-folder named dev
。我不能把它变成一个分支名称,所以我会因为错误而退出。 但事实并非如此。相反,Git 对自己说:嗯,没有名为的分支dev
,也没有名为的文件或文件夹。但是有一个origin/dev
。我敢打赌你想让我创建一个名为 的分支dev
,就好像你已经运行了git checkout --track origin/dev
. 然后它会这样做。
值得准确描述一下旧版本出了什么问题,git checkout
而新git switch
/git restore
拆分则没有。(而且,正如我所提到的,git checkout
它本身已经变得更智能,因此它现在不会盲目地做错事——但是对于 2.23 之前的 Git 版本,请注意!)这两种“类型”git checkout
是:
切换分支的那个。这是一个非破坏性的命令:如果你有未提交的工作,git checkout
可以让你切换分支,但它只会这样做,如果你的未提交的工作不会在这个过程中被破坏。(这个很复杂,先别看,不过这个问题就是这么回事。)
在 Git 2.23 中,您可以使用git switch
执行此命令。你仍然可以使用git checkout
,也是。
破坏你未完成工作的那个。这是破坏性的命令!假设您一直在编辑一些文件,并且您决定尝试做一些有用的事情没有结果,现在应该被彻底地、不可挽回地摧毁。您希望将事情恢复到原来的样子——至少对于一个特定的文件,也许对于几个文件。
在 Git 2.23 中,您可以使用git restore
来执行此命令,但在每个版本的 Git 中,您也可以git checkout
在此处使用。
这意味着一种git checkout
是完全安全的:它永远不会破坏正在进行的工作。另一种git checkout
是非常危险的:你告诉 Git请彻底清除我正在进行的工作,不可挽回。
这就是我上面提到的危险。dev
假设您在一个名为的文件夹中有一堆文件和一个远程跟踪名称origin/dev
,但您还没有一个名为 的分支dev
。如果你运行:
git checkout dev
期望 Git 创建一个名为dev
now 基于的分支origin/dev
,你会得到一个令人讨厌的惊喜:Git(2.23 之前)会清除你对文件所做的任何工作dev/*
。
(还有更多git checkout
可以做的事情,所有这些现在都是拆分命令的一部分。我把这些都留了下来以保持这个答案简短。好吧,无论如何,更短。)