有的时候,改完代码提交 commit 后发现写得实在太烂了,连本身的都看不下去,与其修改它还不如丢弃重写。怎么操做呢?git
若是是最近提交的 commit 要丢弃重写能够用 reset
来操做。好比你刚写了一个 commit:shell
写完回头看了看,你以为不行这得从新写。那么你能够用 reset --hard
来撤销这条 commit。bash
git reset --hard HEAD^
HEAD^ 表示往回数一个位置的 commit`,上篇刚说过。this
由于你要撤销最新的一个 commit,因此你须要恢复到它的父 commit ,也就是 HEAD^
。那么在这行以后,你要丢弃的最新一条就被撤销了:3d
不过,就像图上显示的,你被撤销的那条提交并无消失,只是你再也不用到它了。若是你在撤销它以前记下了它的 SHA-1 码,那么你还能够经过 SHA-1 来找到他它。rest
假若有一个 commit,你在刚把它写完的时候并无以为它很差,但是在以后又写了几个提交之后,你忽然灵光一现:哎呀,那个 commit 不应写,我要撤销!code
不是最新的提交,就不能用 reset --hard
来撤销了。这种状况的撤销,就要用以前介绍过的一个指令交互式变基:rebase -i
。blog
以前介绍过,交互式变基能够用来修改某些旧的 commit。其实除了修改提交,它还能够用于撤销提交。好比下面这种状况:rem
你想撤销倒数第二条 commit,那么可使用 rebase -i
:it
git rebase -i HEAD^^
Git 引导到选择要操做的 commit 页面:
pick 310154e 第 N-2 次提交 pick a5f4a0d 第 N-1 次提交 # Rebase 710f0f8..a5f4a0d onto 710f0f8 # # Commands: # p, pick <commit> = use commit # r, reword <commit> = use commit, but edit the commit message # e, edit <commit> = use commit, but stop for amending # s, squash <commit> = use commit, but meld into previous commit # f, fixup <commit> = like "squash", but discard this commit's log message # x, exec <command> = run command (the rest of the line) using shell # b, break = stop here (continue rebase later with 'git rebase --continue') # d, drop <commit> = remove commit ...
在上篇中,讲到要修改哪一个 commit 就把哪一个 commit 前面的 pick
改为 edit
。而若是你要撤销某个 commit ,作法就更加简单粗暴一点:直接删掉这一行就好(使用 d
命令)。
pick a5f4a0d 第 N-1 次提交 # Rebase 710f0f8..a5f4a0d onto 710f0f8 # # Commands: # p, pick <commit> = use commit # r, reword <commit> = use commit, but edit the commit message # e, edit <commit> = use commit, but stop for amending # s, squash <commit> = use commit, but meld into previous commit # f, fixup <commit> = like "squash", but discard this commit's log message # x, exec <command> = run command (the rest of the line) using shell # b, break = stop here (continue rebase later with 'git rebase --continue') # d, drop <commit> = remove commit ...
把这一行删掉就至关于在 rebase 的过程当中跳过了这个 commit,从而也就把这个 commit 丢弃了。
若是你经过 git log
查看,就会发现以前的倒数第二条 commit 已经不在了。
除了用交互式 rebase,你还能够用 rebase --onto
来更简便地撤销提交。
rebase 加上 --onto
选项以后,能够指定 rebase 的「起点」。通常的 rebase, 的「起点」是自动选取的,选取的是当前 commit 和目标 commit 在历史上的交叉点。
例以下面这种状况:
若是在这里执行:
git rebase 第3个commit
那么 Git 会自动选取 3
和 5
的历史交叉点 2
做为 rebase 的起点,依次将 4
和 5
从新提交到 3
的路径上去。
而 --onto
参数,就能够额外给 rebase 指定它的起点。例如一样以上图为例,若是我只想把 5
提交到 3
上,不想附带上 4
,那么我能够执行:
git rebase --onto 第3个commit 第4个commit branch1
选项 --onto
参数后面有三个附加参数:目标 commit、起点 commit(注意:rebase 的时候会把起点排除在外)、终点 commit。因此上面这行指令就会从 4
往下数,拿到 branch1
所指向的 5
,而后把 5
从新提交到 3
上去。
一样的,你也能够用 rebase --onto
来撤销提交:
git rebase --onto HEAD^^ HEAD^ branch1
上面这行代码的意思是:以倒数第二个 commit 为起点(起点不包含在 rebase 序列里),branch1
为终点,rebase 到倒数第三个 commit 上。
也就是这样:
撤销最近一次的 commit 直接使用 reset --hard
,撤销过往历史提交。方法有两种:
git rebase -i
在编辑界面中删除想撤销的 commitgit rebase --onto
在 rebase 命令中直接剔除想撤销的 commit这有两种理念是同样的,即在 rebase 的过程当中去掉想撤销的 commit,让它消失在历史中。