如何删除当前HEAD之后的提交?

时间:2014-12-25 11:09:02

标签: git git-commit

在我的Git存储库中,我连续创建了三个提交:commit1commit2commit3

然后我意识到我在commit2commit3搞砸了,并决定回到commit1。为此,我跑了

git checkout commit1

现在我在commit1。如何删除commit2commit3

4 个答案:

答案 0 :(得分:3)

检查分支,然后重置

根据您的说明,假设您在mybranch(在下面的图表中commit1)之前访问了某个名为C1的分支,您必须处于以下情况:

C1 [HEAD]
 \
  C2 -- C3 [mybranch]

提交C2C3仍会显示在git log的输出中,因为它们仍然可以从mybranch引用中获得。另请注意,HEAD已分离。你应该做的是......

  1. 运行

    ,将HEAD重新挂接到mybranch
    git checkout mybranch
    

    这应该会使您处于以下情况:

    C1
     \
      C2 -- C3 [HEAD -> mybranch]
    
  2. 通过运行

    mybranch分支重置为其小费的祖父母
    git reset --hard mybranch~2
    

    这应该会让你处于以下情况:

    C1 [HEAD -> mybranch]
    
  3. 由于提交C2C3现已无法访问(即"已删除"),因此最后一个图表中未显示这些内容。


    为什么在没有首先重新连接HEAD的情况下进行重置

    这可能有点厚颜无耻,但这里解释了为什么其他两个答案不会起作用。正如cmbuckley在his comment中正确指出的那样,

      

    git reset重置您当前分支的状态(因此您需要在分支上执行此操作)。如果你已经签出commit1,那么你可能不在分支机构(独立的HEAD状态)。

    由于OP(Imray)处于分离的HEAD状态,在重新连接HEAD到分支之前运行git-reset 移动有问题的分支引用。这是一个说明这一点的玩具示例。

    # set things up
    $ mkdir test
    $ cd test
    $ git init
    Initialized empty Git repository in /Users/jubobs/Desktop/test/.git/
    
    # create a first commit
    $ touch README
    $ git add .
    $ git commit -m "add README"
    [master (root-commit) 85137ba] add README
     1 file changed, 0 insertions(+), 0 deletions(-)
     create mode 100644 README
    
    # create a second commit
    $ printf "foo\n" > README
    $ git commit -am "write 'foo' in README"
    [master 3948e84] write 'foo' in README
     1 file changed, 1 insertion(+)
    
    # inspect the log
    $ git log --graph --decorate --oneline --all
    * 3948e84 (HEAD, master) write 'foo' in README
    * 85137ba add README
    
    # check out the second commit (which detaches the HEAD)
    $ git checkout 3948e84
    Note: checking out '3948e84'.
    # (boilerplate stdout is omitted...)
    HEAD is now at 3948e84... write 'foo' in README
    
    # reset to the first commit (equivalent to 'git reset --hard 85137ba')
    $ git reset --hard HEAD^
    HEAD is now at 85137ba add README
    $ git log --graph --decorate --oneline --all
    * 3948e84 (master) write 'foo' in README
    * 85137ba (HEAD) add README
    

    请注意,git reset命令将HEAD移动到初始提交,但移动master分支。第二次提交未被删除",因为它仍然可以从master 到达;因此,它列在git log的输出中。

答案 1 :(得分:1)

我会假设你在你的回购中的主分支中出于命名目的,但任何分支都会这样做。这可以被认为是指向提交对象的指针。您还可以将HEAD视为另一个指针,您可以使用git checkout

移动它
commit1  ->  commit2  ->  commit3
                             ^
                             |
                           master

如果要将主指针更改为commit1,则需要发出git reset命令,正如其他人指示的那样。

git reset --hard commit1

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

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

git gc --aggressive --prune

直到它从你的仓库中被主动清除,你仍然可以检查commit2和commit3,所以尽管你将主指针移回commit1(带git reset),你必须小心,如果(说)你意外地将密码提交到存储库并试图恢复 - 它们仍将在您的本地仓库中进行修剪。

答案 2 :(得分:1)

强制您的分支到当前的HEAD和结帐分支

git branch -f mybranch
git checkout -

Checkout分支并强制您的分支到当前HEAD

git checkout -
git reset --hard HEAD@{1}

第二个选项特别有利,因为您不需要键入Branh的名称或当前提交的标识。你甚至可以把它变成别名。

编辑:这假设您没有跳过,最近的结帐是来自您的分支。

答案 3 :(得分:0)

你想要核实提交commit3(假设你目前正在使用commit3 - HEAD)。你可以这样做:

git reset --hard HEAD~1

结果是:

commit1 -> commit2 
              ↑
             HEAD

您可以按照类似的流程返回commit1(即git reset --hard HEAD~2)。