最近因為幫忙重新整理 git repository, 所以有機會接觸 git filter-branch, 過去因為 policy 沒有定義好, 所以大家都將 binary 檔也加進 repository, 造成整個 repository 很肥大, 要 checkout 時也必須要等很久, 所以我的任務就是把這些 binary 檔拔掉, 改成用 md5 or sha1 檔案代替, 如果真的需要用到時, 再去另外一個 http server 下載.
http://www.kernel.org/pub/software/scm/git/docs/git-filter-branch.html
假設整個 repository 有 1000 個版本, 那filter-branch 執行的過程, 其實就是依序把這些版本 checkout, 然後執行你指定的指令來改變檔案的內容, 或是甚至新增/刪除檔案, 之後再把修改過的檔案 commit 進去新的 repository. 所以執行完之後, 整個 repository 中每一筆項目的 SHA ID 都會改變, 是個很暴力的作法, 但也因為很暴力, 所以基本上你想要做什麼事應該都可以達成.
Filter
filter-branch 提供了許多不同 filter, 可以幫助你在正確的時間點執行指令--env-filter
幫助你修改 author name 或是 author e-mail, 可以參考以下網址提供的 scripthttps://help.github.com/articles/changing-author-info
--tree-filter
幫助你在每一個版本去修改檔案的內容, 新增/刪除檔案, 最常使用的應該也是這個, 以我自己的例子來說, 我會寫一個像以下的 script 把大檔案轉成 sha1 檔#!/bin/bash function transform { file=$1 sha1_name=$file.sha1 if [ -f /tmp/git/$file ]; then rm -f $file cp /tmp/git/$sha1_name $sha1_name else sha1sum $file > $sha1_name mv $file /tmp/git cp $sha1_name /tmp/git fi } pushd ./bigfile for file in *.tgz *.zip; do if [ ! -f $file ]; then continue; fi transform $file popd
--index-filter
這個其實是 --tree-filter 的快速版本, 如果你沒有要改變檔案的內容, 只是單純改變 repository 的 history, 那可以使用這個, 因為他不會真的 checkout 檔案, 速度上快很多, 下面兩個網址都有示範, 最常用的功能就是把某一個特定的檔案永久的從 repository 中刪除.https://help.github.com/articles/remove-sensitive-data
http://dalibornasevic.com/posts/2-permanently-remove-files-and-folders-from-a-git-repository
--msg-filter
這個是用來改變 commit message 的內容, 原來的內容會介由 standard input 輸入, 而你輸出到 standard output 的內容就會作為新的 commit message.# 舉例來說, 因為 cat 就不會改變內容, 所以 commit message 完全不變 $ git filter-branch --msg-filter cat # tac 會把內容全部反過來 $ git filter-branch --msg-filter tac
--tag-name-filter
用來改變 tag name, 如果該版本有加上 tag, 那當 checkout 這個版本時, 就會乎叫你指定的指令, 原來的內容會介由 standard input 輸入, 而你輸出到 standard output 的內容就會作為新的 tag name--subdirectory-filter
把某一個 folder 下的 commit 獨立出來變成一個新的 repository, 如果當你的專案越來越大時, 你可能會想把某個資料夾獨立出來變成一個新專案, 那這個功能就很好用http://gugod.org/2012/07/split-a-git-repository/
沒有留言:
張貼留言