我正在我的存储库中做一些工作,并注意到一个文件有本地更改。我不再想要它们,所以我删除了文件,以为我可以签出一个新副本。我想做的 Git 相当于
svn up .
使用git pull
似乎不起作用。一些随机搜索把我带到了一个有人推荐做的网站
git checkout HEAD^ src/
(src
是包含已删除文件的目录)。
现在我发现我有一个分离的头。我不知道那是什么。我该如何撤消?
我正在我的存储库中做一些工作,并注意到一个文件有本地更改。我不再想要它们,所以我删除了文件,以为我可以签出一个新副本。我想做的 Git 相当于
svn up .
使用git pull
似乎不起作用。一些随机搜索把我带到了一个有人推荐做的网站
git checkout HEAD^ src/
(src
是包含已删除文件的目录)。
现在我发现我有一个分离的头。我不知道那是什么。我该如何撤消?
分离的头意味着你不再在一个分支上,你已经签出了历史中的一个提交(在这种情况下是 HEAD 之前的提交,即 HEAD^)。
您只需要检查您所在的分支,例如
git checkout master
下次你更改了一个文件并想将它恢复到它在索引中的状态时,不要先删除文件,只需执行
git checkout -- path/to/foo
这会将文件 foo 恢复到它在索引中的状态。
git branch tmp
- 这会将您的更改保存在一个名为tmp
.git checkout master
master
运行。运行后你应该在分支上。git merge tmp
master
master
git checkout master
如果您更改了不想丢失的文件,可以推送它们。我已经在分离模式下提交了它们,之后你可以移动到一个临时分支以便稍后在 master 中集成。
git commit -m "....."
git branch my-temporary-work
git checkout master
git merge my-temporary-work
摘自:
无需创建临时分支的解决方案。
当您已经在此模式下更改了某些内容并且(可选)想要保存更改时,如何退出(“修复”)分离的 HEAD 状态:
提交您想要保留的更改。如果您想接管您在分离 HEAD 状态下所做的任何更改,请提交它们。像:
git commit -a -m "your commit message"
放弃不想保留的更改。硬重置将丢弃您在分离 HEAD 状态下所做的任何未提交的更改:
git reset --hard
(没有这个,第 3 步将失败,抱怨在分离的 HEAD 中修改了未提交的文件。)
检查你的分支。通过检查您之前处理的分支来退出分离的 HEAD 状态,例如:
git checkout master
接管你的提交。您现在可以通过挑选来接管您在分离 HEAD 状态下所做的提交,如我对另一个问题的回答中所示。
git reflog
git cherry-pick <hash1> <hash2> <hash3> …
分离头的意思:
如果您没有更改:您可以通过应用以下命令切换到 master
git checkout master
如果您有想要保留的更改:
在分离 HEAD 的情况下,提交工作正常,除了没有命名分支被更新。要使用您提交的更改更新主分支,请在您所在的位置创建一个临时分支(这样临时分支将拥有您在分离的 HEAD 中所做的所有提交更改),然后切换到主分支并将临时分支与大师。
git branch temp
git checkout master
git merge temp
HEAD 是一个指针,它直接或间接地指向一个特定的提交:
附加 HEAD 表示它附加到某个分支(即它指向一个分支)。
分离的 HEAD 意味着它没有附加到任何分支,即它直接指向某个提交。
换句话说:
为了更好地理解附加/分离 HEAD 的情况,让我们展示导致上面四组图片的步骤。
我们从存储库的相同状态开始(所有象限中的图片都相同):
现在我们要执行git checkout
- 在各个图片中使用不同的目标(它们顶部的命令变暗以强调我们只会应用这些命令):
这是执行这些命令后的情况:
如您所见,HEAD 指向命令的目标——git checkout
一个分支(四联体的前 3 个图像),或(直接)指向一个提交(四联体的最后一个图像)。
工作目录的内容也被更改,以符合适当的提交(快照),即与 HEAD (直接或间接)指向的提交一致。
所以现在我们处于与此答案开头相同的情况:
如果您进行了更改,然后意识到您处于超然状态,您可以执行以下操作:stash -> checkout master -> stash pop:
git stash
git checkout master # Fix the detached head state
git stash pop # Or for extra safety use 'stash apply' then later
# after fixing everything do 'stash drop'
您将拥有未提交的更改和正常的“附加” HEAD,就像什么都没发生一样。
这是我在意识到自己处于超然状态并且已经做出一些改变之后所做的事情。
我提交了更改。
$ git commit -m "..."
[detached HEAD 1fe56ad] ...
我记得提交的哈希(1fe56ad)。然后我检查了我应该在的分支。
$ git checkout master
Switched to branch 'master'
最后,我将提交的更改应用于分支。
$ git cherry-pick 1fe56ad
[master 0b05f1e] ...
我认为这比创建临时分支要容易一些。
当您签出 中的特定提交时git
,您最终会处于分离的头部状态......也就是说,您的工作副本不再反映命名引用的状态(如“master”)。这对于检查存储库的过去状态很有用,但如果您实际上尝试还原更改,则不是您想要的。
如果您对特定文件进行了更改并且只想丢弃它们,则可以使用如下checkout
命令:
git checkout myfile
这将丢弃任何未提交的更改并将文件恢复到它在当前分支头部的任何状态。如果您想放弃已经提交的更改,您可能需要使用该reset
命令。例如,这会将存储库重置为先前提交的状态,丢弃任何后续更改:
git reset --hard HEAD^
但是,如果您与其他人共享存储库,则 agit reset
可能会造成破坏(因为它会删除存储库历史的一部分)。如果您已经与其他人共享了更改,您通常希望查看git revert
它,它会生成一个“反提交”——也就是说,它会创建一个“撤消”相关更改的新提交。
Git Book有更多细节。
由于“分离头状态”使您处于临时分支上,因此只需使用git checkout -
它将您置于您所在的最后一个分支上。
你可能做到了git reset --hard origin/your-branch
。
试着只是git checkout your-branch
处于“分离头”意味着 HEAD 指的是特定的未命名提交(与命名分支相反)(参见:https ://git-scm.com/docs/git-checkout部分分离头)。实际上,这意味着您已经签出了一个提交,但没有与之关联的分支名称。
您可以选择仅通过以下方式创建与您的提交相关联的新分支
git branch new-branch-name
.
这使您可以将当前状态保存在名为的新分支new-branch-name
中,而不再处于某个detached head
状态。
或者如果你想回到之前的状态,你需要选择之前被选中的分支
git checkout @{-1}
附录
如果您希望返回的分支是您最后一次结帐,您可以简单地使用checkout @{-1}
. 这将带您回到之前的结帐。
此外,您可以为该命令设置别名,例如,git global --config alias.prev
您只需键入git prev
即可切换回上一个结帐。
分离的头意味着您没有正确签出您的分支,或者您刚刚签出了一个提交。
如果您遇到这样的问题,那么首先存储您的本地更改,这样您就不会丢失您的更改。
之后...使用以下命令检查您想要的分支:
假设您想要分支 MyOriginalBranch:
git checkout -b someName origin/MyOriginalBranch
这种方法可能会丢弃部分提交历史,但如果旧主分支和当前状态的合并很棘手,或者您只是不介意丢失部分提交历史,则更容易。
为了简单地保持当前状态而不合并,将当前分离的 HEAD 转换为 master 分支:
detached-head
),其中将包含处于当前状态的文件:git checkout -b detached-head
git branch -D master
git branch -M master old-master
git branch -M detached-head master
来源:改编自Gary Lai 的这篇 Medium 文章。
Git告诉我怎么做。
如果您输入:
git checkout <some-commit_number>
保存状态
git add .
git commit -m "some message"
然后:
git push origin HEAD:<name-of-remote-branch>
通常HEAD
指向一个分支。当它不指向分支时,而是指向提交哈希时,69e51
这意味着您有一个分离的 HEAD。您需要将它指向两个分支来解决问题。你可以做两件事来修复它。
hash
HEAD 必须指向一个分支,而不是提交哈希是黄金法则。
我想保留我的更改,所以我只是解决这个问题......
git add .
git commit -m "Title" -m "Description"
(so i have a commit now example: 123abc)
git checkout YOURCURRENTBRANCH
git merge 123abc
git push TOYOURCURRENTBRANCH
那对我有用
当您处于分离头情况并创建新文件时,首先确保将这些新文件添加到索引中,例如:
git add .
但是,如果您只更改或删除了现有文件,则可以通过以下方式同时添加 (-a) 并使用消息 (-m) 提交:
git commit -a -m "my adjustment message"
然后,您可以使用当前状态简单地创建一个新分支:
git checkout -b new_branch_name
您将拥有一个新分支,并且您的所有调整都将在该新分支中进行。然后,您可以根据需要继续推送到远程和/或结帐/拉取/合并。
merge
意识到我有一个超然的头脑而不知道我是如何设法得到它的(比如三个提交) ,我还发现尝试rebase
或cherry-pick
触发了数百个合并冲突,所以我采取了不同的方法:
(假设一切都已提交(工作树是“干净的”))
保存我的提交信息:git log > /tmp/log
保存我的工作树:mkdir /tmp/backup && cp -a all_my files_and_directories /tmp/backup
恢复为master
:git checkout master
删除所有工作文件和目录:rm ...
使用备份:cp -a /tmp/backup/. .
git add
并git commit
使用来自 saved 的消息/tmp/log
,也许用不同的文件子集重复它......
缺点是如果一个文件被多次更改,你会丢失你的提交历史master
,但最后我有一个干净的master
.
我也有类似的情况。
出于某种原因,我最终得到了一个分离的头——我已经在与我认为我所在的分支相同的路径上进行了提交——例如,HEAD 是分支标签的子标签,但由于某种原因,分支标签一直停留在历史上提交...可能是因为我推了??
它不会让我推动,因为我不被认为在我认为我所在的分支上。
我不想改变我的任何历史或做任何樱桃采摘,我刚刚在分支上工作了大约 8 周,所以reset --hard
让我有点紧张!
解决方案只是执行以下操作:
git branch -f myStuckBranch HEAD
git checkout myStuckBranch
即使 HEAD 和 myStuckBranch 现在指向同一事物,您也需要进行结帐,因为您仍然被认为处于分离的头部状态(而不是在分支上)
我不是 git 专家(主要使用 mercurial,它永远不会造成这种奇怪的情况),但我对这个命令的理解是它只是说“将 myStuckBranch 更改为指向 HEAD”。
我经常发现自己使用此命令在获取后合并来自 master 的更改,而无需交换我的工作目录 - 否则它会尝试使用旧(无趣)版本的 master:
git fetch
git branch -f master origin/master -- err yeah don't just ignore what's been going on remotely - eg point my master at the real master
git merge master -- merge the changes into my local branch
不得不一直手动执行此操作有点烦人,但仍然比更改工作目录只是为了更新另一个分支以合并其中的更改要好。
git pull origin master
为我工作。这只是明确给出远程和分支名称。
这对我有用,它将为分离头分配一个新分支:
git checkout new_branch_name detached_head_garbage_name
分离的 HEAD 表示您当前不在任何分支上。如果您想保留当前更改并简单地创建一个新分支,您可以这样做:
git commit -m "your commit message"
git checkout -b new_branch
之后,您可能希望将此新分支与其他分支合并。总是有用的是 git "a dog"命令:
git log --all --decorate --oneline --graph
使用git rebase您可以将 HEAD 移动到所需的提交
假设您的分支处于分离状态,如下所示:
* bfcb8f9 Commit 4
* 540a123 Commit 3
* 4356d64 Commit 2
| * fecb8d2 Commit 2
|/
| * 8012f45 Commit 2x
|/
| * 6676d15 (HEAD -> master) Commit 2 --amend
|/
* 1818f91 Commit 1
分离的头部是通过错误地变基创建的,指向一个分离的提交,该提交是先前由于git commit --amend命令而创建的。
如果您想将 HEAD 引用移动到最近的提交,请使用您想要指向的所需 HASH 提交应用 rebase。在此示例中,哈希是最近提交的:
git rebase bfcb8f9
这将使您的分支的 HEAD 指向所需的提交(在这种情况下是最新的):
* bfcb8f9 (HEAD -> master) Commit 4
* 540a123 Commit 3
* 4356d64 Commit 2 --amend
| * fecb8d2 Commit 2
|/
| * 8012f45 Commit 2x
|/
| * 6676d15 Commit 2
|/
* 1818f91 Commit 1
添加到@ralphtheninja 的答案。如果您在使用后收到此消息git checkout master
:
请在切换分支之前提交您的更改或存储它们。中止
然后,您可以简单地使用 -f 标志强制结帐,如下所示:
git checkout -f master
显然,这将导致丢失在分离模式下所做的所有更改。所以使用的时候要小心。