.gitignoreをコマンド一つで自動生成する

## はじめに

手作業で無視するべきファイルを調査して書いたり、前のプロジェクトからコピーしたりするのが面倒くさい `.gitignore` ファイル。

この記事ではそんな `.gitignore` ファイルをWebサイト **[gitignore.io][gi]** から生成する方法と、さらにはコマンドを1度実行するだけで生成する方法を紹介します。

|Environment        |Version
|---                |---
|Windows10 Pro x64  |1803
|git                |2.19.1.windows.1


## [gitignore.io][gi]

キーワードを入力して `Create` ボタンを押せば、`.gitignore` の雛形を表示してくれるWebサイト。
この表示されたテキストを各プロジェクト（リポジトリ）の `.gitignore` にコピー＆ペーストすればできあがり。

![gitignore.io](https://qiita-image-store.s3.amazonaws.com/0/238841/fccefe6d-d6d4-3975-02dd-8b815c3f5ecb.png "gitignore.io website.")


使い方は上記の通りなんですが、APIも公開してくれているため下記のようにコマンドラインからも利用できます。

"ブラウザでWebページを開いて～"という動作が不要になるのでさらに快適。


## `.gitignore` 生成コマンドを作成する

[gitignore.io][gi] のAPIにアクセスするためのコマンドを作成します。

といっても [READMEに書かれてある通り][cli] に実行すればOKです。

各環境下でのコマンド作成方法が記述されていますが、`git` のエイリアス機能を使う方法がおすすめです。

> ```bash:git-bash
> $ git config --global alias.ignore '!gi() { curl -L -s https://www.gitignore.io/api/$@ ;}; gi'
> ```
>
> <https://github.com/joeblau/gitignore.io#git>

上記のコマンド実行後、 `git ignore` コマンドとして [gitignore.io][gi] から取得した `.gitignore` の内容を標準出力することができます。

`git ignore` コマンドにおける引数（各種プログラム言語やIDEのキーワード）の区切りはスペースではなく **カンマ（ `,` ）** になります。
むしろスペースが混ざると上手く動作しませんのでご注意ください。

```bash:実行例：git-bash
# 標準出力に表示
$ git ignore unity,visualstudiocode

# .gitignoreに出力（追記）
$ git ignore unity,visualstudiocode >> .gitignore
```


### 毎回同じキーワードを入力するのがしんどい

例えば `visualstudiocode` や `windows` といった自分の環境で、いつも決まりきったキーワードを入力している場合。

このような個々人の開発環境に依存する無視ファイルの設定は、グローバルな `.gitignore`（`$XDG_CONFIG_HOME/git/ignore`）に記述してしまうのがおすすめです。

1. `$XDG_CONFIG_HOME/git/ignore` ファイルのパス指定

    ```bash:git-bash
    git config --global core.excludesfile $HOME/.config/git/ignore
    ```

1. `$XDG_CONFIG_HOME/git/ignore` ファイルの作成

    ```bash:git-bash
    $ mkdir -p $HOME/.config/git

    # VS Code と Windows用の設定
    $ git ignore visualstudiocode,windows > $HOME/.config/git/ignore
    ```

一度 `$XDG_CONFIG_HOME/git/ignore` を設定すればローカル上のすべてのリポジトリに適用される。

`.gitignore` 設定の優先度はリポジトリのものが優先されるため、特定のリポジトリ下では追跡するようにもできる。

```shell:リポジトリ下の.gitignoreファイル
# 行頭に ! をつけると無視されなくなる
!*.lnk
```

---

以上でずっと簡単に `.gitignore` ファイルを生成できるようになったと思います。

が、より使いやすくするべく `git ignore` コマンドのアレンジに挑戦しました。


## 黒魔術完全に理解した

シェルスクリプト完全ニ理解シタ。

現在は `git ignore` コマンドを次のように上書きし、エラー発生時にはエラーメッセージのみ表示するようにしてます。

```bash:git-bash
git config --global alias.ignore '!gicheck() { if grep -sq "ERROR: " <<< "$*" ; then grep "ERROR: " <<< "$*" ; else echo -e "$*" ; fi;}; gi() { curl -LsS https://www.gitignore.io/api/$@ | sed -r -e "s@.*(ERROR: )(\w+)@\1\x1b[31;40;1m\2\x1b[m@gi"| gicheck "$(cat -)" ;}; gi'
```

```bash:実行例：git-bash
# .gitignoreテンプレートを表示
$ git ignore unity

# エラー発生時
$ git ignore javascript

ERROR: javascript is undefined. Use list command to see defined gitignore types !!#
```

以下これにたどり着くまでの流れ。

1. エラーメッセージを強調したい

    エラーメッセージ `#!! ERROR: <keyword> is undefined. ~` に対して、エラー原因であるキーワードを赤文字で強調させる。

    ```bash:git-bash
    git config --global alias.ignore '!gi() { curl -L -s https://www.gitignore.io/api/$@ | sed -r -e "s@.*(ERROR: )(\w+)@\1\x1b[31;40;1m\2\x1b[m@gi" ;}; gi'
    ```
    * `sed` コマンドを使ってエラー原因のキーワードを抽出、色変更
    * `\x1b[31;40;1m` 以降は赤色になり `\x1b[m` 以降はデフォルト色に戻る
       * ANSIエスケープシーケンスを `\e` で指定すると `sed` コマンドでは期待通りの動作をしてくれなかった

1. エラー発生をもっとわかりやすくしたい（現行）

    エラーが発生した場合、そのときの出力を `.gitignore` に使うことはないと考えられる。
    よってエラー時の出力はエラーメッセージのみにし、ひと目でエラーだと判断できるようにする。

    グローバル変数を作りたくないので関数を増やし、引数を表す変数（`$@` や `$*`）を使うことで対処してます。

    ```bash:git-bash
    git config --global alias.ignore '!gicheck() { if grep -sq "ERROR: " <<< "$*" ; then grep "ERROR: " <<< "$*" ; else echo -e "$*" ; fi;}; gi() { curl -LsS https://www.gitignore.io/api/$@ | sed -r -e "s@.*(ERROR: )(\w+)@\1\x1b[31;40;1m\2\x1b[m@gi"| gicheck "$(cat -)" ;}; gi'
    ```

    ```bash:実行例：git-bash
    $ git ignore javascript

    ERROR: javascript is undefined. Use list command to see defined gitignore types !!#
    ```
    * `gicheck()` 関数を追加、エラーメッセージ有る無しで処理分岐
    * 変数・標準入力が改行コードを含むため、変数展開（`""` で囲む）しないと期待する動作をしてくれない


## おわりに

黒魔術コワイ。気づいたら夜が明けてました……。
`git` も使いこなそうとすると知らない機能がいっぱい出てきてコワイですね。

うっかり消費した時間が無駄でないよう、この記事が誰かの役に立つことを祈ってます！


## 参考

* [gitignore.io - Create useful .gitignore files for your project][gi]
* [.gitignoreを自動的に作る（gibo, gitignore.io を使う）][link-1]
* [複数人で開発するとき git 管理から外す指定方法 3 パターンの使い分け][gitignore]

黒魔術

* [シェルの入出力制御あれこれ][shell-1]
* [if 文と test コマンド | UNIX & Linux コマンド・シェルスクリプト リファレンス][shell-2]
* [簡素なif文は一行で書く | 半径5メートル][shell-3]
* [シェルスクリプトの出力に色をつけたい！][shell-4]
* [catで標準入力と連結 - ボクノス][shell-5]
* [bashで複数行の文字列の代入と、ヒアドキュメントを使わずに変数に格納する方法 - それマグで！][shell-6]
* [初心者向けシェルスクリプトの基本コマンドの紹介][shell-7]

[gi]:https://www.gitignore.io/
[cli]:https://github.com/joeblau/gitignore.io#install-command-line
[gitignore]:https://qiita.com/qurage/items/0333a210c151324064e8
[link-1]:https://qiita.com/yumechi/items/b7932f5b31613a1f50f9
[shell-1]:https://qiita.com/tag1216/items/7ce35b7c27d371165e56
[shell-2]:https://shellscript.sunone.me/if_and_test.html
[shell-3]:http://d.hatena.ne.jp/srkzhr/20080201/1201833497
[shell-4]:https://qiita.com/dojineko/items/49aa30018bb721b0b4a9
[shell-5]:http://d.hatena.ne.jp/tanakaBox/20070806/1186341811
[shell-6]:http://takuya-1st.hatenablog.jp/entry/2017/03/22/144700
[shell-7]:https://qiita.com/zayarwinttun/items/0dae4cb66d8f4bd2a337