Git 如何删除当前标头之后的提交?

Git 如何删除当前标头之后的提交?,git,git-commit,Git,Git Commit,在我的Git存储库中,我一行创建了三个提交:commit1、commit2和commit3 然后我意识到我在commit2和commit3中搞砸了,决定回到commit1。为了做到这一点,我跑了 git checkout commit1 现在我在commit1。如何删除commit2和commit3?您想取消commitcommit3(假设您当前在commit3上-作为头)。您可以执行以下操作: git reset --hard HEAD~1 结果是: commit1 -> commi

在我的Git存储库中,我一行创建了三个提交:
commit1
commit2
commit3

然后我意识到我在
commit2
commit3
中搞砸了,决定回到
commit1
。为了做到这一点,我跑了

git checkout commit1

现在我在
commit1
。如何删除
commit2
commit3

您想取消commit
commit3
(假设您当前在commit3上-作为
)。您可以执行以下操作:

git reset --hard HEAD~1
结果是:

commit1 -> commit2 
              ↑
             HEAD
您可以按照类似的过程返回到
commit1
(即
git reset--hard HEAD~2
)。

检查分支,然后重置它 根据您的描述,并假设您在签出
commit1
之前在名为
mybranch
的分支机构工作(
C1
,在下面的图表中),您必须处于以下情况:

C1 [HEAD]
 \
  C2 -- C3 [mybranch]
C1
 \
  C2 -- C3 [HEAD -> mybranch]
C1 [HEAD -> mybranch]
提交
C2
C3
仍然出现在
git log
的输出中,因为它们仍然可以从
mybranch
引用访问。另外,请注意,
头部
已分离。你应该做的是

  • 通过运行将
    HEAD
    重新连接到
    mybranch

    git签出mybranch
    
    这将使您处于以下情况:

    C1 [HEAD]
     \
      C2 -- C3 [mybranch]
    
    C1
     \
      C2 -- C3 [HEAD -> mybranch]
    
    C1 [HEAD -> mybranch]
    
  • 通过运行将
    mybranch
    分支重置为其tip的祖辈

    git重置——硬mybranch~2
    
    这将使您处于以下情况:

    C1 [HEAD]
     \
      C2 -- C3 [mybranch]
    
    C1
     \
      C2 -- C3 [HEAD -> mybranch]
    
    C1 [HEAD -> mybranch]
    
  • 因为提交
    C2
    C3
    现在变得不可访问(即“已删除”),所以在最后一个图表中没有显示它们


    为什么不先重新连接头部就复位不起作用 这可能有点厚颜无耻,但下面解释一下为什么其他两个答案不起作用。正如cmbuckley在中正确指出的那样


    git reset
    重置您当前所在分支的状态(因此您需要在分支上执行此操作)。如果您签出了
    commit1
    ,则可能不在分支上(分离头状态)

    由于OP(Imray)处于分离头部状态,因此在将头部重新连接到分支之前运行git reset不会移动有问题的分支引用。下面是一个玩具的例子来说明这一点

    #把事情安排好
    $mkdir测试
    $cd测试
    $git init
    已在/Users/jubobs/Desktop/test/.Git中初始化空Git存储库/
    #创建第一次提交
    $touch自述文件
    $git add。
    $git commit-m“添加自述”
    [master(root提交)85137ba]添加自述
    1个文件已更改,0个插入(+),0个删除(-)
    创建模式100644自述文件
    #创建第二个提交
    $printf“foo\n”>自述
    $git commit-am“在自述文件中写入'foo'”
    [master 3948e84]在自述文件中写“foo”
    1个文件已更改,1个插入(+)
    #检查日志
    $git log--图形--装饰--单线--全部
    *3948e84(头,主)在自述中写“foo”
    *85137ba添加自述
    #查看第二个提交(它分离头部)
    $git结帐3948e84
    注意:正在签出“3948e84”。
    #(样板标准省略了…)
    头现在在3948e84。。。在自述中写“foo”
    #重置为第一次提交(相当于“git重置--hard 85137ba”)
    $git重置--硬头^
    HEAD现在位于85137ba添加自述
    $git log--图形--装饰--单线--全部
    *3948e84(主)在自述文件中编写“foo”
    *85137ba(标题)添加自述
    

    请注意,
    git reset
    命令将
    HEAD
    移动到初始提交,但没有移动
    master
    分支。第二次提交没有被“删除”,因为它仍然可以从
    主控
    访问;因此,出于命名目的,我假设您在回购协议的主分支中,但任何分支都可以。这可以简单地看作是指向提交对象的指针。您还可以将HEAD视为另一个指针,您可以使用
    git checkout

    commit1  ->  commit2  ->  commit3
                                 ^
                                 |
                               master
    
    如果要将主指针更改为commit1,则需要发出
    git reset
    命令,其他人已经指出了这一点

    git reset --hard commit1
    
    这会将上图中的主指针移动到与commit1对象相同的位置

    注意,您实际上并没有删除commit2和commit3对象,只是在git中没有指向它们的分支,所以git可以自由地清理它们,或者您可以通过运行垃圾收集来强制它,比如:

    git gc --aggressive --prune
    
    在从回购协议中主动清除之前,您仍然可以签出commit2和commit3,因此尽管您将主指针移回commit1(使用
    git reset
    ),但如果您意外地将密码提交到存储库并试图恢复-在删除之前,密码仍将在本地回购中。

    强制您的分支到当前HEAD和Checkout分支 签出分支并强制分支到当前头 第二个选项特别有利,因为您不需要键入branh的名称或当前提交的标识。你甚至可以把它变成别名


    编辑:这假设您没有跳转,最近的签出是从您的分支进行的。

    注意,在执行
    签出commit1
    (其中
    commit1
    是提交ID、远程分支或标记)后,您位于分离的头上(=不在分支上)。然后,您必须签出您的分支,并按照注释和答案中描述的
    重置
    步骤进行操作。我不在
    主分支
    上,我在不同的分支我不在
    主分支
    上,而是在
    我的第一分支
    上,这有什么关系吗?不,我只是说大师,所以正文的其余部分与那个分支相关。所有分支都只是指针的名称。这个答案不正确。因为OP处于分离头状态,
    git reset--hard commit1