使用多个遥控器,我签出了一个提交,做了一些更改并创建了一个新分支,当我签出到任何分支时,我得到分离的头错误



我的目标:成功结账,没有分离的HEAD错误。

到目前为止我做了什么:目前我有两个遥控器设置:

起源 :它指向我目前正在学习的课程的存储库。

fsprojects :它指向我的个人回购。

$ git remote
fsprojects
origin

$ git remote show fsprojects
* remote fsprojects
Fetch URL: https://github.com/fs-projects/core-concepts-nextjs.git
Push  URL: https://github.com/fs-projects/core-concepts-nextjs.git
HEAD branch: events-projects-finsih
Remote branches:
client-and-serverside-fetching-useswr                            tracked
events-project-data-fetching-pre-rendering                       tracked
events-projects-finsih                                           tracked
nextjs-optimisations                                             tracked
project-api-routes                                               tracked
ssg-functions                                                    tracked
writing-api-in-same-server-and-leveraging-from-server-and-client tracked
Local branch configured for 'git pull':
project-api-routes merges with remote project-api-routes
Local ref configured for 'git push':
project-api-routes pushes to project-api-routes (up to date)

我在远程"源">中签出了一个提交,所以我进入了一个分离的 HEAD 状态(正如预期的那样)。我在分离的 HEAD 状态中做了一些新的更改,并从该点创建了一个新的分支项目-api-routes

我现在使用此命令设置此分支以跟踪位于fsprojects/projects-api-routes中的同名远程分支 -

git branch -u fsprojects/project-api-routes

git status输出:

$ git status
On branch project-api-routes
Your branch is up to date with 'fsprojects/project-api-routes'.
nothing to commit, working tree clean

现在,当我使用以下命令签出属于远程fsprojects的任何分支时

git checkout remotes/fsprojects/events-projects-finsih

我得到以下错误:

$ git checkout remotes/fsprojects/events-projects-finsih
Note: switching to 'remotes/fsprojects/events-projects-finsih'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at 539cfbe All events projects - finish up all pages

尽管我的源是一个分支而不是任何提交 id,但我无法理解为什么会出现此错误。

我想签出到目标分支,没有任何分离的 HEAD 错误。实现它的任何帮助/指导都将有所帮助。提前感谢!!

仅供参考 -

git branch -a(查看可以签出的所有分支的列表)给出以下输出:

MINGW64 /d/Next.Js/nextjs-course-code ((539cfbe...))
$ git branch -a
* (HEAD detached at fsprojects/events-projects-finsih)
main
project-api-routes
remotes/fsprojects/client-and-serverside-fetching-useswr
remotes/fsprojects/events-project-data-fetching-pre-rendering
remotes/fsprojects/events-projects-finsih
remotes/fsprojects/nextjs-optimisations
remotes/fsprojects/project-api-routes
remotes/fsprojects/ssg-functions
remotes/fsprojects/writing-api-in-same-server-and-leveraging-from-server-and-client
remotes/origin/01-getting-started
remotes/origin/01-getting-started-extra-files
remotes/origin/02-file-based-routing
remotes/origin/02-file-based-routing-extra-files
remotes/origin/03-prj-routing
remotes/origin/03-prj-routing-extra-files
remotes/origin/04-data-fetching
remotes/origin/04-data-fetching-extra-files
remotes/origin/05-prj-data-fetching
remotes/origin/06-optimizations
remotes/origin/07-api-routes
remotes/origin/07-api-routes-extra-files
remotes/origin/08-prj-api-routes
remotes/origin/08-prj-api-routes-extra-files
remotes/origin/09-context
remotes/origin/09-context-extra-files
remotes/origin/10-prj-blog
remotes/origin/10-prj-blog-extra-files
remotes/origin/11-deployment
remotes/origin/11-deployment-extra-files
remotes/origin/11-deployment-static
remotes/origin/12-auth
remotes/origin/12-auth-extra-files
remotes/origin/HEAD -> origin/main
remotes/origin/empty
remotes/origin/main
remotes/origin/starting-prj
remotes/origin/zz-nextjs-summary
remotes/origin/zz-nextjs-summary-extra-files
remotes/origin/zz-prj-nextjs-summary
remotes/origin/zz-prj-react-summary
remotes/origin/zz-react-summary
remotes/origin/zz-react-summary-extra-files

