在我的Git存储库中,我连续创建了三个提交:commit1
,commit2
和commit3
。
然后我意识到我在commit2
和commit3
搞砸了,并决定回到commit1
。为此,我跑了
git checkout commit1
现在我在commit1
。如何删除commit2
和commit3
?
答案 0 :(得分:3)
根据您的说明,假设您在mybranch
(在下面的图表中commit1
)之前访问了某个名为C1
的分支,您必须处于以下情况:
C1 [HEAD]
\
C2 -- C3 [mybranch]
提交C2
和C3
仍会显示在git log
的输出中,因为它们仍然可以从mybranch
引用中获得。另请注意,HEAD
已分离。你应该做的是......
运行
,将HEAD
重新挂接到mybranch
git checkout mybranch
这应该会使您处于以下情况:
C1
\
C2 -- C3 [HEAD -> mybranch]
通过运行
将mybranch
分支重置为其小费的祖父母
git reset --hard mybranch~2
这应该会让你处于以下情况:
C1 [HEAD -> mybranch]
由于提交C2
和C3
现已无法访问(即"已删除"),因此最后一个图表中未显示这些内容。
这可能有点厚颜无耻,但这里解释了为什么其他两个答案不会起作用。正如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)
git branch -f mybranch
git checkout -
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
)。