【初級者向け】ターミナル（zsh）にgitのブランチ名表示＆補完機能を公式ドキュメントをじっくり読み解いて実装

※2022年から技術系の記事は[個人ブログ](https://yamaday0u.net/category/programmer/)に投稿しております。ぜひこちらもご覧ください→[yamaday0u Blog](https://yamaday0u.net/category/programmer/)
## はじめに
やまだゆう（[@yamaday0u](https://twitter.com/yamaday0u)）です。
今回は、ターミナル（zsh）でgitを操作するときにとても便利な以下の機能を実装します。

- ブランチ名の表示
- Tab補完

## 目標
自身のターミナルで以下のようにブランチ名の表示とTabキーによる補完機能を実装することを目標とします。
![スクリーンショット 2021-09-07 22.36.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849306/7a14d3c2-fa6b-44ba-8d2b-29e316be0fd8.png)

## チャレンジ
原典・一次情報から学ぶ習慣を身につけるべく、なるべく公式ドキュメントを参考にしていきます。
手っ取り早く実装したい場合は以下の記事を読んでください。大変わかりやすい記事です。
[【zsh】絶対やるべき！ターミナルでgitのブランチ名を表示&補完【git-prompt / git-completion】（Qiita）](https://qiita.com/mikan3rd/items/d41a8ca26523f950ea9d)

## gitのドキュメント
ブランチ名の表示とTab補完は、それぞれgitの公式ドキュメントの中の`git-prompt`と`git-completion`に実装方法が記載されているので、この指示に従って実装します。

[git/contrib/completion/git-prompt.sh](https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh)、
[git/contrib/completion/git-completion.zsh](https://github.com/git/git/blob/master/contrib/completion/git-completion.zsh)のコメントアウト部分の説明をぜひ1度ご覧ください！

## ブランチ名の表示機能を実装（git-prompt）
[git/contrib/completion/git-prompt.sh](https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh)の指示を1つずつ確認していきます。
### 手順1：git-prompt.shファイルをコピー

```:git/contrib/completion/git-prompt.sh
#    1) Copy this file to somewhere (e.g. ~/.git-prompt.sh).

       ※訳：このファイル（git-prompt.sh）をどこかにコピーしてください。
```

今回はzshフォルダを作成して、このフォルダ下にファイルをコピーします。

```zsh:ターミナル
% mkdir ~/.zsh
% cd ~/.zsh

% curl -o git-prompt.sh https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh
```

コピーするURL`https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh`は以下の「Raw」をクリックすることで開かれるページです。
![スクリーンショット 2021-09-09 22.38.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849306/8d043175-7225-c67f-2442-8a9fce554979.png)

`curl -o ファイル名 URL`コマンドで、URLから取得したソースコードを指定した名前のファイルに出力して保存してくれます。
参考：[curl公式サイト](https://curl.se/)、[curl コマンド（hydroculのメモ）](https://hydrocul.github.io/wiki/commands/curl.html)

ちなみにcurlという名前はclient for urlから来ているらしいです。（[IT用語辞典 e-Words](https://e-words.jp/w/CURL.html)）

### 手順2：.zshrcファイルに設定を追記
```:git/contrib/completion/git-prompt.sh
#    2) Add the following line to your .bashrc/.zshrc:
#        source ~/.git-prompt.sh

       ※訳：次のコードを.bashrcか.zshrcファイルに追記してください。
```

今回はzshを使用していることを前提としているので、.zshrcファイルに設定を追記します。
ちなみに.zshrcファイルのrcはRun Commandの略だそうです。（[【.zshrc解説】コピペで簡単zshカスタマイズ【設定方法】（Suwaru blog）](https://suwaru.tokyo/%e3%80%90-zshrc%e8%a7%a3%e8%aa%ac%e3%80%91%e3%82%b3%e3%83%94%e3%83%9a%e3%81%a7%e7%b0%a1%e5%8d%98zsh%e3%82%ab%e3%82%b9%e3%82%bf%e3%83%9e%e3%82%a4%e3%82%ba%e3%80%90%e8%a8%ad%e5%ae%9a%e6%96%b9%e6%b3%95/)）

```:~/.zshrc
source ~/.zsh/git-prompt.sh
```
このコードの追記により、git-promptを読み込みます。


### 手順3：表示形式の設定

```:git/contrib/completion/git-prompt.sh
#    3a) Change your PS1 to call __git_ps1 as
#        command-substitution:
#        Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
#        ZSH:  setopt PROMPT_SUBST ; PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
#        the optional argument will be used as format string.
```

.zshrcファイルに以下のように追記します。

```:~/.zshrc
# プロンプトのオプション表示設定
GIT_PS1_SHOWDIRTYSTATE=true
GIT_PS1_SHOWSTASHSTATE=true
GIT_PS1_SHOWUNTRACKEDFILES=true
GIT_PS1_SHOWUPSTREAM=auto

# プロンプトの表示設定(好きなようにカスタマイズ可)
setopt PROMPT_SUBST ; PS1='%F{green}%n@%m%f: %F{cyan}%~%f %F{red}$(__git_ps1 "(%s)")%f
\$ '
```

プロンプトのオプション表示設定はの説明は以下の通りです。

- GIT_PS1_SHOWDIRTYSTATE（ファイル変更の有無）

ステージング（git add）されている変更があればブランチ名の横に"+"が表示され、ステージングされていない変更があると"*"が表示されます。
![スクリーンショット 2021-09-12 20.05.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849306/974e9d9e-e5d4-3fa1-864a-1729b5a9f684.png)

以下の例では、ステージングされていない変更（Top.jsx）があるため、ブランチ名の横に"*"が表示されています。
![スクリーンショット 2021-09-12 20.21.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849306/d737fca4-80bc-46a8-3e3a-6c0e216785b6.png)

- GIT_PS1_SHOWSTASHSTAT（スタッシュの有無）

スタッシュに入っているものがあるとブランチ名の横に"$"が表示されます。スタッシュが何かについては[こちら](https://qiita.com/chihiro/items/f373873d5c2dfbd03250)の記事が最近公開されたものでわかりやすいので参照してください。以下の例では、スタッシュを削除したことで、"$"の表示が消えています。
![スクリーンショット 2021-09-12 20.35.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849306/6742f69c-403d-5493-96d9-a1e44145bfe3.png)
- GIT_PS1_SHOWUNTRACKEDFILES（新規ファイルの有無）

ステージング（git add）されていない新規ファイルがあると"%"が表示されます。以下の画像では`git add .`される前は"%"が表示され、された後は"+"が表示されています。

![スクリーンショット 2021-09-12 20.05.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849306/974e9d9e-e5d4-3fa1-864a-1729b5a9f684.png)



- GIT_PS1_SHOWUPSTREAM（HEADとそのアップストリームの違い）

現在のブランチのアップストリームより進んでいれば">"、遅れていれば"<"、同じであれば"="が表示されます。アップストリームは比較対象のブランチで、設定を変えていなければorigin/masterのブランチがアップストリームになっているようです。

`git commit`をするとHEADの方がorigin/masterより進んだため">"と表示され、
![スクリーンショット 2021-09-12 20.50.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849306/6ec7a423-cec1-82c9-5fe6-75f757a6961d.png)

`git push`すると">"から"="に表示が変わりました。
![スクリーンショット 2021-09-12 20.50.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849306/c9d23813-6245-13f6-6cdf-5f4a263ea61c.png)



## Tab補完機能を実装（git-completion）
[git/contrib/completion/git-completion.zsh](https://github.com/git/git/blob/master/contrib/completion/git-completion.zsh)の指示を1つずつ確認していきます。

###手順1：git-completion.zshファイルとgit-completion.bashファイルをコピー

```:git/contrib/completion/git-completion.zsh
# The recommended way to install this script is to make a copy of it as a
# file named '_git' inside any directory in your fpath.
#
# For example, create a directory '~/.zsh/', copy this file to '~/.zsh/_git',

*訳：このファイル（git-completion.zsh）を_gitというファイル名で好きなフォルダにコピーしてください。
```

先ほど作成した.zshフォルダ下でコピーします。

```zsh:ターミナル
% cd ~/.zsh

% curl -o _git https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.zsh
```

###手順２：.zshrcファイルに設定を追記（その1）

```:git/contrib/completion/git-completion.zsh
# and then add the following to your ~/.zshrc file:
#
#  fpath=(~/.zsh $fpath)

*訳：.zshrcファイルに次の一文（fpath=(~/.zsh $fpath)）を追記してください。
```

.zshrcファイルに以下のように追記します。

```:~/.zshrc
fpath=(~/.zsh $fpath)
```

###手順３：.zshrcファイルに設定を追記（その2）

```:git/contrib/completion/git-completion.zsh
# You need git's bash completion script installed. By default bash-completion's
# location will be used (e.g. pkg-config --variable=completionsdir bash-completion).

# If your bash completion script is somewhere else, you can specify the
# location in your ~/.zshrc:
#
#  zstyle ':completion:*:*:git:*' script ~/.git-completion.bash

*訳：git-completion.bashもインストールしておく必要があります。git-completion.zshでは
    デフォルトでgit-completionの位置が使われます。
    すでにgit-completion.bashのスクリプトがある場合は、.zshrcファイル内でgit-completion.bash
    の場所を指定できます。（要は次の一文「zstyle〜」も追記せよということ）

```

.zshフォルダ下でgit-completion.bashをコピーします。

```zsh:ターミナル
% cd ~/.zsh

% curl -o git-completion.bash https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash
```

次に、.zshrcファイルに以下のように追記します。

```:~/.zshrc
zstyle ':completion:*:*:git:*' script ~/.zsh/git-completion.bash
```


## 最終形の確認
最終的に、.zshrcファイルには以下の記述がされています。

```:~/.zshrc
# git-promptの読み込み
source ~/.zsh/git-prompt.sh

# git-completionの読み込み
fpath=(~/.zsh $fpath)
zstyle ':completion:*:*:git:*' script ~/.zsh/git-completion.bash
autoload -Uz compinit && compinit

# プロンプトのオプション表示設定
GIT_PS1_SHOWDIRTYSTATE=true
GIT_PS1_SHOWSTASHSTATE=true
GIT_PS1_SHOWUNTRACKEDFILES=true
GIT_PS1_SHOWUPSTREAM=auto

# プロンプトの表示設定(好きなようにカスタマイズ可)
setopt PROMPT_SUBST ; PS1='%F{green}%n@%m%f: %F{cyan}%~%f %F{red}$(__git_ps1 "(%s)")%f
\$ '
```

これでブランチ名の表示機能とTab補完機能が実装されたはずです。
快適なgitライフを！


## 参考資料
**Git**
- [git/contrib/completion/git-completion.zsh](https://github.com/git/git/blob/master/contrib/completion/git-completion.zsh)
- [git/contrib/completion/git-prompt.sh](https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh)
- [【git stash】コミットはせずに変更を退避したいとき（Qiita）](https://qiita.com/chihiro/items/f373873d5c2dfbd03250)

**zsh**
- [ZSH - THE Z SHELL（公式サイト）](https://zsh.sourceforge.io/)
- [【.zshrc解説】コピペで簡単zshカスタマイズ【設定方法】（Suwaru blog）](https://suwaru.tokyo/%e3%80%90-zshrc%e8%a7%a3%e8%aa%ac%e3%80%91%e3%82%b3%e3%83%94%e3%83%9a%e3%81%a7%e7%b0%a1%e5%8d%98zsh%e3%82%ab%e3%82%b9%e3%82%bf%e3%83%9e%e3%82%a4%e3%82%ba%e3%80%90%e8%a8%ad%e5%ae%9a%e6%96%b9%e6%b3%95/)
- [【zsh】絶対やるべき！ターミナルでgitのブランチ名を表示&補完【git-prompt / git-completion】（Qiita）](https://qiita.com/mikan3rd/items/d41a8ca26523f950ea9d)
- [【Git】Gitプロンプトを便利にする方法（ちょっと厨二っぽいSEのブログ）](https://ryokwkm2.hatenadiary.jp/entry/2017/09/21/125854)
- [Bash のプロンプトに Git のブランチ名を表示する（Qiita）](https://qiita.com/takuya0301/items/4f7c6a797224d9b75eb9)