让我补充几点。 (这应该是一个注释,但我想使用格式 - 我将像往常一样超出注释长度限制。 )

  1. 你用git checkout remote/name说:

    我得到以下错误:

    You are in 'detached HEAD' state. ...
    

    从技术上讲,这不是一个错误。 这只是一个提示/警告消息,表明您做了一些您可能不想要的事情。git switch命令将(如 joanis 在注释中指出的那样)产生错误,并且不会将您置于分离的 HEAD 状态。

  2. git checkoutgit switch都有一个--guess选项(默认情况下处于打开状态)。 显式选项(也附带git config设置)是 Git 2.30.0 中的新功能,因此如果您的 Git 版本比这更早,它将缺少--guess--no-guess选项,并且始终打开猜测。

猜测模式,以前称为 DWIM模式(DWIM= 做我的意思,vs "做我说的"),一直是git checkout的一项功能,现在git switch允许您从远程跟踪名称创建(本地)分支名称,而无需明确告诉 Git远程跟踪名称创建分支名称。 但在我们正确描述这一点之前,我们必须首先定义分支名称和远程跟踪名称之间的区别。 其实很简单:

  • 分支名称在内部是内部拼写以refs/heads/开头的名称。

  • 远程跟踪名称在内部是内部拼写以refs/remotes/开头的名称。

不幸的是,这些内部拼写不会显示在git branch输出中 - 无论如何都不会直接显示。 下面是git branch -a输出的片段,其中显示了显示的内容:

main
project-api-routes
remotes/fsprojects/client-and-serverside-fetching-useswr
remotes/fsprojects/events-project-data-fetching-pre-rendering
remotes/origin/main
remotes/origin/starting-prj

名称main是一个分支名称:它通过从前面剥离refs/heads/来显示,以便refs/heads/main显示为main

名称project-api-routes同样是分支名称。

名称remotes/fsprojects/client-and-serverside-fetching-useswr是一个远程跟踪名称:在本例中,它通过从refs/remotes/fsprojects/client-and-serverside-fetching-useswr前面剥离refs/来显示。

