這是起底Git系列的第六篇,本篇我們來介紹一下Git的進(jìn)階技巧。
假設(shè)當(dāng)前版本庫如下圖所示,有時我們可能先找到當(dāng)前提交的父提交和祖先提交,^和~可以滿足我們的需求
^和~都匹配當(dāng)前提交的父提交,^^和~~匹配父提交的父提交,^和~后面跟數(shù)字的時候意義是不同的,具體可以看下面的例子
$ git log HEAD^
A2
$ git log HEAD^^
A1
$ git log HEAD^2
B1
$ git log HEAD~
A2
$ git log HEAD~~
A1
$ git log HEAD~2
A1
有時候我們可能會想選擇一個區(qū)間,比如A1,A2,A3,下面通過例子說明..,…和^的區(qū)別
$ git log master..test
C0 C1
$ git log ^master test
C0 C1
$ git log master…test
A1 A2 A3 C0 C1
A:設(shè)想這樣一種情況,摸個分支test,開發(fā)完后被刪除了,怎么找回這個分支呢?
其實git會在本地記錄每次HEAD的變化,通過reflog命令可以拿到這些記錄
$ git reflog
0e94c5b HEAD@{0}: commit: 222
7e07aa7 HEAD@{1}: commit: 111
c5aba97 HEAD@{2}: commit: 000
比如111是test分支最后一個提交,我們可以去111這個提交,然后在新建一個分支就ok了
$ git checkout 7e07aa7 # 或者git checkout HEAD@{1}
$ git checkout -b test
B:設(shè)想這樣一種情況,某天你突然發(fā)現(xiàn)某行代碼寫錯了,你想快速找到這個bug的始作俑者?
blame可以快速顯示文件的每一行最后一次修改是誰
$ git blame README.md
f6ffa8f4 (yanhaijing 2016-08-03 19:54:42 +0800 1) 123
f6ffa8f4 (yanhaijing 2016-08-03 19:54:42 +0800 1) 456
C:設(shè)想這樣一種情況,你想在Git的某個歷史提交中進(jìn)行搜索?
grep只能搜索工作目錄,git grep可以在指定提交中進(jìn)行搜索
$ git grep yanhaijing HEAD~27 fis-conf.js
HEAD~27:fis-conf.js: * @author yanhaijing.com
D:設(shè)想這樣一種情況,你想在Git的整個歷史中進(jìn)行搜索?git log可以實現(xiàn)這個功能
$ git log -Syanhaijing --oneline
0a191c message aaa
E:設(shè)想這樣一種情況,某一天你突然發(fā)現(xiàn)線上代碼掛了,但你找不到原因,你想快速找到是哪一個版本引入的bug?
git bisect是一個非常有用的調(diào)試工具,它通過自動進(jìn)行一個二分查找來找到哪一個特定的提交是導(dǎo)致 bug 或者問題的第一個提交
$ git bisect start # 開始
$ git bisect bad # 標(biāo)記為好的
$ git bisect good # 標(biāo)記為壞的
$ git bisect reset # 結(jié)束
假設(shè)你提交完后發(fā)現(xiàn)忘記了一些東西,打算更改上次提交,在git中可以使用追加提交,假設(shè)現(xiàn)在倉庫狀態(tài)如下所示
修改完后可以再次提交
$ git add .
$ git commit --amend
就可以修改上次提交,需要注意的是上一次提交并沒有被刪除,只是沒有分支引用,變成了游離狀態(tài),在未來的某個時間會被git自動回收
如果你進(jìn)行了幾次提交后后悔了,想重寫之前的好幾次提交,那就只能用rebase了,假設(shè)目前狀態(tài)如下
假設(shè)你想重寫A1和A2
$ git rebase -i HEAD~2
需要注意的是已經(jīng)push到遠(yuǎn)端的提交,就不要再重寫了,不然世界人民會恨你,因為你需要git push -f
重置有兩種方法,reset和checkout,這兩個方法非常容易混淆,兩個命令都分為全局模式和文件模式
reset全局模式可以用下圖總結(jié)
reset的文件模式可以覆蓋索引區(qū),一個副作用就是用來取消暫存
git reset xxx – file
checkout的全局模式可以用下圖總結(jié)
checkout的文件模式會覆蓋索引區(qū)和工作區(qū),可以用來丟棄修改,屬于不可逆轉(zhuǎn)的操作
git checkout xxx – file
其實下圖就總結(jié)兩個命令的區(qū)別
合并分支時,很多人非常害怕遇到?jīng)_突,其實沖突并不可怕
A:git默認(rèn)的沖突顯示包括our和their,如下所示
xxx
如果想得到和svn那樣包含base+our+their的代碼,可以檢出沖突
$ git checkout --conflict=diff3 hello.rb
B:如果在沖突時想想svn一樣得到,base+our+their三個文件的代碼
$ git show :1:xxx > xxx.base
$ git show :2:xxx > xxx.our
$ git show :3:xxx > xxx.their
C:合并沖突一團亂麻,想撤銷合并
$ git merge --abort
D:合并后后悔了?想撤消合并?分為兩種情況
假如還沒推送到遠(yuǎn)端,可以reset掉
$ git reset --hard HEAD~
如果已經(jīng)推動到遠(yuǎn)端,可以用revert
$ git revert -m 1 HEAD
如果你有任何疑問的話,歡迎留言討論;如果本系列文章對你有幫助的話,那我很榮幸,別忘了打賞哦,O(∩_∩)O哈哈~
最后感謝你的閱讀,O(∩_∩)O哈哈~
更多建議: