第12章 改变历史
我是电影《回到未来》的粉丝,偶尔会做梦,梦见穿梭到未来拿回一本2000-2050体育年鉴。操作Git也可以体验到穿梭时空的感觉,因为Git像极了一个时光机器,不但允许你在历史中穿梭,而且还能够改变历史。
本章的最开始将介绍两种最简单和最常用的历史变更操作——“悔棋”操作,就是对刚刚进行的一次或几次提交进行修补或撤销。对于跳跃式的历史记录的变更,即仅对过去某一个或某几个提交做出改变,会在“回到未来”小节详细介绍。在“丢弃历史”小节会介绍一种版本库瘦身的方法,这可能会在某些特定的场合用到。
作为分布式版本控制系统,一旦版本库被多人共享,改变历史就可能是无法完成的任务。在本章的最后,介绍还原操作以实现在不改变历史提交的情况下还原错误的改动。
12.1 悔棋
在日常的Git操作中,会经常出现这样的状况,输入git commit命令刚刚敲下回车键就后悔了:可能是提交说明中出现了错别字,或者有文件忘记提交,或者有的修改不应该提交,诸如此类。
像Subversion那样的集中式版本控制系统是“落子无悔”的系统,只能叹一口气责怪自己太不小心了。然后根据实际情况弥补:马上做一次新提交改正前面的错误;或者只能将错就错,错误的提交说明就让它一直错下去吧。因为大部分Subversion管理员不敢或不会放开修改提交说明的功能,从而导致无法对提交说明进行修改。
Git提供了“悔棋”的操作,甚至因为“单步悔棋”是如此经常的发生,乃至于Git提供了一个简洁的操作——修补式提交,命令是:git commit—amend。
看看当前版本库最新的两次提交:
$cd/path/to/my/workspace/demo
$git log—stat-2
commit 822b4aeed5de74f949c9faa5b281001eb5439444
Author:Jiang Xin<jiangxin@ossxp.com>
Date:Wed Dec 8 16:27:41 2010+0800
测试使用qgit提交。
README|1+
src/hello.h|2—
2 files changed,1 insertions(+),2 deletions(-)
commit 613486c17842d139871e0f1b0e9191d2b6177c9f
Author:Jiang Xin<jiangxin@ossxp.com>
Date:Tue Dec 7 19:43:39 2010+0800
偷懒了,直接用-a参数直接提交。
src/hello.h|1+
1 files changed,1 insertions(+),0 deletions(-)
最新一次的提交的确是在上一章使用qgit进行的提交,但这和提交内容无关,因此需要改掉这个提交的提交说明。使用下面的命令即可做到。
$git commit—amend-m "Remove hello.h,which is useless."
[master 7857772]Remove hello.h,which is useless.
2 files changed,1 insertions(+),2 deletions(-)
delete mode 100644 src/hello.h
上面的命令使用了-m参数是为了演示的方便,实际上完全可以直接输入git commit—amend,在弹出的提交说明编辑界面修改提交说明,然后保存退出完成修补提交。
下面再看看最近两次的提交说明,可以看到最新的提交说明更改了(包括提交的SHA1哈希值),而它的父提交(即前一次提交)没有改变。
$git log—stat-2
commit 78577724305e3e20aa9f2757ac5531d037d612a6
Author:Jiang Xin<jiangxin@ossxp.com>
Date:Wed Dec 8 16:27:41 2010+0800
Remove hello.h,which is useless.
README|1+
src/hello.h|2—
2 files changed,1 insertions(+),2 deletions(-)
commit 613486c17842d139871e0f1b0e9191d2b6177c9f
Author:Jiang Xin<jiangxin@ossxp.com>
Date:Tue Dec 7 19:43:39 2010+0800
偷懒了,直接用-a参数直接提交。
src/hello.h|1+
1 files changed,1 insertions(+),0 deletions(-)
如果最后一步操作不想删除文件src/hello.h,而只是想修改README,则可以按照下面的方法进行修补操作,具体操作过程如下。
(1)还原删除的src/hello.h文件。
$git checkout HEAD^—src/hello.h
(2)此时查看状态,会看到src/hello.h被重新添加回暂存区。
$git status
On branch master
Changes to be committed:
(use "git reset HEAD<file>…"to unstage)
#
new file:src/hello.h
#
(3)执行修补提交,不过提交说明是不是也要更改呢,因为毕竟这次提交不会删除文件了。
$git commit—amend-m "commit with—amend test."
[master 2b45206]commit with—amend test.
1 files changed,1 insertions(+),0 deletions(-)
(4)再次查看最近的两次提交,会发现最新的提交不再删除文件src/hello.h了。
$git log—stat-2
commit 2b452066ef6e92bceb999cf94fcce24afb652259
Author:Jiang Xin<jiangxin@ossxp.com>
Date:Wed Dec 8 16:27:41 2010+0800
commit with—amend test.
README|1+
1 files changed,1 insertions(+),0 deletions(-)
commit 613486c17842d139871e0f1b0e9191d2b6177c9f
Author:Jiang Xin<jiangxin@ossxp.com>
Date:Tue Dec 7 19:43:39 2010+0800
偷懒了,直接用-a参数直接提交。
src/hello.h|1+
1 files changed,1 insertions(+),0 deletions(-)