出于某种原因——我不知道这个原因是什么;它在 00 年代初(也许在 2001 年至 2004 年之间)消失在历史中——git branch -r会从远程跟踪名称中删除refs/remotes/,但git branch -a只从它们中删除refs/;但与此同时,git branch -a并没有停止从(本地)分支名称中剥离heads/。 例如,如果git branch -a只从所有内容中剥离refs/,可能会更一致。 但它就是这样,而且大部分都是可用的:

  • 请注意,如果您意外(或故意)创建了一个全名为refs/heads/remotes/origin/main本地分支,git branch -a将显示两次remotes/origin/main
  • 其中之一将是(本地)分支remotes/origin/main,全名refs/heads/remotes/origin/main
  • 另一个是远程跟踪remotes/origin/name,全名refs/remotes/origin/main
  • Git不会混淆两者,但您可能会混淆! (幸运的是,默认情况下,打开颜色模式git branch -a将显示分支名称为绿色,远程跟踪名称为红色。

当您运行git fetch时,远程跟踪名称就会出现。 您可以使用git fetch调用远程存储库(另一个 Git 存储库,例如,您以名称originfsprojects存储其 URL),并且该Git 存储库具有分支名称。 您的 Git 软件将这些分支名称复制到您的 Git 存储库,但为了避免覆盖您的分支名称,请重命名这些分支名称,将它们转换为远程跟踪名称。

无论如何,既然您了解了远程跟踪名称和分支名称之间的区别(后者是 Git 对其他 Git 分支名称的记忆),并且当给定远程跟踪名称时,git checkout将进入分离 HEAD 模式,您也准备好了解--guess或 DWIM 选项。

假设像现在的情况一样,您没有分支名称xyzzy(也没有具有该名称的文件)。 如果运行:

git checkout xyzzy

或:

git switch xyzzy

然后这些命令将尝试使用xyzzy作为分支名称。这将失败,因为没有这样的分支名称。 (旧的和不太好的git checkout命令接下来也会尝试将其作为文件名,这是您可能希望在此处专门开始使用git switch的原因之一。 但是让我们假设这也失败了。

现在,如果xyzzy不是分支名称,则尝试切换到该分支会失败。 它现在几乎失败了,但现在,两个命令都会检查是否启用了--guess- 而且确实如此! 因此,这两个命令现在都会查看您的所有远程跟踪名称

如果某个远程跟踪名称以/xyzzy结尾,则该远程跟踪名称与您要求的分支名称(某种)匹配。 也就是说,如果有refs/remotes/fsprojects/xyzzy,那就是候选匹配。 如果有refs/remotes/origin/xyzzy,那也是候选匹配

找到一定数量的候选匹配项(零个、一个、两个,如果有更多的遥控器,则可能更多),guess代码现在检查匹配项的数量。 当且仅当只有一个匹配项时,--guess代码会将您的命令从:

git switch xyzzy

自:

git switch --track <remote-tracking-name>

这会使用指定的远程跟踪名称创建一个新的(本地)分支(xyzzy)。

如果没有匹配项,或者有两个或多个匹配项,猜测代码将失败。 因此,如果您有remotes/origin/xyzzyremotes/fsprojects/xyzzy--guess模式将失败。 如果两者都没有(现在就是这种情况),--guess模式也会失败。

为什么我要为此持续这么久

大多数Git 克隆只有一个远程,名为origin。 因此,在大多数克隆中,您可以运行:

git switch develop

即使你还没有develop,只要你有origin/develop.--guess模式(默认处于打开状态)将找到origin/develop创建您自己的develop

但是,一旦您有两个遥控器,--guess模式通常会停止工作,因为两个遥控器都有develop。 Git 还有另一个配置设置来再次执行此操作:

checkout.defaultRemote
当您运行git checkout <something>git switch <something>并且只有一个遥控器,它可能 隐式回退到结帐和跟踪,例如origin/<something>.一旦您超过,这将停止工作 一个带有<something>参考的遥控器。此设置允许 设置首选遥控器的名称,该遥控器应始终获胜 来消除歧义。典型的用例是将其设置为origin.

也就是说,checkout.defaultRemote说,如果--guess代码中有两个或多个匹配项,并且其中一个来自指定的远程,则使该匹配项"获胜",就好像它是唯一的匹配项一样。

如果这感觉像鲁布·戈德堡的机器,那是因为它确实如此。 我几乎希望 Git 一开始就没有--guess模式。 请注意,您可以运行:

git switch -t origin/somebranch

origin/somebranch创建somebranch,所以--guess模式不会购买很多东西(它可以让您避免键入-t以及远程名称和斜杠)。

您问题中的几乎所有细节(多个遥控器,您之前所做的)都无关紧要。事实很简单:检查远程跟踪分支,例如

git checkout remotes/fsprojects/events-projects-finsih 

(?)确实是一个超脱的头。唯一分离的结帐是本地分支的名称。这就是所有需要知道的,也是你需要知道的,关于分离的头。

因此,鉴于您的分支列表

git branch -a
main
project-api-routes
remotes/fsprojects/...

。您可以执行的唯一非独立结帐是mainproject-api-routes.这些是您拥有的唯一本地分支名称。如果要以非分离方式签出另一个提交,则需要创建指向它的另一个本地分支名称。

最新更新