我今天结束了一个分离的头,同样的问题描述:git推送说所有最新的,即使我有局部的变化
据我所知,我没有做任何不同寻常的事情,只是从本地回购中提交和推送。
那么,我是如何得到一个分离的头部的呢?
我今天结束了一个分离的头,同样的问题描述:git推送说所有最新的,即使我有局部的变化
据我所知,我没有做任何不同寻常的事情,只是从本地回购中提交和推送。
那么,我是如何得到一个分离的头部的呢?
任何不是分支名称的提交签出都会得到一个分离的HEAD。SHA1表示树枝的顶端,仍然给出一个分离的HEAD。只有签出本地分支名称才能避免这种模式。
参见使用分离的HEAD进行承诺
当分离HEAD时,除了没有更新命名分支外,提交工作正常。(您可以将其视为一个匿名分支。)
例如,如果您签出一个“远程分支”而没有首先跟踪它,您可能会得到一个分离的HEAD。
见git:开关分支没有分离头
意思是:git签出origin/main(或者以前的origin/master)会导致:
Note: switching to 'origin/main'.
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 a1b2c3d My commit message
这就是为什么你不应该再使用git checkout,而应该使用新的git switch命令。
使用git switch,同样尝试“签出”(切换到)远程分支将立即失败:
git switch origin/main
fatal: a branch is expected, got remote branch 'origin/main'
添加更多git开关:
使用Git 2.23(2019年8月),你不必再使用令人困惑的Git checkout命令了。
git switch也可以签出一个分支,并获得一个分离的HEAD,除了:
它有一个显式的—detach选项
在不创建新分支的情况下提交HEAD~3进行临时检查或实验: git开关——分离HEAD~3 HEAD现在在9fc9555312合并分支cc/shared-index-permbits
它不能错误地分离远程跟踪分支
See:
C:\Users\vonc\arepo>git checkout origin/master
Note: switching to 'origin/master'.
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.
Vs.使用新的git switch命令:
C:\Users\vonc\arepo>git switch origin/master
fatal: a branch is expected, got remote branch 'origin/master'
如果你想创建一个新的本地分支来跟踪一个远程分支:
git switch <branch>
如果没有找到<分支>,但是在恰好一个远程(称其为<远程>)中存在一个具有匹配名称的跟踪分支,则将其等效于 Git开关-c <分支>——track <远程>/<分支>
别再犯错了! 没有更多不想要的分离头!
如果你使用git switch <tag>而不是git switch——detach <tag>, git 2.36会帮助你记住缺失的——detach选项。
如果您试图通过重新签出文件而撤消所做的更改,并且语法不完全正确,则很容易发生这种情况。
你可以看看git日志的输出——你可以把上次成功提交后的日志尾部粘贴到这里,我们都可以看到你做了什么。或者你可以粘贴它,然后在freenode IRC上的#git中询问。
我刚才无意中重复了这句话:
列出远程分支 Git branch -r /功能/ f1234起源 来源/主 我想在本地签出一个,所以我剪切粘贴: git checkout origin/Feature/f1234 您看!分离HEAD状态 你处于“分离的头部”状态。[…])
解决方案1:
不包括起源/在我的分支规格前检查时:
git checkout Feature/f1234
解决方案2:
添加-b参数,用于从远程创建本地分支
git checkout -b origin/Feature/f1234或
git checkout -b Feature/f1234它会自动回到原点
try
git reflog
这给了你一个HEAD和分支指针的历史 哪里搬过去了。
例如:
88ea06b HEAD@{0}: checkout:从DEVELOPMENT移动到remotes/origin/SomeNiceFeature e47bf80 HEAD@{1}:拉动原点发展:快进
这个列表的顶部是一个原因,人们可能会遇到一个分离的头 状态……检查一个远程跟踪分支。
进入git分离头状态的另一种方法是尝试提交到远程分支。喜欢的东西:
git fetch
git checkout origin/foo
vi bar
git commit -a -m 'changed bar'
请注意,如果您这样做,任何进一步尝试签出origin/foo将使您回到分离的头部状态!
解决方案是创建自己的本地foo分支来跟踪origin/foo,然后可选地push。
这可能与您最初的问题无关,但该页在“git分离头”的谷歌次点击中排名靠前,这个场景的文档记录严重不足。
一个简单的偶然的方法是做一个git签出头作为head的拼写错误。
试试这个:
git init
touch Readme.md
git add Readme.md
git commit
git checkout head
这给了
Note: checking out 'head'.
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 performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b <new-branch-name>
HEAD is now at 9354043... Readme
如果您有一个与分支同名的标记,就会发生这种情况。
例如:如果“release/0.1”是标签名,那么
git checkout release/0.1
在“release/0.1”处产生分离的HEAD。如果您期望release/0.1是一个分支名称,那么您会感到困惑。
当你签出到一个commit git checkout <commit-hash>或一个远程分支时,你的HEAD将被分离,并尝试在上面创建一个新的提交。
任何分支或标记都无法访问的提交将在30天后被垃圾收集并从存储库中删除。
解决这个问题的另一种方法是为新创建的提交和签出创建一个新分支。Git checkout -b <branch-name> <commit-hash>
本文将说明如何进入分离HEAD状态。
分离HEAD意味着当前签出的不是本地分支。
导致分离HEAD状态的一些场景:
If you checkout a remote branch, say origin/master. This is a read-only branch. Thus, when creating a commit from origin/master it will be free-floating, i.e. not connected to any branch. If you checkout a specific tag or commit. When doing a new commit from here, it will again be free-floating, i.e. not connected to any branch. Note that when a branch is checked out, new commits always gets automatically placed at the tip. When you want to go back and checkout a specific commit or tag to start working from there, you could create a new branch originating from that commit and switch to it by git checkout -b new_branch_name. This will prevent the Detached HEAD state as you now have a branch checked out and not a commit.
如果git要重命名分离的HEAD,我会让它命名为一个没有被分支标识的HEAD,并且很快就会被忘记。
我们作为人可以很容易地记住分支机构的名称。我们做git checkout new-button-feature / git checkout main。主按钮和新按钮功能易于记忆。我们可以用gitbranch得到所有分支的列表。但如果只是提交,你必须做git reflog,这非常乏味。因为你有成千上万的提交,但只有很少的分支。
分离提交的标识符就是它的SHA。假设你签出了一个提交(而不是一个分支),即你签出了git d747dd10e450871928a56c9cb7c6577cf61fdf31,你会得到:
注意:检查 “d747dd10e450871928a56c9cb7c6577cf61fdf31”。 你处于“分离的头部”状态。 ...
然后,如果你做了一些更改并提交,你仍然不在分支上。
你还记得commit SHA吗?你不会!
Git不希望这种情况发生。因此,它通知您的HEAD没有关联到一个分支,因此您更倾向于签出一个新的分支。结果在该消息下面还说:
如果您想创建一个新的分支来保留您所创建的提交,您可以 可以(现在或以后)再次使用-b和签出命令。 例子: Git checkout -b
为了深入一点,分支以一种聪明的方式构建。当你提交时,它会更新它的HEAD。另一方面,标签并不是这样的。如果签出一个标签,那么你又在一个分离的HEAD上。主要的原因是,如果你从那个标签做出一个新的提交,那么这个提交没有被任何东西(不是任何分支或标签)引用,那么它仍然被认为是一个分离的HEAD。
只有当你在一个分支上时,附加的正面才会发生。
更多信息请看这里
HEAD是一个指针,它直接或间接地指向 特殊的提交: 附加HEAD意味着它附加到某个分支(即它 指向一个分支)。 分离的头意味着它没有附着在任何分支,即它 直接指向一些提交。
从另一个角度看,如果你在树枝上做cat .git/HEAD,你会得到:
ref: refs/heads/Your-current-branch-name
然后如果你使用cat refs/heads/ your -current-branch-name,那么你也会看到你的分支所指向/引用的提交的SHA。
然而,如果你在一个分离的HEAD上,你和cat .git/HEAD只会得到提交的SHA,没有别的:
639ce5dd952a645b7c3fcbe89e88e3dd081a9912
我的意思是它的头没有指向任何分支。它只是直接指向一个提交。
As a result of all this, anytime you checkout a commit (without using the branch name to checkout), even if that commit was the latest commit of your main branch, you're still in a detached HEAD because your HEAD is not pointing to any of your local branches. Hence even checking out a tag will put you in a detached HEAD. To add onto that, even checking out a remote branch that you have fetched into your computer would result in a detached head ie git checkout origin main would also end up as a detached head...
总结
以下所有情况都会导致头部脱落:
检出任何提交 签出任何标签 签出任何远程分支
如果你查过当地的分支机构,你就只在一个附属的头上
特别感谢Josh Caswell和Saagar Jha帮助我解决这个问题。
在我的案例中,情况是这样的:
创建一个新的分支(feb_debugging)。 运行git fetch 我看到新的分支(feb_debugging)被拉 现在,我使用git checkout origin/feb_debugging
在这里它让我到HEAD现在在....
我只需要再结账一次
Git签出feb_debugging 现在git说我在feb_debugging分支。
以下是VonC的评论,这是我如何解决这个“分离的头部”问题的简短版本。
在我的遥控器上创建了一个分支;来源/ dev /功能 在我的本地运行git fetch,所以现在我的本地将知道这个新的远程分支 现在运行git switch feature/dev,我们就完成了!
分离的头
HEAD是一个指向当前签出分支或提交的指针,它回答了一个问题:我现在在存储库的哪个位置?HEAD可以处于附加(默认)或分离两种状态之一,这取决于您是否签出了本地分支。
我的头是怎么脱落的?
操作比让HEAD处于分离状态
最终进入分离的HEAD状态可能是由于各种原因造成的,以下是5种常见的情况(也许你做过以下任何一种):
使用哈希表签出一个特定的提交。 $ git checkout 14ko3 显式地签出一个远程分支,即。 $ git checkout origin/master 使用分离标志切换到一个分支(Git 2.23),即 $ git主开关——分离 签出一个标签,即 $ git checkout v1.0.1 执行一个交互式的重基(或者包含冲突变更的常规重基),例如: $ git rebase master特性-1 -交互式
在分离状态下,可以在不影响任何现有分支的情况下进行实验更改。请参见下面的信息图,说明在附加状态和分离状态下提交的区别。
一个常见的误解是,消息You are in 'detached HEAD' state是错误的语气,而实际上它只是描述HEAD是如何引用当前快照的。
从分离到依附的状态
要从分离状态切换到附加状态,您可以从所在的位置创建一个新分支,或者切换回现有的分支。
注意:如果你切换到另一个现有的分支,在分离状态下创建的任何提交最终(垃圾收集后)都会被丢弃,而不是首先在一个新的分支中持久化你的更改。
来源:以上节选自这篇关于主题的完整文章:Git中的HEAD是什么?
对于其他人可能正在寻找一种获得分支名称的方法,但却得到了HEAD,这是我想出的:
const { execSync } = require('child_process');
const getBranchName = () => {
let branch = execSync('git rev-parse --abbrev-ref HEAD').toString().trim();
if (branch === 'HEAD') branch = execSync(`git branch -a --contains HEAD | sed -n 2p | awk '{ printf $1 }'`).toString().trim();
return branch;
}