我在分支机构工作,需要撤消一些提交.所以我做了
$> git reset --hard bd53134
Run Code Online (Sandbox Code Playgroud)
这有所期望的效果,除了我现在有一个独立的头:(
$> git status
HEAD detached at bd53134
Run Code Online (Sandbox Code Playgroud)
我怎样才能解决这个问题 ?
tor*_*rek 10
看起来你可能仍在四处寻找,所以这里有一些背景知识.你在评论中提到你开始了git rebase并且git rebase --continue总是在抱怨.(这确实应该是原始问题的一部分.)
首先注意:HEAD可以是正常的("未分离"?)或"分离"."正常"只HEAD包含分支名称.如果你是"在分支机构master",HEAD只需说"分支机构主".一个"分离的HEAD",听起来像法国大革命中的东西,而不是原始的SHA-1提交ID.我喜欢在下面的图中编写附加的HEAD,HEAD=branch然后显示分支指向的位置,使用箭头指向一个特定的提交.
在开始一个rebase之前,你有一个提交图,看起来像这样:
...- A - B - E - F <-- master, origin/master
\
C - D <-- HEAD=branch
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我假设你做了一个git checkout -b branchfrom master,并做了一些提交branch(创建C和D),然后可能做了一个git checkout master,git pull它带来了提交E和F"远程origin".然后你回去branch了git checkout branch(因此HEAD=branch).
然后,您决定应该重新设置两者C并D在其之上F,提供更线性的提交序列:
...- A - B - E - F <-- master, origin/master
\
C' - D' <-- HEAD=branch
Run Code Online (Sandbox Code Playgroud)
(我将在片刻展示为什么那些是C',D'而不是C和D.)所以你跑去git rebase master"移动"提交C并D进入尖端master.
Rebase实际上并没有移动提交.它的作用是复制一些现有的提交,使新的"做同样的事情"并且"同样好"(我们希望!).因此,rebase保持C和D周围.它使用一个特殊的标签ORIG_HEAD来跟踪提交D(以及一堆额外的.git/rebase-apply/文件来跟踪整个rebase操作的所有进度 - 这些文件实际上是git知道rebase是"正在进行中").
Rebase通过添加ORIG_HEAD和"分离HEAD"来启动该过程.它将"分离的HEAD"设置为直接指向rebase的目标(F在本例中为commit ).(通过探讨,似乎文档略微关于它重置分支.但是在旧版本的git中可能会有所不同;我认为文档在某一点上是准确的.)因此:
...- A - B - E - F <-- master, origin/master
\ \
\ \...... HEAD [detached]
\
C - D <-- ORIG_HEAD, branch
Run Code Online (Sandbox Code Playgroud)
然后,对于每个提交(C和D此处),它获取提交中所做的更改,并尝试将相同的更改应用于HEAD提交.如果一切顺利 - 它通常会 - 它使用与旧提交相同的消息进行新提交.这是承诺C':
...- A - B - E - F <-- master, origin/master
\ \
\ C'..... HEAD [detached]
\
C - D <-- ORIG_HEAD, branch
Run Code Online (Sandbox Code Playgroud)
申请成功后C,以F使C'脱落F,底垫命令继续尝试应用D到新的(但仍然分离的)HEAD,C'.但是,这次出现问题:补丁不适用:
CONFLICT ...
Failed to merge in the changes.
Patch failed at ...
The copy of the patch that failed is found in:
...
When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".
Run Code Online (Sandbox Code Playgroud)
此时,您的提交图看起来像我上面绘制的(有点混乱)图.
作为rebase打印,您可以:
git rebase --continue,或D在这种情况下)与git rebase --skip,或git rebase --abort.选择最后一个选项告诉rebase停止rebase尝试,放回HEAD原来的样子,并删除"rebase in progress"状态/跟踪文件.这也会丢弃整个新的链(但尚未标记为分支)提交.(从技术上讲,他们仍然在那里,在reflog中.你通常不会看到它们.)
执行第一个("手动解析")或选择中间("跳过")选项,让rebase继续向前.假设你解决问题了git rebase --continue.一旦rebase用完提交 - 并且D是最后一个 - 它将分支名称移动到最终提交,并HEAD再次设置为分支名称.所以在这种情况下,你得到这个:
...- A - B - E - F <-- master, origin/master
\ \
\ C' - D' <-- HEAD=branch
\
C - D <-- ORIG_HEAD
Run Code Online (Sandbox Code Playgroud)
由于犯下指出,由ORIG_HEAD不正常显示,它看起来像C和D都消失了,和副本(C'和D')是唯一的提交离开.(一如往常虽然,C和D实际上仍然在那里,并坚持了一段时间,直到引用日志条目到期.)
考虑到所有这些,一旦你处于"超级HEAD"状态,git reset --hard就没有分支名称可以影响.它将移动HEAD并更改工作目录,但HEAD仍将直接指向提交.所以git reset你在一个篮子中间做的任何事情,最好是奇怪的.(如果你继续下去的话,他们会弄清楚rebase会发生什么,因为继续一个rebase只是不断增加到HEAD当时的任何一点.)
在更正常的情况下(当你在"分支上"时),HEAD具有分支的名称.然后(并且只有那时),git reset可以并且确实更改了branch-name指向的提交.
你怎么知道git reset将采取哪些行动,以及发生了什么?答案是使用git status.如果你不确定发生了什么,那git status就是有帮助的.在过去的几年里,它实际上也在帮助它变得更好!:-)
小智 7
如果你在一个分支上,git reset --hard bd53134应该更新分支,并让你离开那个分支.因此,我怀疑你实际上并不在分支机构.
如果这是正确的,通过回到分支来解决它的一种方法:
git checkout <branch>
Run Code Online (Sandbox Code Playgroud)
然后git reset再次运行您已经使用过的相同命令.
| 归档时间: |
|
| 查看次数: |
3920 次 |
| 最近记录: |