[Git] gitconfig 活用しよう

:::note info
この記事は [Wano Group Advent Calendar 2024](https://qiita.com/advent-calendar/2024/wano-group) の 1日目の記事となります。
:::

## 自己紹介
TuneCore Japanでフルスタックエンジニアをしている@_tachi_です。
Go/Perl/React を使って日々開発をしております。


## 概要
皆さんは `gitconfig` をどれくらい活用しているでしょうか？
私はどこでも使いたい git の共通設定は `dotfiles` として管理しています。

私はこれくらいの設定で使っているよ〜という内容を一部共有したいと思います。

中身だけ知りたい！という方は 👉 [(公開) gitconfig](##-(共有)-gitconfig)

## そもそも自分の設定はどこに置いておく？
自分の `gitconfig` の設定を管理する場合は、`$XDG_CONFIG_HOME/git/config` にセットできます。

:::note info
[XDG Base Directory](https://wiki.archlinux.jp/index.php/XDG_Base_Directory) についてはこちらをご確認ください。
:::

https://wiki.archlinux.jp/index.php/XDG_Base_Directory

`man git` でマニュアルを開き、`/XDG` で検索すれば設定ファイルの読み込みについてのマニュアルがヒットします。

```text:man git
GIT_CONFIG_GLOBAL, GIT_CONFIG_SYSTEM
   Take the configuration from the given files instead from global or system-level configuration files. If GIT_CONFIG_SYSTEM is set, the system config file
   defined at build time (usually /etc/gitconfig) will not be read. Likewise, if GIT_CONFIG_GLOBAL is set, neither $HOME/.gitconfig nor
   $XDG_CONFIG_HOME/git/config will be read. Can be set to /dev/null to skip reading configuration files of the respective level.
```

`gitignore` の設定も `$XDG_CONFIG_HOME/git/ignore` で管理できます。
どこでも無視したいファイル(`.DS_store` など)はあらかじめ設定してしまうと良いでしょう。

```text:man gitignore
   •   Patterns which a user wants Git to ignore in all situations (e.g., backup or temporary files generated by the user’s editor of choice) generally go into a
       file specified by core.excludesFile in the user’s ~/.gitconfig. Its default value is $XDG_CONFIG_HOME/git/ignore. If $XDG_CONFIG_HOME is either not set or
       empty, $HOME/.config/git/ignore is used instead.
```

設定を終えれば大体の人は以下のようになります。
`config.local` については後ほど説明します。

```terminal: ディレクトリの構成
~
% ls -1 .config/git/
config
config.local
ignore
```

## [core] （Windowsの罠）改行コードは CRLF or LF に合わせよう
[書式設定と空白文字](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#_%E6%9B%B8%E5%BC%8F%E8%A8%AD%E5%AE%9A%E3%81%A8%E7%A9%BA%E7%99%BD%E6%96%87%E5%AD%97)
Windows と Mac 及び Linux では改行コードが異なりますので、どこに合わせるか設定をしておいた方が良いです。
大体は `LF` に合わせたいですから `CRLF` が検知されたら自動で `LF` に変換されるような設定を入れています。

```config:config
[core]
  autocrlf = input
```

## [include] 持ち運びたい設定と会社の設定は別で管理しよう
`[include]` では別の `gitconfig` を読み込むことができます。
私の場合は、`config,ignore` を `dotfiles` の管理対象に、 `config.local`は `dotfiles` で管理せずローカルに置くという管理をしています。
ローカルで持ってきおきたい設定として考えられるものは `user` や `email` の設定がありますね。
会社で使う設定は自分のリポジトリに置きたくないですから、切り出して管理します。

```terminal:layout
./config
└── git
    ├── config       //持ち運ぶ設定
    ├── config.local //端末(環境)固有の設定
    └── ignore       //持ち運ぶ設定
```

```config:config
[include]
  path=config.local
```

```config:config.local
[user]
  name = tacchi
  email = tacchi@mail.hoge.com
```

## [difftastic] 外部toolの力を借りて差分を見やすくしよう
標準機能だけで差分を確認するのは、いくら diff オプションが充実すれど読みにくいですね。
標準であることに強いこだわりがないなら綺麗に差分を表示してくれるツールに頼った方がストレスを感じないです。
私は [difftastic](https://github.com/Wilfred/difftastic#can-difftastic-do-merges) という差分表示をサポートしてくれるツールを利用しています。
[公式マニュアル](https://difftastic.wilfred.me.uk/introduction.html) に沿った設定を行えばOKです。

どんな風に差分が見えるようになるのかざっくり紹介したいと思います。

元々以下のファイルがあったとします。
```python:before.py
def add1(a: int, b: int) -> int:
    return a + b

assert add1(1, 2), 3

```

以下のような変更を加えました。
```python:after.py
def add(a: int, b: int) -> int:
    return a + b

def minus(a: int, b: int) -> int:
    return a - b

assert add(1, 2), 3

assert minus(2, 1), 1

```

`git diff` を実行すると以下のようにターミナルに表示されます。
差分が小さいので読みにくい訳ではないのですが編集した本人以外が見たら読みにくいよね、というのは diff あるあるです。

```diff:git diff
-def add1(a: int, b: int) -> int:
+def add(a: int, b: int) -> int:
     return a + b

-assert add1(1, 2), 3
+def minus(a: int, b: int) -> int:
+    return a - b
+
+assert add(1, 2), 3
+
+assert minus(2, 1), 1
```

difftastic を利用すると、まるでエディタで開いた時のような見やすい形式でターミナルに差分を表示してくれます。
こちらはスクショです。
![スクリーンショット 2024-11-27 10.04.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628131/3bf3bde2-dcbf-225a-f7f6-a5d5057a57b2.png)


## [alias] よく使うものはお手軽に
`[alias]` に登録したら、その時点で `git <alias>` で呼び出せます。
`.bashrc` や `.zshrc` を編集した時のように再読み込みの必要はありません。
特に私が使うものは `git oneline`, `git (sw|sc|bb)`, `git (dl|ds|dft)` あたりです。
日々増えているので来年になったらもっと効率化するような何かが増えているかもしれません。

```config:config
[alias]
  unstage = reset HEAD --

  graph = log --graph --pretty=format:'%C(auto)%h %C(auto)[%cs] %C(red)%<(10,trunc)%an %C(white)%s %C(green)%d'
  oneline = log --oneline --pretty=format:'%C(auto)%h %C(auto)[%cs] %C(red)%an %C(white)%s %C(green)%d'

  status-short = status -s

  #search branch including specified commit hash
  contains = branch --contains
  contains-all = branch -a --contains

  stash-all = stash save -ku

  #first commit
  first-commit = commit --allow-empty -m 'first commit'
  #meld current changes into previous commit
  meld = commit --amend --no-edit

  #change branch
  sw = switch
  #create branch
  sc = switch -c
  #back previous branch
  bb = switch -
  # `git log` with patches shown with difftastic.
  dl = -c diff.external=difft log -p --ext-diff
  # Show the most recent commit with difftastic.
  ds = -c diff.external=difft show --ext-diff
  # `git diff` with difftastic.
  dft = -c diff.external=difft diff
```

## (共有) gitconfig

以下、2024年時点の設定内容を載せておくので、👇だけ見たいという方はこちらとなります。

```config:config
[core]
  autocrlf = false

[push]
  default = current

[pull]
  ff = only

[merge]
  tool = nvimdiff
  guitools = nvimdiff
  conflictStyle = zdiff3
  ff = false

[mergetool]
  keepBackup = false

[diff]
  diffAlgorithm = histogram

[commit]
  verbose = true

[blame]
  coloring = highlightRecent
  date = short

[alias]
  unstage = reset HEAD --

  graph = log --graph --pretty=format:'%C(auto)%h %C(auto)[%cs] %C(red)%<(10,trunc)%an %C(white)%s %C(green)%d'
  oneline = log --oneline --pretty=format:'%C(auto)%h %C(auto)[%cs] %C(red)%an %C(white)%s %C(green)%d'

  status-short = status -s

  #search branch including specified commit hash
  contains = branch --contains
  contains-all = branch -a --contains

  stash-all = stash save -ku

  #first commit
  first-commit = commit --allow-empty -m 'first commit'
  #meld current changes into previous commit
  meld = commit --amend --no-edit

  #change branch
  sw = switch
  #create branch
  sc = switch -c
  #back previous branch
  bb = switch -
  # `git log` with patches shown with difftastic.
  dl = -c diff.external=difft log -p --ext-diff
  # Show the most recent commit with difftastic.
  ds = -c diff.external=difft show --ext-diff
  # `git diff` with difftastic.
  dft = -c diff.external=difft diff

[include]
  path=config.local
```

## 人材募集
現在 TuneCore Japan ではエンジニア募集をしています。
興味のある方は下記を参照してください！

https://herp.careers/v1/wano