![](/img/trans.png)
[英]Convert file to iso-8859-1 (ok from utf-8 but fails on us-ascii files)
[英]Switching a Git repository from ISO-8859-1 to UTF-8 encoding for source code files
我將在本周末使用快速導出將大型Mercurial項目轉換為Git。 我已經多次測試了,結果很好。
我們還希望將我們的源代碼編碼(許多德語注釋/字符串文字與Umlauts)從ISO-8859-1轉換為UTF-8(repo中的所有其他非java文件應保持原樣),並且Git遷移為我們提供了一個機會,因為每個人都需要再次克隆。 但是,我找不到一個好的方法。
git filter-tree --tree-filter ...
方法來評論SO 。 然而,雖然這似乎是理想的,但由於存儲庫的大小(大約200000次提交,18000個代碼文件),它將花費比我周末更多的時間。 我已經嘗試運行它(在一個高度優化的版本中,文件列表被分塊並且子列表並行轉換(使用GNU並行 ))直接來自具有72個內核的Linux VM上的64GB tmpfs卷,但它仍然會需要幾天...... --all
為<rev-list>
),但都只是一些過去的承諾是承諾從目前活躍的分支到達和不可到達(希望)所有當前分支的前身( branch-a branch-b branch-c --not old-tag-before-branch-abc-forked-off
as <rev-list>
)。 它仍在運行,但我擔心我不能真正相信結果,因為這似乎是一個非常糟糕的主意。 所以現在,我覺得最好的解決辦法就是堅持使用ISO-8859-1。
有沒有人有想法? 有人提到, reposurgeon可能基本上接近1使用其transcode
操作,其性能比git filter-tree --tree-filter ...
但我不知道它是如何工作的。
git filter-branch
樹過濾git filter-branch
本質上很慢。 它的工作原理是將每個提交提取到一個臨時目錄中的完整樹中,讓您更改每個文件,然后找出您更改的內容並從您留下的每個文件中進行新提交。
如果您通過快速導出/快速導入導出和導入, 那么就是轉換數據的時間:在將文件寫入內容之前,您在文件系統中將擴展的文件數據放在內存中,而不是文件系統形式。出口/進口管道。 而且, git fast-import
本身就是一個shell腳本,因此在那里插入過濾是微不足道的,而hg-fast-export
是一個Python程序,因此在那里插入過濾也很簡單。 顯而易見的地方就在這里 :只需重新編碼d
。
您可以考慮使用git filter-branch --index-filter
-as,而不是--tree-filter
(這是默認值)。 這個想法是使用--index-filter
,沒有結帳步驟(即每次迭代都沒有(重新)填充工作樹)。
所以你可以考慮為git filter-branch --index-filter
編寫一個過濾git filter-branch --index-filter
,它將使用git ls-files
東西:
調用git ls-files --cached --stage
並遍歷每個條目。
僅考慮那些具有100644
文件模式的文件 - 即普通文件。
對於每個條目運行的東西
sha1=`git show ":0:$filename" \\ | iconv -f iso8859-1 -t utf-8 \\ | git hash-object -t blob -w --stdin` git update-index --cacheinfo "10644,$sha1,$filename" --info-only
沖洗,重復。
我想要的另一種方法是從不同的角度解決問題:由git fast-export
生成並由git fast-import
消耗的流的格式是純文本¹(只需將導出器的輸出傳輸給less
或另一個尋呼機並查看你自己)。
您可以使用您喜歡的PL編寫一個過濾器來解析流,重新編碼任何data
塊。 流的組織方式使得不使用SHA-1哈希,因此您可以隨時重新編碼。 我唯一明顯的問題是data
塊沒有關於它們將在結果提交中表示哪個文件的信息(如果有的話),所以如果你的歷史記錄中有非文本文件,你可能需要采用基於猜測的方法。關於每個數據blob的內容,或者通過記住它看到的blob並決定在看到將文件名分配給(某些)blob的commit
記錄后重新編碼它們中的哪一個來使處理器更復雜。
¹用git-fast-import(1)
-run git help fast-import
。
我有完全相同的問題,解決方案基於@kostix回答使用filter-branch
的--index-filter
選項作為基礎,但是,有一些額外的改進。
git diff --name-only --staged
來檢測暫存區域的內容 git ls-files $filename
,即它不是已刪除的文件 git show ":0:$filename" | file - --brief --mime-encoding
的結果git show ":0:$filename" | file - --brief --mime-encoding
git show ":0:$filename" | file - --brief --mime-encoding
不是binary
,即它是一個文本文件,也不是UTF-8編碼的 git ls-files $filename --stage | cut -c 1-6
檢測文件模式 git ls-files $filename --stage | cut -c 1-6
這是我的bash函數的外觀:
changeencoding() {
for filename in `git diff --name-only --staged`; do
# Only if file is present, i.e., filter deletions
if [ `git ls-files $filename` ]; then
local encoding=`git show ":0:$filename" | file - --brief --mime-encoding`
if [ "$encoding" != "binary" -a "$encoding" != "utf-8" ]; then
local sha1=`git show ":0:$filename" \
| iconv --from-code=$encoding --to-code=utf-8 \
| git hash-object -t blob -w --stdin`
local mode=`git ls-files $filename --stage | cut -c 1-6`
git update-index --cacheinfo "$mode,$sha1,$filename" --info-only
fi
fi
done
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.