2017/03/08

git repository 中の CRLF を LF に一括変換する

2018/04/12 追記
  • スペースを含むファイルがあると失敗する問題があったので修正しました
  • `.gitattributes` 等の取り扱いについて追記しました

以下のサイトを参考に自分用にちょっとアレンジ。特にバイナリを変換しちゃいそうになって危なかったので。

CRLF を使っているファイルを確認する

$ git grep --cached -l -I $'\r$'
contain_crlf.txt

autocrlf=true/input に設定されている場合、ワークツリーのファイルとリポジトリの改行コードが一致していない可能性があるので、--cached を指定します。 また、-I を指定することでバイナリファイルを除外します1

一時的に autocrlf を false にする

$ git config core.autocrlf false

ワークツリーを更新する

.git ディレクトリを除いて消去し2、チェックアウトしなおします。

$ ls -A --color=never -I .git | xargs -d '\n' rm -rf
$ git checkout -- .

--color=never はフェイルセーフです。

また、xargs-d '\n' でスペースを含んだファイルも処理できるようになります3。 Linux 以外4の処理系の場合は少しオプションが異なるようです。詳細は参考リンクを参照してください。

参考

確認する

--cached をはずして grep をかけ、ワークツリーにレポジトリが映されていることを確認します。

$ git grep -l -I $'\r$'
contain_crlf.txt

改行コードを変換

今回は nkf を使いましたが、変換はお好きなツールでどうぞ。

$ git grep -l -I $'\r$' | xargs -d '\n' nkf -Lu --overwrite

Windows 用 nkf はこちら

コミットして確認

コミットして5 --cached つきの grep をかけます。 何も表示されなかったら成功。

$ git commit -a
$ git grep --cached -l -I $'\r$'

autocrlf を元に戻す(必要なら)

今後も CRLF が混在してしまうような環境であるなら、設定しておいた方が良いでしょう。 true もしくは input に戻します。

$ git config core.autocrlf input

ワークツリーを更新する(必要なら)

この時点でワークツリー内の改行コードは LF で統一されています。 お馬鹿な IDE のために CRLF に戻したい場合はもう一度、ワークツリーを更新する必要があります。 この際、core.autocrlf=true でないと更新時に改行コードの変換が行われないので注意が必要です。

$ git config core.autocrlf
true
$ ls -A --color=never -I .git | xargs -d '\n' rm -rf
$ git checkout -- .
$ git grep -l -I $'\r$'
contain_crlf.txt

.gitattributes を使うことも検討してみる

お馬鹿な IDE 特定のツールを使わなければならない環境等で、必ず改行コードを CRLF で扱いたい(でも、レポジトリは LF で統一したい)という場合、.gitattributes6 の使用を検討してみるのも手です。

以下のような .gitattributes ファイルを用意すると、そのディレクトリ以下(再帰的に検索される様子)の対象のファイルは CRLF でチェックアウトされ、LF でコミットされます。

.gitattributres
1
2
*.c text eol=crlf
*.h text eol=crlf

参考

.gitattributesで改行コードの扱いを制御する - Qiita

  1. これを忘れて危うくバイナリ壊しちゃうところでした… 
  2. autocrlf を変更した際、設定を反映させてチェックアウトしなおすには、ワークツリーのファイルを消すしかないようです 
  3. 正確には、分割文字を改行のみに限定している 
  4. GNU xargs 以外 
  5. 良い子は -a オプションを安易に使ってはいけません :-p 
  6. attributes と複数形なので注意 
?

0 件のコメント: