重写历史纪录-Git详解(6)

概要:

  • git commit –amend 修改当前提交
  • git rebase 超强的历史修改能力,常用来维护线性历史
  • git reset
  • git reflog 维护了一个HEAD的历史引用信息

git commit –amend

修改当前的提交,然后产生新的提交,替换当前提交

1
2
3
4
5
6
$ git lol
* 74ea61c (HEAD -> master) third commit
* a5caca5 second commit
* 4db06b3 initial_commit
$ vim master.txt # 修改文件
$ git commit --amend

git rebase

维护线性历史举例

1
2
3
4
5
6
7
8
9
10
11
12
$ git checkout -b v0 HEAD~
$ vim master.txt
$ #做一些修改,使历史看上去有分叉
$ $ git lol
* 7563975 (master) 5
* ed0bcf8 4s
| * 1fe21de (HEAD -> v0) v0_5a
| * 4b9e9f7 v0_5
|/
* 515aabd 3s
* 4037fac 2
* c04ce5f 1

第一步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: v0_5
error: Failed to merge in the changes.
Using index info to reconstruct a base tree...
M master.txt
Falling back to patching base and 3-way merge...
Auto-merging master.txt
CONFLICT (content): Merge conflict in master.txt
Patch failed at 0001 v0_5
The copy of the patch that failed is found in: .git/rebase-apply/patch
When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".

第二步

1
2
$ vim master.txt #修改冲突
$ git add master.txt

第三步

1
2
3
4
5
6
7
$ git rebase --continue
Applying: v0_5
Applying: v0_5a
Using index info to reconstruct a base tree...
M master.txt
Falling back to patching base and 3-way merge...
No changes -- Patch already applied.

结果

1
2
3
4
5
6
7
$ git lol
* 2aef270 (HEAD -> v0) v0_5
* 7563975 (master) 5
* ed0bcf8 4s
* 515aabd 3s
* 4037fac 2
* c04ce5f 1

修改v0分支的后,又重新出现了分支,rebase是重置了分支的起点

1
2
3
4
5
6
7
8
9
10
$ git lol
* d6c5fe7 (HEAD -> master) ma
| * 3d87ba5 (v0) va
| * 2aef270 v0_5
|/
* 7563975 5
* ed0bcf8 4s
* 515aabd 3s
* 4037fac 2
* c04ce5f 1

git reflog

维护了HEAD引用的历史,比如,我们想查看rebase之前的分支v0的开发情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ git reflog
d6c5fe7 (HEAD -> master) HEAD@{0}: commit: ma
7563975 HEAD@{1}: checkout: moving from v0 to master
3d87ba5 (v0) HEAD@{2}: commit: va
2aef270 HEAD@{3}: rebase finished: returning to refs/heads/v0
2aef270 HEAD@{4}: rebase: v0_5
7563975 HEAD@{5}: rebase: checkout master
1fe21de HEAD@{6}: checkout: moving from master to v0
7563975 HEAD@{7}: commit: 5
ed0bcf8 HEAD@{8}: commit (amend): 4s
3b2b538 HEAD@{9}: checkout: moving from v0 to master
1fe21de HEAD@{10}: commit: v0_5a
4b9e9f7 HEAD@{11}: commit: v0_5
515aabd HEAD@{12}: checkout: moving from master to v0
3b2b538 HEAD@{13}: commit: 4
515aabd HEAD@{14}: checkout: moving from v0 to master
515aabd HEAD@{15}: checkout: moving from master to v0
515aabd HEAD@{16}: commit (amend): 3s
2ee9964 HEAD@{17}: commit (amend): 3
2adb172 HEAD@{18}: commit: 3
4037fac HEAD@{19}: commit: 2
c04ce5f HEAD@{20}: commit (initial): 1

使用 reset 命令 –hard 参数,使得工作区和暂存区,都还原到HEAD@{6}指向的那个commit的状态

1
2
3
4
5
6
7
8
9
10
11
12
$ git reset --hard HEAD@{6}
$ git lol
* 3d87ba5 (v0) va
* 2aef270 v0_5
* 7563975 5
* ed0bcf8 4s
| * 1fe21de (HEAD -> master) v0_5a
| * 4b9e9f7 v0_5
|/
* 515aabd 3s
* 4037fac 2
* c04ce5f 1