- 12.3.3 时间旅行三
- Rebase d71ce92..b6f0b0a onto d71ce92
- Commands:
- p,pick=use commit
- r,reword=use commit,but edit the commit message
- e,edit=use commit,but stop for amending
- s,squash=use commit,but meld into previous commit
- f,fixup=like "squash",but discard this commit's log message
- x<cmd>,exec<cmd>=Run a shell command<cmd>,and stop if it fails
- If you remove a line here THAT COMMIT WILL BE LOST.
- However,if you remove everything,the rebase will be aborted.
- Rebase b3af728..b6f0b0a onto b3af728
- Commands:
- p,pick=use commit
- r,reword=use commit,but edit the commit message
- e,edit=use commit,but stop for amending
- s,squash=use commit,but meld into previous commit
- f,fixup=like "squash",but discard this commit's log message
- x<cmd>,exec<cmd>=Run a shell command<cmd>,and stop if it fails
- If you remove a line here THAT COMMIT WILL BE LOST.
- However,if you remove everything,the rebase will be aborted.
- This is a combination of 2 commits.
- The first commit's message is:
- This is the 2nd commit message:
12.3.3 时间旅行三
《回到未来》第三集,成了铁匠的布朗博士手工打造了可以时光旅行的飞行火车,使用蒸汽作为动力。这款时间旅行火车更大、更安全、更舒适,适合一家四口外加宠物的时空旅行。与之对应本次实践也将采用“手工打造”:交互式变基。
交互式变基就是在上一节介绍的变基命令的基础上,添加了-i参数,在变基的时候进入一个交互界面。使用了交互界面的变基操作,不是自动化变基转换为手动确认那么没有技术含量,而是充满了魔法。
执行交互式变基操作,会将<since>..<till>的提交悉数罗列在一个文件中,然后自动打开一个编辑器来编辑这个文件。可以通过修改文件的内容设定变基操作,实现删除提交、将多个提交压缩为一个提交、更改提交的顺序,以及更改历史提交的提交说明等。
例如,下面的界面就是针对当前DEMO版本库执行的交互式变基时编辑器打开的文件:
pick b3af728 ignore object files.
pick 3488f2c move.gitignore outside also works.
pick 48456ab add hello.h
pick b6f0b0a modify hello.h
Rebase d71ce92..b6f0b0a onto d71ce92
#
Commands:
p,pick=use commit
r,reword=use commit,but edit the commit message
e,edit=use commit,but stop for amending
s,squash=use commit,but meld into previous commit
f,fixup=like "squash",but discard this commit's log message
x<cmd>,exec<cmd>=Run a shell command<cmd>,and stop if it fails
#
If you remove a line here THAT COMMIT WILL BE LOST.
However,if you remove everything,the rebase will be aborted.
从该文件中可以看出:
开头的四行由上到下依次对应于提交C、D、E、F。
前四行默认的动作都是pick,即应用此提交。
参考文件中的注释,可以通过修改动作名称,在变基的时候执行特定操作。
动作reword,或者简写为r。在变基时会应用此提交,但是在提交的时候允许用户修改提交说明。这个功能在Git 1.6.6之后开始提供,对于修改历史提交的提交说明非常方便。对于老版本的Git没有reword动作,可以使用edit动作。
动作edit,或者简写为e。也会在变基时应用此提交,但是会在应用后暂停变基,提示用户使用git commit—amend执行提交,以便对提交进行修补。当用户执行git commit—amend完成提交后,还需要执行git rebase—continue继续变基操作。用户在变基暂停状态下可以执行多次提交,从而实现把一个提交分解为多个提交。edit动作非常强大,对于老版本的Git没有reword动作,可以使用edit动作实现相同的效果。
动作squash,或者简写为s。该提交会与前面的提交压缩为一个。
动作fixup,或者简写为f。类似动作squash,但是此提交的提交说明被丢弃。这个功能在Git 1.7.0之后开始提供,老版本的Git还是使用squash动作吧。
可以通过修改变基任务文件中各个提交的先后顺序,进而改变最终变基后提交的先后顺序。
可以修改变基任务文件,删除包含相应提交的行,这样该提交就不会被应用,进而在变基后的提交中被删除。
有了对交互式变基命令的理解,就可以开始新的“回到未来”之旅了。
确认舞台已经布置完毕。
$git status-s-b
master
$git log—oneline—decorate-6
b6f0b0a(HEAD,tag:F,master)modify hello.h
48456ab(tag:E)add hello.h
3488f2c(tag:D)move.gitignore outside also works.
b3af728(tag:C)ignore object files.
d71ce92(tag:hello_1.0,tag:B)Hello world initialized.
c024f34(tag:A)README is from welcome.txt.
1.现在演出第一幕:干掉坏蛋D
(1)执行交互式变基操作。
$git rebase-i D^
(2)自动用编辑器修改文件。文件内容如下:
pick 3488f2c move.gitignore outside also works.
pick 48456ab add hello.h
pick b6f0b0a modify hello.h
Rebase b3af728..b6f0b0a onto b3af728
#
Commands:
p,pick=use commit
r,reword=use commit,but edit the commit message
e,edit=use commit,but stop for amending
s,squash=use commit,but meld into previous commit
f,fixup=like "squash",but discard this commit's log message
x<cmd>,exec<cmd>=Run a shell command<cmd>,and stop if it fails
#
If you remove a line here THAT COMMIT WILL BE LOST.
However,if you remove everything,the rebase will be aborted.
#
(3)将第一行删除,使得上面的文件看起来像是这样(省略井号开始的注释):
pick 48456ab add hello.h
pick b6f0b0a modify hello.h
(4)保存退出。
变基自动开始,即刻完成。
显示下面的内容:
Successfully rebased and updated refs/heads/master.
(5)看看日志。当前分支master已经完成变基,消灭了“坏蛋D”。
$git log—oneline—decorate-6
78e5133(HEAD,master)modify hello.h
11eea7e add hello.h
b3af728(tag:C)ignore object files.
d71ce92(tag:hello_1.0,tag:B)Hello world initialized.
c024f34(tag:A)README is from welcome.txt.
63992f0 restore file:welcome.txt
2.幕布拉上,后台重新布景
为了第二幕能够顺利演出,需要将master分支重新置回到提交F上。执行下面的操作完成“重新布景”。
$git checkout master
Already on 'master'
$git reset—hard F
HEAD is now at b6f0b0a modify hello.h
布景完毕,大幕即将再次拉开。
3.现在演出第二幕:坏蛋D被感化,融入社会
(1)同样执行交互式变基操作,不过因为要将C和D压缩为一个,因此变基从C的父提交开始。
$git rebase-i C^
(2)自动用编辑器修改文件。文件内容如下(忽略井号开始的注释):
pick b3af728 ignore object files.
pick 3488f2c move.gitignore outside also works.
pick 48456ab add hello.h
pick b6f0b0a modify hello.h
(3)修改第二行(提交D),将动作由pick修改为squash。修改后的内容如下:
pick b3af728 ignore object files.
squash 3488f2c move.gitignore outside also works.
pick 48456ab add hello.h
pick b6f0b0a modify hello.h
(4)保存退出。自动开始变基操作,在执行到squash命令设定的提交时,进入提交前的日志编辑状态。
显示的待编辑日志如下。很明显C和D的提交说明显示在了一起。
This is a combination of 2 commits.
The first commit's message is:
ignore object files.
This is the 2nd commit message:
move.gitignore outside also works.
(5)保存退出,即完成squash动作标识的提交合并及后续变基操作。
看看提交日志,看到提交C和提交D都不见了,代之以一个融合后的提交出现。
$git log—oneline—decorate-6
c0c2a1a(HEAD,master)modify hello.h
c1e8b66 add hello.h
db512c0 ignore object files.
d71ce92(tag:hello_1.0,tag:B)Hello world initialized.
c024f34(tag:A)README is from welcome.txt.
63992f0 restore file:welcome.txt
(6)可以看到融合C和D的提交日志实际上是两者日志的融合。在前面单行显示的日志中看不出来。
$git cat-file-p HEAD^^
tree 00239a5d0daf9824a23cbf104d30af66af984e27
parent d71ce9255b3b08c718810e4e31760198dd6da243
author Jiang Xin<jiangxin@ossxp.com>1291720899+0800
committer Jiang Xin<jiangxin@ossxp.com>1292153393+0800
ignore object files.
move.gitignore outside also works.
时光旅行结束了,多么神奇的Git啊。