git履歴を書き換えて、すべてのCRLFをLFに置き換えますか?


32

プライベートGitリポジトリをwin32ボックスからUbuntuに転送します。最終的なdos2unixコミットはできますが、履歴全体を書き直したいので、一部のGit GUIはlog / diffを正しく表示します。たとえば、gitgは各CR / LFに空の行を挿入します。

回答:


25

git filter-branchそのために、--tree-filterオプションを使用して、--allブランチを指定するために使用できます。

次に例を示します(Unixタイプのテキストファイルを含む空のディレクトリで開始します:

準備:

$ hexdump -C testfile 
00000000  61 0d 0a 62 0d 0a 63 0d  0a                       |a..b..c..|
00000009

$ git init
Initialized empty Git repository in /home/seigneur/tmp/a/.git/

$ git add testfile && git commit -m "dos file checked in"
[master (root-commit) df4970f] dos file checked in
 1 files changed, 3 insertions(+), 0 deletions(-)
 create mode 100644 testfile

コマンド:

$ git filter-branch --tree-filter 'git ls-files -z | xargs -0 dos2unix' -- --all

出力:

Rewrite df4970f63e3196216d5986463f239e51eebb4014 (1/1)dos2unix: converting file testfile to Unix format ...

Ref 'refs/heads/master' was rewritten

$ hexdump -C testfile 
00000000  61 0a 62 0a 63 0a                                 |a.b.c.|
00000006

事前に完全バックアップを行うことを強くお勧めします。Linuxマシンから実行する(Windows環境に適切なシェルがセットアップされていない限り)のはおそらく簡単でしょう。

編集:変換が最初に逆転した場合。


1
ありがとう、この投稿は私を大いに助けてくれました。名前にスペースが含まれるファイルがいくつかありましたが、元のコマンドを少し変更すると修正されましたgit filter-branch --tree-filter 'git ls-files -z | xargs -0 dos2unix' -- --all。フラグ-z-0立ててgit ls-files、行末としてxargs印刷および解釈nullします。
イヴァン

DOS2UNIXコマンドに別の方法としては、gitの自体に依存することです:git filter-branch --prune-empty --tree-filter 'git add --renormalize .' -- --all
Vilmantas Baranauskas

6

マットの答えは、問題を頭の中で突き止めました。残念ながら、バージョン10.04(Lucid Lynx)以降のUbuntu Linuxでは、dos2unix / unix2dosコマンドは使用できなくなり、fromdos / todosに置き換えられました。さらに、変換コマンドの両方のセットは、バイナリファイルの存在に対してさまざまな程度の無知を持っているため、リポジトリに画像、フォントなどが含まれている場合、それらはこのプロセスによって破損します。

Linuxの「ファイル」コマンドを使用して、以下に示すようにテキストファイルのみを正しく識別および処理するバイナリファイル破損の問題の回避策を見つけることができました。以下のコマンドは--tag-name-filterオプションを使用して、既存のタグを新しく修正されたコミットに移動することで保持します。また、--forceフラグを使用して、以前にリポジトリでtree-filterを実行したことがあるイベントでコマンドが機能することを確認します。

git filter-branch --force --tree-filter 'git ls-files | xargs file | sed -n -e "/.*: .*text.*/s/\(.*\): .*/\1/p" | xargs fromdos' --tag-name-filter cat -- --all

3

また、追加のツール(「fromdos」、「dos2unix」など)なし:

git filter-branch --force --tree-filter 'git ls-files | xargs file | sed -n -e "/.*: .*text.*/s/\(.*\): .*/\1/p" | xargs -0 sed -i"" -e "s/"$(printf "\015")"$//"' --tag-name-filter cat -- --all

クロスプラットフォーム(OS X、FreeBSD、Linux)便利なアナログ「fromdos」、「dos2unix」:

sed -i'' -e 's/'"$(printf '\015')"'$//'

おそらく便利な「unix2dos」:

sed -i '' -e 's|$|'"`printf '\015'`"'|' file.name

あなたが何をしているのか絶対にわからない場合、現在のディレクトリ「。」内のすべてのファイルから「/ r」を削除するために、この単純なインラインコマンドを使用できます。

find . -type f -exec sed -i'' -e 's/'"$(printf '\015')"'$//' {} \;

1
むしろ\ rのみを削除するのではなく、\ r \ nを\ nに変更します
-xdevs23

対応するsed呼び出しはより短い呼び出しに置き換えることができると思いますsed -n -e "s/\(.*\): .*text.*/\1/p"
。– dma_k
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.