大家好,我是若川。持續組織了近一年的源碼共讀活動,感興趣的可以?加我微信?ruochuan12?參與,每周大家一起學習200行左右的源碼,共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》?包含20余篇源碼文章。歷史面試系列。另外:目前建有江西|湖南|湖北
籍前端群,可加我微信進群。
Git的功能是對文件做版本管理,其底層原理是一個對文件存取的系統,要想掌握Git,最重要的是理解commit tree,也就是提交記錄歷史,平時開發中我們都是通過分支來更新commit tree,Git的基礎就是要學會分支操作,推薦閱讀 《圖解Git分支和命令》。
在日常開發中,只掌握分支操作是不夠的,還需要通過各種命令操作commit tree,本文我們選擇5個典型場景,介紹一下 Git 的進階技巧,如下所示,學會這些技巧,可以極大提高工作中Git使用的效率:
??選擇版本
??搜索調試
??重寫歷史
??重置揭秘
??高級合并
選擇版本
假設當前版本庫如下圖所示,有時我們可能先找到當前提交的父提交和祖先提交,^和~可以滿足我們的需求。
^和~都匹配當前提交的父提交,^和~匹配父提交的父提交,^和~后面跟數字的時候意義是不同的,具體可以看下面的例子,假設有如下圖所示的提交樹:

如下的命令,可以看到^和~的區別:
$?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
有時候我們可能會想選擇一個區間,比如 A1,A2,A3,下面通過例子說明..,...和^的區別
$?git?log?master..test
C0?C1
$?git?log?^master?test
C0?C1
$?git?log?master…test
A1?A2?A3?C0?C1
搜索調試
A:設想這樣一種情況,某個分支 test,開發完后被刪除了,怎么找回這個分支呢?
其實 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:設想這樣一種情況,某天你突然發現某行代碼寫錯了,你想快速找到這個 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
blame 時可以指定范圍
$?git?blame?-L10,15??README.md?#?查看10-15行的信息
C:設想這樣一種情況,你想在 Git 的某個歷史提交中進行搜索?
grep 只能搜索工作目錄,git grep 可以在指定提交中進行搜索
$?git?grep?yanhaijing?HEAD~27?fis-conf.js
HEAD~27:fis-conf.js:?*?@author?yanhaijing.com
D:設想這樣一種情況,你想在 Git 的整個歷史中進行搜索?git log 可以實現這個功能
$?git?log?-Syanhaijing?--oneline
0a191c?message?aaa
E:設想這樣一種情況,某一天你突然發現線上代碼掛了,但你找不到原因,你想快速找到是哪一個版本引入的 bug?
git bisect 是一個非常有用的調試工具,它通過自動進行一個二分查找來找到哪一個特定的提交是導致 bug 或者問題的第一個提交
$?git?bisect?start?#?開始
$?git?bisect?bad?#?標記為好的
$?git?bisect?good?#?標記為壞的
$?git?bisect?reset?#?結束
重寫歷史
假設你提交完后發現忘記了一些東西,打算更改上次提交,在 git 中可以使用追加提交,假設現在倉庫狀態如下所示

修改完后可以再次提交
$?git?add?.
$?git?commit?--amend
就可以修改上次提交,需要注意的是上一次提交并沒有被刪除,只是沒有分支引用,變成了游離狀態,在未來的某個時間會被 git 自動回收

如果你進行了幾次提交后后悔了,想重寫之前的好幾次提交,那就只能用 rebase 了,假設目前狀態如下

假設你想重寫 A1 和 A2
$?git?rebase?-i?HEAD~2
需要注意的是已經 push 到遠端的提交,就不要再重寫了,不然世界人民會恨你,因為你需要git push -f

重置揭秘
重置有兩種方法,reset 和 checkout,這兩個方法非常容易混淆,兩個命令都分為全局模式和文件模式
reset 全局模式可以用下圖總結

reset 的文件模式可以覆蓋索引區,一個副作用就是用來取消暫存
git?reset?xxx?–?file
checkout 的全局模式可以用下圖總結

checkout 的文件模式會覆蓋索引區和工作區,可以用來丟棄修改,屬于不可逆轉的操作
git?checkout?xxx?–?file
其實下圖就總結兩個命令的區別

高級合并
合并分支時,很多人非常害怕遇到沖突,其實沖突并不可怕
A:git 默認的沖突顯示包括 our 和 their,如果想得到和 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:合并后后悔了?想撤消合并?分為兩種情況
假如還沒推送到遠端,可以 reset 掉
$?git?reset?--hard?HEAD~

如果已經推動到遠端,可以用 revert
$?git?revert?-m?1?HEAD

總結
歡迎大家閱讀本文,如果你覺得本文對你有幫助,那就點贊加關注作者吧,如果對本文有任何疑問,歡迎在評論區交流。
我在阿里招前端,我該怎么幫你?(現在還可以加模擬面試群)
如何拿下阿里巴巴 P6 的前端 Offer
如何準備阿里P6/P7前端面試--項目經歷準備篇
大廠面試官常問的亮點,該如何做出?
如何從初級到專家(P4-P7)打破成長瓶頸和有效突破
若川知乎問答:2年前端經驗,做的項目沒什么技術含量,怎么辦?
如何準備20K+的大廠前端面試
·················?若川簡介?·················
你好,我是若川,畢業于江西高校。現在是一名前端開發“工程師”。寫有《學習源碼整體架構系列》20余篇,在知乎、掘金收獲超百萬閱讀。
從2014年起,每年都會寫一篇年度總結,已經堅持寫了8年,點擊查看年度總結。
同時,最近組織了源碼共讀活動,幫助4000+前端人學會看源碼。公眾號愿景:幫助5年內前端人走向前列。
掃碼加我微信 lxchuan12、拉你進源碼共讀群
今日話題
目前建有江西|湖南|湖北?籍 前端群,想進群的可以加我微信 lxchuan12?進群。分享、收藏、點贊、在看我的文章就是對我最大的支持~