大家在平常開發工作時,應該常常會遇到程式碼一些敏感字詞是不想被 commit 進 Git 的,比方說 database 的帳號密碼,或是一些 IDE 自動生成的字詞,比方說 XCode 的 .xcscheme
等。這時候有的人就會說『那就手動把它 unstage 就好啦』,但同一件事重複做好幾年實在不符合懶人的個性,所以這時候 Git Keyword Expansion 就派上用場啦!
Git Keyword Expansion
關於 Keyword Expansion , Git 中文網 是這麼解釋的
使用 SVN 或 CVS 的開發人員經常要求關鍵字擴展。這在 Git 中主要的問題是,你無法在一個檔案被提交後再修改它,因為 Git 會先對該檔計算 checksum。然而,你可以在檔案 check out 之後注入(inject)一些文字,然後在提交前再把它移除。
聽起來很美好,對吧?接下來我們透過一個實際的例子來展示如何設定 Keyword Expansion 以及它如何實際作用在我們的 repository 中。
現在,我有一個 python 寫的 connect_db.py
,如下
可以看到這段 script 裡面充滿了各種的敏感資訊,我的目標是可以讓 db 的連線資訊全部被隱藏起來不要 commit 進 git 。git 提供兩種方向的過濾設定,分別為 clean 與 smudge (如下圖)。在 .gitattributes
中,你能對特定的檔案或路徑設定過濾程式,然後在 .git/config
中設定處理這些檔案的腳本,這些腳本會在 checkout 前 (smudge)與 add 前(clean)被執行。
接下來我們就一步一步的來設定 git filter 達成我們的目的。
設定 .gitattributes
:
首先我們打開 cmd ,進到專案的資料夾底下,新增一個 .gitattributes
(如果你本來沒有的話),並且在.gitattributes
內加上
connect_db.py filter=sensitive_filter
這段的意思是在告訴 git 說『如果遇到 connect_db.py
這個檔案,幫我套用 sensitive_filter
這個 filter 。』當然你也可以寫成 *.py
讓 git 幫你把過濾器套用到所有的 .py
檔。這邊只有單純地告訴 .gitattributes
說有個叫 sensitive_filter
的過濾器,至於這個過濾器的實作細節則必須在 .git/config
內設定。
設定 .git/config
:
接下來一樣在 cmd 輸入
git config filter.sensitive_filter.clean "python remove_sensitive_string.py"
這段是在告訴 git 說『我這邊有一個叫 sensitive_filter
的過濾器,然後在這個過濾器的 clean
階段請幫我執行 python remove_sensitive_string.py
這個指令』。當你設定完後,在接下來只要執行 git add
的指令時,git 就會將被 add 的檔案傳送給remove_sensitive_string.py
並執行我們撰寫的過濾腳本。
撰寫過濾腳本:
接下來來撰寫過濾腳本。新增remove_sensitive_string.py
,並輸入以下內容
這段程式讓 git filter 透過 sys.stdin
輸入你的程式碼,並且將敏感字詞取代為空字串,最後透過 sys.stdout.write
來輸出到 git staging area。
完成後存檔,接著你可以試試看在 cmd 輸入 git diff
,就會發現 db 連線資訊全部都變成空字串,但你的 source code 依然帶有這些 db 資訊,這樣就可以安心地進行開發工作,而不用擔心一不注意就把 db 資訊暴露到 git server 上了。
結語
Git Keyword Expansion 除了可以避免將程式傳到 staging area 上,也可以反過來透過設定 smudge 來避免 git 上的資訊傳回自己本地端的 working directory,讓自己的工作資料夾保持乾淨(?)。但這類型的指令使用上一定要謹慎,需要與團隊充分溝通後再進行設定,否則就會發生『咦我明明改了程式碼但 git 上卻沒有』之類的慘劇。
參考資料
https://pascalbugnion.net/blog/ipython-notebooks-and-git.html