我怎样才能调和分离的HEAD与主/来源?
我是Git的分支复杂性的新手。 我总是在单个分支上工作并提交更改,然后定期推送到我的远程原点。
最近,我做了一些文件的重置,使它们脱离了提交阶段,后来又做了一个rebase -i
来摆脱最近的一些本地提交。 现在我处于一个我不太明白的状态。
在我的工作区域, git log
显示了我所期望的 – 我在正确的列车上提交了我不想去的地方,还有新的地方等等。
但是我只是推到了远程仓库,有什么不同 – 我在rebase中杀死的一些提交被推送了,而在本地提交的新提交不在那里。
我认为“master / origin”是从HEAD中分离出来的,但是我并不十分清楚这是什么意思,怎么用命令行工具来显示它,以及如何解决它。
首先,让我们澄清一下HEAD是什么以及它是什么意思。
HEAD是当前签出的提交的符号名称。 当HEAD没有分离(“正常” 1的情况:你有一个分支签出)时,HEAD实际上指向分支的“ref”,分支指向提交。 HEAD因此“附属于”一个分支。 当您进行新的提交时,HEAD指向的分支会更新为指向新的提交。 HEAD自动跟随,因为它只是指向分支。
-
git symbolic-ref HEAD
产生refs/heads/master
名为“主”的分支被检出。 -
git rev-parse refs/heads/master
yield17a02998078923f2d62811326d130de991d1a95a
该提交是主分支的当前提示或“头”。 -
git rev-parse HEAD
也产生17a02998078923f2d62811326d130de991d1a95a
这就是“符号参考”。 它通过一些其他的参考指向一个对象。
(符号参考最初是以符号链接的forms实现的,但后来更改为带有额外解释的普通文件,以便可以在没有符号链接的平台上使用它们。)
我们有HEAD
→ refs/heads/master
→ 17a02998078923f2d62811326d130de991d1a95a
当HEAD被分离时,它直接指向一个提交 – 而不是通过一个分支间接地指向一个提交。 你可以把分离的HEAD想象成一个未命名的分支。
-
git symbolic-ref HEAD
失败fatal: ref HEAD is not a symbolic ref
-
git rev-parse HEAD
得出17a02998078923f2d62811326d130de991d1a95a
由于它不是一个符号参考,它必须直接指向提交本身。
我们有HEAD
→ 17a02998078923f2d62811326d130de991d1a95a
用分离的HEAD来记住的重要的事情是,如果它指向的提交不被引用(其他引用无法达到它),那么当你签出其他提交时,它将变成“悬挂”。 最终,这种悬而未决的提交将通过垃圾收集过程被修剪(默认情况下,它们被保留至less2周,并且可以通过被HEAD的reflog引用而保持更长的时间)。
1用一个独立的HEAD进行“正常”的工作是完全正确的,你只需要跟踪你正在做的事情,以避免把丢失的历史logging排除在reflog之外。
交互式重新分配的中间步骤是用分离的HEAD完成的(部分是为了避免污染活动分支的reflog)。 如果您完成了全部的rebase操作,它将更新您的原始分支与rebase操作的累积结果,并将HEAD重新附加到原始分支。 我的猜测是,你从来没有完全完成rebase进程; 这会让你有一个分离的HEAD指向最近由rebase操作处理的提交。
为了从你的情况中恢复,你应该创build一个分支,指向你分离的HEAD当前指向的提交:
git branch temp git checkout temp
(这两个命令可以缩写为git checkout -b temp
)
这将重新连接你的HEAD到新的temp
分支。
接下来,您应该将当前提交(及其历史logging)与您希望在其中工作的常规分支进行比较:
git log --graph --decorate --pretty=oneline --abbrev-commit master origin/master temp git diff master temp git diff origin/master temp
(你可能想要试验一下日志选项:add -p
,leave off --pretty=…
来查看整个日志信息等)
如果你的新temp
分支看起来不错,你可能想更新(例如) master
指向它:
git branch -f master temp git checkout master
(这两个命令可以简写为git checkout -B master temp
)
您可以删除临时分支:
git branch -d temp
最后,你可能会想推动重build的历史:
git push origin master
如果远程分支不能被快速转发到新的提交中,你可能需要在这个命令的最后添加--force
(即,你删除了,或者重写了一些现有的提交,或者重写了一些历史logging)。
如果您正在进行重新布局操作,您应该清理它。 您可以通过查找目录.git/rebase-merge/
来检查是否正在进行重新.git/rebase-merge/
。 您可以通过删除该目录(例如,如果您不再记住活动的rebase操作的目的和上下文)来手动清理正在进行的rebase。 通常你会使用git rebase --abort
,但是会做一些你可能想要避免的额外的重置操作(它会把HEAD移回到原来的分支,并将其重置回原来的提交,这将撤销我们上面做的一些工作)。
只要这样做:
git checkout master
或者,如果您有想要保留的更改,请执行以下操作:
git checkout -b temp git checkout -B master temp
我遇到了这个问题,当我读到顶级投票答案:
HEAD是当前签出的提交的符号名称。
我想:啊哈! 如果HEAD
是currenlty签出提交的象征性名称,我可以通过将其与master
重新绑定来与master
进行协调:
git rebase HEAD master
这个命令:
- 检查出
master
- 将
HEAD
的父提交标识回到从master
发出的头HEAD
- 在
master
之上播放这些提交
最终的结果是,所有在HEAD
但不是master
提交也在master
。 master
仍然签出。
关于偏远:
我在基地被杀的几个提交被推了,在当地犯下的新提交不在那里。
远程历史logging不能再使用本地历史logging进行快速转发。 你需要强制推( git push -f
)覆盖远程历史。 如果你有任何合作者,通常有必要与他们协调,所以每个人都在同一页面上。
将master
推送到远程origin
,远程跟踪分支origin/master
将更新为指向与master
相同的提交。
在这里寻找分离头的基本解释:
http://git-scm.com/docs/git-checkout
命令行可视化:
git branch
要么
git branch -a
你会得到如下输出:
* (no branch) master branch1
* (no branch)
显示你在分离的头部。
你可以通过做一个git checkout somecommit
等来达到这个状态,它会提醒你以下几点:
你处于“脱离头”状态。 您可以环顾四周,进行实验性更改并提交它们,并且可以放弃您在此状态下进行的任何提交,而不会通过执行另一个结算来影响任何分支。
如果您想要创build一个新的分支来保留您创build的提交,可以通过再次使用-b和checkout命令(现在或以后)来执行此操作。 例:
git checkout -b new_branch_name
现在,让他们到主人:
做一个git reflog
甚至只是git log
并记下你的提交。 现在, git checkout master
和git merge
提交。
git merge HEAD@{1}
编辑:
要添加,使用git rebase -i
不仅用于删除/终止您不需要的提交,还可以编辑它们。 只要在提交列表中提到“编辑”,你将能够修改你的提交,然后发出git rebase --continue
– 继续前进。 这将确保你从来没有进入一个独立的头。
让你的分离提交到自己的分支
只需运行git checkout -b mynewbranch
。
然后运行git log
,你会在这个新的分支上看到提交现在是HEAD
。
如果你只是掌握了分支,想回到“开发”或者一个function,只需要这样做:
git checkout origin/develop
注意:检查出处/发展 。
您处于分离的HEAD状态。 你可以环顾四周,做实验性的修改并提交它们,你可以放弃你在这个状态下进行的任何提交,而不会影响任何分支机构,通过执行另一个结帐…
然后
git checkout -b develop
有用 :)
如果你想推送你当前分离的HEAD(检查之前的git log
),请尝试:
git push origin HEAD:master
将你分离的HEAD发送到原始分支。 如果您的推送被拒绝,请先尝试git pull origin master
以从原点获取更改。 如果你不关心来自原产地的变化,它被拒绝了,因为你做了一些有意的变更,而你想用当前分离的分支replaceorigin / master,那么你可以强制它( -f
)。 如果你失去了一些访问以前的提交,你总是可以运行git reflog
查看所有分支的历史。
要回到主分支,在保持更改的同时,请尝试以下命令:
git rebase HEAD master git checkout master
请参阅: Git:“目前没有任何分支”。 有没有一种简单的方法来恢复分支,同时保持更改?
如果你完全确定HEAD是一个好的状态:
git branch -f master HEAD git checkout master
因为你的主人已经偏离了原点,你可能无法推到原点。 如果您确定没有其他人使用回购,您可以强制推送:
git push -f
如果您在function分支上没有其他人正在使用,那么这将非常有用。
你所要做的就是'git checkout [branch-name]',其中[branch-name]是你进入分离头部状态的原始分支的名字。 (从asdfasdf分离)将消失。
所以例如,在分支'dev'中签出提交asdfasd14314 – >
'git checkout asdfasd14314'
你现在处于独立的头部状态
“git分支”将列出类似于 – >的内容
* (detached from asdfasdf) dev prod stage
但要离开头部状态并回到开发 – >
'git checkout dev'
然后'git分支'将列出 – >
* dev prod stage
但是这当然是,如果你不打算保持从分离头部状态的任何变化,但我发现自己做了很多不打算做任何改变,只是看看以前的提交
我今天刚刚遇到这个问题。 很确定我通过这样做来解决它:
git branch temp git checkout master git merge temp
当我想到如何做到这一点的时候,我正在我的工作电脑上,现在我正在遇到同样的问题。 所以当我回到工作岗位时,必须等到星期一才看到我是如何做到的。
而不是做git checkout origin/master
只要做git checkout master
那么git branch
会确认你的分支。
对我来说,就像删除本地分支一样简单,因为我没有任何我想要推动的本地提交:
所以我做了:git branch -d branchname
然后再检查分支
git checkout branchname
简单的说,Detached HEAD状态意味着你没有签出任何分支的头(或者提示) 。
以例子来理解
大多数情况下的分支是多个提交的序列,如:
提交1: master – > branch_HEAD(123be6a76168aca712aea16076e971c23835f8ca)
提交2: master – > 123be6a76168aca712aea16076e971c23835f8ca – > branch_HEAD(100644a76168aca712aea16076e971c23835f8ca)
正如你可以在上面看到的情况下提交你的分支指向你最近的提交。 所以在这种情况下,如果你签出提交123be6a76168aca712aea16076e971c23835f8ca那么你将处于分离头状态,因为你的分支的HEAD指向100644a76168aca712aea16076e971c23835f8ca,并且在技术上你在没有分支的HEAD处检出。因此,你处于分离的HEAD状态
理论解释
在这个博客中,明确指出的Git仓库是一个提交树,每个提交指向它的祖先,每个提交指针被更新,并且这些指向每个分支的指针被存储在.git / refs子目录中。 标签存储在.git / refs /标签中,分支存储在.git / refs /头中。 如果您查看任何文件,您会发现每个标记对应于一个文件,具有40个字符的提交哈希值,正如上面@Chris Johnsen和@Yaroslav Nikitenko所解释的那样,您可以查看这些参考文献
如果你在master的顶部做了一些提交,并且只想在那里“向后合并” master
(即你想让master
指向HEAD
),那么单行就是:
git checkout -B master HEAD
- 这创build了一个名为
master
的新分支,即使它已经存在(这就像移动master
,这就是我们想要的)。 - 新创build的分支被设置为指向
HEAD
,这是你的位置。 - 新的分支被检出,所以你在之后的
master
。
我发现这在子存储库的情况下特别有用,而这些子存储库也经常处于分离状态。
我进入了一个非常愚蠢的状态,我怀疑其他人会发现这个有用的….但以防万一
git ls-remote origin 0d2ab882d0dd5a6db93d7ed77a5a0d7b258a5e1b HEAD 6f96ad0f97ee832ee16007d865aac9af847c1ef6 refs/heads/HEAD 0d2ab882d0dd5a6db93d7ed77a5a0d7b258a5e1b refs/heads/master
我最终解决了这个问题
git push origin :HEAD
在我的情况下,我运行git status
,我看到我的工作目录上有几个未跟踪的文件。
为了使重build工作,我只需要清理它们(因为我不需要它们)。
如果你在eclipse中使用egit:假设你的主人是你的主要开发分支
- 将更改提交给通常是新的分支
- 然后从遥控器拉
- 然后右键单击项目节点,select团队,然后select显示历史logging
- 然后右键点击主,select退房
- 如果日食告诉你,有两个主人一个本地一个远程,select远程
在此之后,您应该能够重新连接到原始主人
这完美地为我工作:
1. git stash
保存您的本地修改
如果你想放弃更改
git clean -df
git checkout -- .
git clean删除所有未跟踪的文件(警告:虽然它不会删除直接在.gitignore中提到的被忽略的文件,它可能会删除文件夹中被忽略的文件),git checkout将清除所有未经处理的更改。
2. git checkout master
切换到主分支(假设你想用master)
3. git pull
从主分支拉最后一个提交
4. git status
为了检查一切看起来不错
On branch master Your branch is up-to-date with 'origin/master'.
正如Chris所指出的那样,我有如下的情况
git symbolic-ref HEAD
失败fatal: ref HEAD is not a symbolic ref
然而, git rev-parse refs/heads/master
指向我可以恢复的一个很好的提交(在我的情况下,最后一次提交,你可以看到使用git show [SHA]
之后我做了很多乱七八糟的事情,但似乎已经修好了,
git symbolic-ref HEAD refs/heads/master
头重新连接!
当我个人发现自己处于一种情况,当我不在master
时候,我做了一些改变(也就是说, HEAD
在master
之上,而且没有提交之间的任何提交),可能会有帮助:
git stash # HEAD has same content as master, but we are still not in master git checkout master # switch to master, okay because no changes and master git stash apply # apply changes we had between HEAD and master in the first place
git checkout checksum #you could use this to peek previous checkpoints git status # you will see HEAD detached at checksum git checkout master #this moves HEAD to master branch