Git log -S漏掉改動?用-G找增刪行

想找「哪次提交把timeout從10改成30」,明明看過那筆修改,git log -S 'timeout'卻沒列出來。原因可能不是紀錄消失,而是搜尋條件不同:-S看指定字串在檔案裡的出現次數有沒有變;-G則檢查差異裡新增或刪除的行是否符合正規表示式。

值改了,字串出現次數卻沒變

假設config.txt原本只有一行timeout=10,下一次提交改成timeout=30。兩個版本都只出現一次timeout;因此,以timeout作為-S條件,不會因為數值變動而選出這筆提交。

git log --oneline -S 'timeout' -- config.txt

git log --oneline -G 'timeout' -- config.txt

第二條會檢查patch裡的增刪行。因為刪掉的timeout=10、新增的timeout=30都符合timeout,所以-G能找到這次改值。第一條仍可能列出最早新增timeout的提交,不能把「有搜尋結果」誤認為已找到這次修改。

用一個練習庫,看清楚兩組結果

在獨立練習資料夾建立Git儲存庫,先提交config.txt,內容為timeout=10,提交訊息用base;再改成timeout=30,提交訊息用raise timeout;最後補上第二行retry=2,提交訊息用add retry。每次都先git add config.txt再提交。完成後查詢:

git log --format=%s -S 'timeout' -- config.txt
# base

git log --format=%s -G 'timeout' -- config.txt
# raise timeout
# base

git log --format=%s -S 'timeout=10' -- config.txt
# raise timeout
# base

這裡的註解是預期顯示的提交訊息,不是另一條命令。-S 'timeout=10'能找到raise timeout,是因為完整字串timeout=10從一次變成零次;搜尋timeout時,它仍各出現一次。最後新增retry那筆不符合這些條件,所以不會列出。

找到提交後,再看實際改了哪一行

git log -p -G '^timeout=' -- config.txt

# 若已找到要核對的提交,將COMMIT換成它的雜湊
git show COMMIT -- config.txt

^timeout=只比對行首為timeout=的增刪行,能縮小搜尋範圍;-p會把差異一併顯示。選中提交後,核對刪除行、新增行、檔案路徑及上下文,再判斷它是否就是造成問題的修改。這些查詢不會把工作目錄切回舊版。

搜不到時,先檢查條件與範圍

  • 找字串何時增加或消失,用-S;找包含某段文字的行何時被改,用-G。-S預設按字面字串搜尋,-G使用正規表示式,點號、括號等字元要按正規表示式規則處理。
  • 不要把--grep當成程式碼搜尋:它找的是提交訊息。提交訊息沒寫timeout,不代表程式裡沒有修改它。
  • --後面是要限制的路徑;路徑拼錯、分支不對,或相關提交不在目前可查的歷史中,都可能沒有結果。
  • 開啟--pickaxe-regex會讓-S把條件當正規表示式,仍然比較出現次數;不會變成-G的增刪行搜尋。

排查一個設定值被改動的時間點,可以先以-G縮小提交,再讀patch;若想追它何時被加入或刪除,再改用-S搜尋完整字串。結果是否符合需求,要回到那筆提交的差異確認。

參考資料

原文鏈接:https://wntheme.com/git-log-pickaxe-s-g-changed-lines/,轉載請註明出處。
0

評論0

顯示驗證碼
沒有帳號?註冊  忘記密碼?