本文首次發表在 6 條 Git 實用技巧 -- 泰曉科技
本文彙總最近一段時間用到的幾則 Git 實用小技巧,歡迎分享。
通過 git blame 找到誰動了某行程式碼
在 定位到出錯的程式碼行 以後,就可以通過 git blame
進一步找到誰動了相關程式碼,或者找到這筆改動的歷史背景,舉例如下:
$ cd linux-stable
$ git blame -L 50,50 init/main.c
78634061 (Frederic Weisbecker 2017-10-27 04:42:28 +0200 50) #include <linux/sched/isolation.h>
複製程式碼
通過 git log 獲取某筆 commit 或 tag 的提交時間
在分析衰退時,如果找到了某筆變更,然後,又想進一步確定這筆變更是在哪個版本(Tag)引入的,這個時候可以先找一下該 commit 的時間,然後再比對 Tag 的修訂時間。那麼如何檢視 commit 和 tag 的引入時間呢?以 HEAD
這筆 commit 舉例如下:
$ date -d @`git log -1 --format=%ct HEAD` +%Y%m%d-%H%M%S
20190719-172216
複製程式碼
把 HEAD
替換為具體的 commit 和 tag 號即可獲得對應時間。對於 Linux 而言,通常不需要這麼複雜,在找到某個變更之後,用下面這個方法就可以確定該變更對應的核心主版本:
$ git show HEAD:Makefile
複製程式碼
因為 Makefile 中記錄了核心的版本號。
通過 git bisect 自動二分法快速定位問題
某個系統,在開發過程中一直都沒測試出問題,突然有一天,發現 Bug。這種蠻多情況是衰退,如果這個 Bug 的復現機率很大的話,就可以直接用二分法快速定位了。git bisect
就可以輔助進行自動二分法。
簡單的話,就是不停地告訴 git bisect
,哪一個是好的,哪一個是壞的,如果有固定的復現指令碼,那麼在獲得第一對 bad, good
的 commit 後,就可以直接讓 git bisect
自動二分法。舉例說明:
$ git bisect start
$ git bisect bad efa5cf
$ git bisect good b6fcf0
$ git bisect run grep -q UCONFIG Makefile
複製程式碼
說明:
efa5cf
:第一個發現有問題的版本b6fcf0
:某個確認沒問題的版本grep -q UCONFIG Makefile
:能找到 UCONFIG 就是好的,找不到就是有問題
在設定完 bad, good
後,git bisect
會自動切出中間某個版本,然後針對這個版本,可以進行配置、編譯、執行,然後根據測試結果設定該版本為 bad or good
,例如:git bisect bad HEAD
,以此類推,git bisect
會不停地切出中間版本,直到可以判斷第一個 bad 的版本,這個版本就是引入衰退的變更。
這個完整的測試過程如果可以自動化,就可以寫成指令碼,作為 git bisect run
的引數,這樣就可以避免手動跑測試。上面的 grep 命令是經過初步分析後,找出的簡化策略。如果都能這樣通過檢索程式碼變更本身就可以判斷問題,那確實可以省去不少力氣。
用 git submodule sync 更新 git submodule 的遠端倉庫地址
前段我們把很多倉庫從 github 搬到了 gitee,搬完以後 Linux Lab 下的 .gitmodules
和 .git/config
都得更新 url 地址,但是更新完以後並不能直接用,還得用 git submodule sync
同步一下:
- 第 1 步,用 sed 替換
.gitmodules
和.git/config
中的 url - 第 2 步,執行
git submodule sync
為不同 Git 倉庫配置不同的 ssh key
為優化下載效率,最近把 Linux Lab 遷移到了碼雲,配置了不同的 ssh 私鑰/公鑰。為了避免在命令列每次都要額外指定不同的引數,可以新增一個配置檔案。
例如,給碼雲的私鑰檔案命名為 gitee.id_rsa
,把它放到 ~/.ssh
目錄下並修改許可權。
$ chmod 600 ~/.ssh/gitee.id_rsa
$ chmod 700 ~/.ssh
複製程式碼
之後,新增一個 ~/.ssh/config
,加入如下配置:
$ cat ~/.ssh/config
Host gitee
HostName gitee.com
IdentityFile ~/.ssh/gitee.id_rsa
User git
複製程式碼
這樣就可以直接類似下面下載和上傳,而無需每次輸入密碼或指定金鑰了,同時省掉了 git@
。
$ git clone gitee:aaaa/yyyy.git
$ cd cloud-lab
$ touch xxxx
$ git add xxxx
$ git commit -s -m "add xxxx"
$ git push gitee:aaaa/yyyy.git master
複製程式碼
用 git fetch 取代 git clone,實現斷點續傳
用 git clone
下載大型程式碼倉庫時,一旦網路中斷,後果是哭爹喊娘,但是於事無補,叫天天不應。
因為 git clone
沒有實現斷點續傳,不知道開發者腦子“進了什麼水”?Linus 求罵嗎?;-)
沒關係,用 git fetch
可以實現類似效果,而且極其簡單。
先用 git init 建立一個空目錄:
$ mkdir test-repo
$ cd test-repo
$ git init
複製程式碼
再在裡頭用 git fetch
要 clone 的倉庫:
$ git fetch https://gitee.com/tinylab/cloud-lab.git
$ git checkout -b master FETCH_HEAD
複製程式碼
git fetch
只能一個一個 branch fetch,fetch 完,把 FETCH_HEAD
checkout 出來新建對應的分支即可。如果 git fetch
中途中斷網路,可以再次 git fetch
,git fetch
可以續傳,不至於一斷網就前功盡棄。
送您一枚免費體驗卡
更多 Linux 精彩歡迎透過下方免費體驗卡訪問『Linux 知識星球』: