Git for Windowsでautocrlfの設定を間違えちゃった時の対応

この記事は ZOZOテクノロジーズ #5 Advent Calendar 2019 16日目の記事です。
昨日は @meganekids さんによる「エンジニアとプロジェクトマネージャー向けのAdobe XD勉強会で意識した4つのこと」でした。
別職種の人とのコミュニケーションを円滑にするための知識の土台作りはとても大事だと思うので、アフターケアを含め取り組む姿勢がとても素敵だと思いました。

本記事はWindowsではまりがちなgitの改行コード自動変換機能のお話です。

# 背景
私が所属しているMA(マーケティングオートメーション)チームではWindows ServerとLinuxのサーバを両方使って開発をしています。
Windowsでしか動かないVBScriptやLinuxでよく使うシェルスクリプトを両方扱っており、文字コードや改行コードに配慮しないと問題が発生してしまう、とてもエキサイティングな職場です。
(文字コードについてはこちらの記事に書いてますので興味があればどうぞ > [Qiitaの記事](https://qiita.com/e_tyubo/items/09c7144b90c70b164ca6))

改行コードについてはgitにautocrlfという自動変換してくれる機能があり、上手く使えば便利です。
しかし、この機能がONになっていると、commitログとファイルシステムが認識している実態に乖離が生じてデプロイ結果が期待と異なるケースがありえます。

Git for Windowsは親切なことに、インストール時にautocrlfの設定を任意で選択することができます。

<img width="497" alt="スクリーンショット 2019-12-15 16.38.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13766/a5569edb-c05b-5542-12e7-7f72d16a8880.png">

一番上の設定にすると、`autocrlf=true`という設定になり、改行コードの自動変換が有効になります。
ここで選択できるのは良いのですが、その後悲しいことにGUIでは設定変更ができません(やり方あれば教えて欲しい)。

間違えてautocrlfがtrueになってしまったら、gitのコマンドを駆使してゴニョゴニョする必要があったので、そのときの対処法をまとめようと思います。操作自体は簡単なので、周辺知識の整理的な意味合いが強いです。

# 環境
この記事はWindows10を使っていてかつ、gitの環境を[Git for Windows](https://gitforwindows.org/)でインストールした環境を想定しています。
Git for Windowsのバージョンによる差異は後ほど記述しますが
v2.19(私が最初インストールしたもの)とv2.24(記事作成時最新)が登場します。

# autocrlf
改行コードは利用するOSによって標準で利用するものが異なります。
特にWindowsではCRLF, MacではLFが標準で利用されます。

サーバをLinuxOS上で動かしていれば、何かしらのシェルスクリプトを利用することはよくあると思いますが、
シェルスクリプトの改行コードがCRLFになっていると困るため、gitの設定にautocrlfという改行コードを自動変換する機能があります。

これはgitでcommitした時とcheckoutした時に自動的に改行コードを変換する仕組みです。
要は作業中の改行コードとcommitログとして記録される改行コードをシステム的に固定する機能のことです。

基本的にWindows Serverを使っているような環境(CRLFが必要な環境)で開発しているのであれば、autocrlfはfalseにすべきだと思います。
autocrlf=trueは最終的にgitに記録する改行コードをLFに固定化する時に使う設定なので、LF以外を駆逐するときに利用しましょう。

下記のgitのドキュメントのcore.autocrlfの項目に記載があるので、そちらを参照してください。
https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA-Git-%E3%81%AE%E8%A8%AD%E5%AE%9A

gitの設定は`git config`というコマンドを使って変更が可能ですが、その際環境が3つある点に注意が必要です。

- system: gitのシステム全体に適用される設定
- global: ホームディレクトリ直下の設定ファイルを見るため、ユーザ単位で全適用される設定
- local: gitで管理しているレポジトリの.git配下の設定ファイルを見る、レポジトリ単位の設定

それぞれ --system, --global, --local とオプションを指定して利用できます。

現在gitのconfigがどのファイルによって何に設定されているかは下記のコマンドでみるとわかりやすいです。

```bash
git config --show-origin core.autocrlf
```

`--show-origin`をつけることで、どのファイルによる設定されているかがわかります。

ここが重要なポイントですが、gitの設定ファイルは
local > global > systemの順で優先されます。

個別に設定した内容は優先して適用されるようです。

git config --helpで出力されるドキュメントの中には下記のように書いてます。優先度については特に記述はないですが、一応載せておきます。

```
When reading, the values are read from the system, global and repository local configuration files by default, and options --system, --global, --local and --file <filename> can be used to tell the command to read from only that location (see the section called "FILES").
```

# Git for Windowsによる自動設定
ここで実際にインストール時の設定がどのように反映されるのか見て行きます。

Git for Windowsはインストール時にautocrlfの設定を選ぶことができます。
この時しっかり理解して設定していればきっと問題は起きないでしょう。

もう一度インストール時の画面です。
<img width="497" alt="スクリーンショット 2019-12-15 16.38.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13766/d6f8d6b2-9e7c-1b75-1313-1637652bf06b.png">

ここで一番上の選択肢を選ぶと、autocrlf=trueな環境のgitが完成します。

設定内容を確認します。

インストール直後はこうなります。

```bash:v2.24
$ git config --show-origin core.autocrlf
file:C:/Program Files/Git/etc/gitconfig true
```

```bash:v2.19
$ git config --show-origin core.autocrlf
file:"C:\\ProgramData/Git/config"       true
```

バージョンによって設定ファイルは異なりますが、このような設定になります。

Git for windowsのリリースノートによると v2.23へのアップデートよって設定ファイルの配置場所が変わったようです。

```
Note! As a consequence of making git config --system work as expected, the location of the system config is now C:\Program Files\Git\etc\gitconfig (no longer split between C:\Program Files\Git\mingw64\etc\gitconfig and C:\ProgramData\Git\config), and likewise the location of the system gitattributes is now C:\Program Files\Git\etc\gitattributes (no longer C:\Program Files\Git\mingw64\etc\gitattributes). Any manual modifications to C:\ProgramData\Git\config need to be ported manually.
```

# 設定の変更方法

環境毎に説明します。

## local
とにかくこのレポジトリだけ対応したい。ということであれば下記の方法でlocalの設定を更新します。

```bash
git config --local core.autocrlf false
```

すると、設定値が下記のようのなります

```bash
$ git config --show-origin core.autocrlf
file:.git/config        false
```

これにて特定レポジトリに対する設定は完了です。
一番手軽で、影響範囲が少ないです。

## global
基本的にautocrlfがfalseでよければこちらの方がまだ良いでしょう。

```bash
git config --global core.autocrlf false
```

--localに設定されていなければ、下記の表示になります。

```bash
$ git config --show-origin core.autocrlf
file:C:/Users/{username}/.gitconfig false
```

## system
根本的に変えたいならこちらの設定を変えましょう。こっちを変えたほうが安心です。
しかし、こちらは権限の問題があるので、Git Bashを「管理者として実行」で起動させてからコマンドを実行する必要があります。

```bash
git config --system core.autocrlf false
```

その結果、v2.19ではなぜか別ファイルが作られます。なんでやねん。

```bash
$ git config --show-origin core.autocrlf
file:C:/Program Files/Git/mingw64/etc/gitconfig false
```

`C:\\ProgramData/Git/config`には true で設定されていますが、`C:/Program Files/Git/mingw64/etc/gitconfig`のfalseが優先されるようです。

こうなるなら`C:\\ProgramData/Git/config`を手で書き換えた方が気分がいいですね。

ただ、v2.24では同じファイルが上書きされたので、新しいの使った方が綺麗に修正できます。

Git for Windowsが古い場合はv2.23以降のバージョンにアップデートして、その時autocrlfをfalseにする設定でインストールするが綺麗かもしれません。

## 再インストール

これでもいいです。
<img width="498" alt="スクリーンショット 2019-12-15 16.38.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13766/a3cae570-c85e-e650-e7f4-1cdf290004a4.png">

一番下のラジオボタンを選べば、autocrlf=falseの状態でsystemのconfigが作られます。

# 最後に
今回もWindows環境と向き合う記事でした。バージョンの違いによる挙動の違いは結構混乱の元だと思うので、その辺を整理できてよかったです。
普段Macを使っているからという理由で億劫になりがちな問題ですが、CRLFな改行コードが必要な世界もあるということを理解しておくことは、開発をする上で大事なことだと思うのでこれからも立ち向かっていきたいですね。

明日は @satto_sann による記事なので、そちらもぜひご覧ください〜