git review (三)
歷史穿梭
- 圖形工具
gitk --all
- 關於
^
^
後面跟的數字表示第幾個父提交,其中如果A是Tag對象,則A^0
表示Tag對象指向的commit對象。 - !!!
~
後面的數字表示該提交的第幾個父提交。A^{tree}
表示里程碑A對應的目錄樹(也可以用A:
表示),顯示樹裏面的文件,可以這樣A^{tree}:src/Makefile
或者A:src/Makefile
,查看暫存區裏面的文件的哈希值git rev-parse :filename
- 還有reflog中提到的符號
@
可以去前面找找,舉個例子master@{0}
- 關於
git log --oneline --graph --stat --decorate
git rev-parse
git rev-list
git diff
語法請看《git權威指南》11章相關內容。
改變歷史
第一種方法
- 執行修改提交說明
git commit --amend 'message'
- 多步悔棋舉例
git reset --soft HEAD^^
git commit -m 'some changes'
背景有六個順序提交Tag分別爲:
A
B
C
D
E
F
G
(master初試所在地)
這裏用前面的命令,是所謂的第一種方法
- 現在消滅
D
代碼序列爲:
git checkout C
git cherry-pick master^
git cherry-pick master
git checkout master
git reset --hard HEAD@{1} #此處用到了reflog語法
恢復初試狀態代碼:
git checkout master
git reset --hard F
- 將
C
和D
融合
代碼序列如下:
git checkout D
git reset --soft HEAD^^ #也就是B那裏
git commit -C C #這裏是重用C提交的提交說明的意思
git cherry-pick E
git cherry-pick F
git checkout master
git reset --hard HEAD@{1}
然後重新恢復初始狀態,跟消滅D一樣的恢復就好
第二種方法改變歷史
git rebase
命令
命令格式git rebase --onto <newbase> <since> <till>
整個命令過程如下:
- 首先執行
git checkout
切換到 <till> - 將<since>…<till>所標識的提交範圍寫入到一個臨時文件中。包括<till>,但不包括<since>及其歷史提交。
- 將當前分支強制重置(
git reset --hard <newbase>
)到<newbase> - 從保存的臨時文件中注意提交到重置之後的分支上。
- 如果提交已經在分支中包含,則跳過該提交。
- 如果遇到衝突則暫停。解決衝突之後執行
git rebase --continue
或者git rebase --skip
或者git rebase --abort
上面的例子,新的代碼命令
- 現在消滅
D
的代碼序列變成了:
git rebase --onto C E^ F
git checkout master
git reset --hard HEAD@{1}
然後恢復 - -、 此處省略
- 接下來就是將
C
和D
融合:
git checkout D
git reset --soft HEAD^^
git commit -C C
git tag newbase
git rebase --onto newbase E^ master
#這裏用了master,checkout直接切換到master了,不用再reset了
git tag -d newbase
第三種改變歷史的方法
git rebase -i newbase
關於命令編輯會彈出說明,這個很好用
丟棄歷史
echo "Commit from tree of tag A." | git commit-tree A^{tree}
這樣就基於A對應的提交創建了一個根提交。然後再將master分支在里程碑A之後的提交變基到新的根提交上,實現對歷史提交的清楚。然後:
git rebase --onto 8f7f94b A master
這裏的8f7f94b是第一條命令的輸出部分。
反轉提交
git revert