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