git操作はGUIツール派な自分もCUIに乗り換えた便利git拡張まとめ

![top.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253997/5bbe6d3b-501c-5aea-c786-1e31307f4ad3.gif)

# はじめに

自分は「楽でわかりやすい」という理由から、git操作にはGUIツールの[Sourcetree](https://www.sourcetreeapp.com/)を使用していました。

ただ、GUIツールを使えない状況などではCUIに直接gitコマンドを入力するわけで、GUIツールの恩恵を得られないことも多々ありました。

そこでいっそのこと、**<font color="Green">GUIツールを真似てgitコマンドを拡張し、CUIに乗り換えることにしました。</font>**

本記事は、その際に作成した拡張のまとめになります。

# 目次（〇〇したいところ）

拡張を作成するにあたって、GUIツールと同じように**「gitコマンドでも〇〇したい！」**と思ったところをピックアップしました。

このピックアップ項目をもとに、gitコマンドを拡張していきます。

（なので、この項目が本記事の目次でもあります）

**〇〇したいところ**

[1. branch一覧から選んでcheckoutしたい](https://qiita.com/yukiarrr/items/9c21d97f6c8ac31de157#1-branch%E4%B8%80%E8%A6%A7%E3%81%8B%E3%82%89%E9%81%B8%E3%82%93%E3%81%A7checkout%E3%81%97%E3%81%9F%E3%81%84)
[2. 差分の内容をもっと見やすくしたい](https://qiita.com/yukiarrr/items/9c21d97f6c8ac31de157#2-%E5%B7%AE%E5%88%86%E3%81%AE%E5%86%85%E5%AE%B9%E3%82%92%E3%82%82%E3%81%A3%E3%81%A8%E8%A6%8B%E3%82%84%E3%81%99%E3%81%8F%E3%81%97%E3%81%9F%E3%81%84)
[3. 差分から選んでadd・resetしたい](https://qiita.com/yukiarrr/items/9c21d97f6c8ac31de157#3-%E5%B7%AE%E5%88%86%E3%81%8B%E3%82%89%E9%81%B8%E3%82%93%E3%81%A7addreset%E3%81%97%E3%81%9F%E3%81%84)
[4. stash一覧をもっと見やすくしたい](https://qiita.com/yukiarrr/items/9c21d97f6c8ac31de157#4-stash%E4%B8%80%E8%A6%A7%E3%82%92%E3%82%82%E3%81%A3%E3%81%A8%E8%A6%8B%E3%82%84%E3%81%99%E3%81%8F%E3%81%97%E3%81%9F%E3%81%84)
[5. stash一覧から選んでapply・dropしたい](https://qiita.com/yukiarrr/items/9c21d97f6c8ac31de157#5-stash%E4%B8%80%E8%A6%A7%E3%81%8B%E3%82%89%E9%81%B8%E3%82%93%E3%81%A7applydrop%E3%81%97%E3%81%9F%E3%81%84)
[6. 現在のbranchのpushを楽にしたい](https://qiita.com/yukiarrr/items/9c21d97f6c8ac31de157#6-%E7%8F%BE%E5%9C%A8%E3%81%AEbranch%E3%81%AEpush%E3%82%92%E6%A5%BD%E3%81%AB%E3%81%97%E3%81%9F%E3%81%84)

# 便利拡張を紹介する前に

gitコマンドを拡張するにあたって一つ、依存しているツールがあります。
それは、[fzf](https://github.com/junegunn/fzf)や[peco](https://github.com/peco/peco)をはじめとするインタラクティブフィルターです。

インタラクティブフィルターとは、受け取ったリストを対話形式でユーザーに選択させ、それを出力する機能を持ったツールのことで、例えば、

```
git branch | fzf | xargs git checkout
```

とすれば、「branch一覧から一つ選んでcheckoutする」ということができるようになります。

![fzf.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253997/c53d4929-574d-4460-1f6d-570ac08a01ed.gif)

今回はこのインタラクティブフィルターのうち、曖昧検索とpreview機能があるfzfを使用しました。

# 便利拡張まとめ

gitコマンドを拡張するにあたって、本記事ではaliasで拡張しています。

ただ、aliasに記述する方式は少し制約もあったりするので、もし必要になればサブコマンド化も検討いただければと思います。

## 1. branch一覧から選んでcheckoutしたい

### <font color="Green">*git co*</font>

![co.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253997/ecfa0443-9a06-fe30-cead-60ced59c51d9.gif)

リモート含めたbranch一覧から一つ選んでcheckoutできるコマンドです。

GUIツールでは当然できることですが、gitコマンドで同じことをするには、複数のコマンドを駆使する必要があり面倒なため拡張しました。

やっていることは以下の通りです。

- 引数がない場合、branch一覧をfzfに渡してリスト表示し、選択されればcheckoutする
- 引数がある場合、特別な処理はせず`git checkout [引数]`を実行する

```sh
[alias]
    co = "!f() { args=$@; if [ -z \"$args\" ]; then branch=$(git branch --all | grep -v HEAD | fzf --preview 'echo {} | cut -c 3- | xargs git log --color=always' | cut -c 3-); git checkout $(echo $branch | sed 's#remotes/[^/]*/##'); else git checkout $args; fi }; f"
```

## 2. 差分の内容をもっと見やすくしたい

### <font color="Green">*git d*</font>

![d.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253997/ad423e66-11d5-d3c6-f144-45698c2de3d7.gif)

差分をファイルごとに切り替えながら確認できるコマンドです。

gitコマンドの`git diff`は、

- 差分がまとめて表示されるため、差分が大きいと見にくくなる
- Untrackedなファイルが表示されない（`git add -N`が必要）

と、個人的に少し使いづらかったため、Sourcetreeの作業コピーを参考に拡張しました。

<img width="944" alt="diff.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253997/17db05f5-7f7b-56d9-602d-831c68b5e0db.jpeg">

引数を指定すれば、commitやbranch間の差分もこの形式で確認でき、よく使うコマンドの一つになっています。

やっていることは以下の通りです。

- 引数がない場合、`git status`からUntrackedなファイルも含めた差分を取得し、それをfzfに渡してリスト表示
- `git d d1319bc2..37efebdb`のように引数がある場合、`git diff --name-status`から差分を取得し、それをfzfに渡してリスト表示

```sh
[alias]
    d = "!f() { args=$@; [ -z \"$args\" ] && args=HEAD; ([ \"$args\" = \"HEAD\" ] && git status --short || git diff --name-status $args | sed 's/\t/  /') | fzf --preview \"echo {} | cut -c 4- | xargs git diff --color=always $args --\" --multi --height 90% | cut -c 4-; }; f"
```

## 3. 差分から選んでadd・resetしたい

### <font color="Green">*git da*</font>

![da.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253997/2e8023ea-1b57-a078-5c4f-f8bca033b0a9.gif)

上記の拡張コマンド`git d`で表示されるリストから、差分ファイルを選んでaddできるコマンドです（`Ctrl+i`で複数選択）。

gitコマンドの`git add`は、全差分が対象であれば問題ありませんが、差分を見ながら一部のファイルだけaddしたい場合に使いづらかったため拡張しました。

```sh
[alias]
    da = !git d | xargs git add --
```

### <font color="Green">*git dr*</font>

上記の拡張コマンド`git da`のresetバージョンになります。

```sh
[alias]
    dr = !git d | xargs git reset --
```

## 4. stash一覧をもっと見やすくしたい

### <font color="Green">*git stl*</font>

![stl.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253997/7c91088a-9c30-abc3-d41b-9c9a7645f1b2.gif)

stash一覧を変更内容も含めて確認できるコマンドです。

gitコマンドの`git stash list -p`は、stash内容がまとめて表示されるため、stashの数が多くなると見にくくなるため拡張しました。

```sh
[alias]
    stl = !git stash list | fzf --preview 'echo {} | grep -o stash@{.*} | xargs git stash show -p --color=always' --height 90% | grep -o stash@{.*}
```

## 5. stash一覧から選んでapply・dropしたい

### <font color="Green">*git sta*</font>

![sta.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253997/ed4cfb55-a677-0598-afa5-722425a8de08.gif)

上記の拡張コマンド`git stl`で表示されるリストから、stashを選んでapplyできるコマンドです。

GUIツールのように、stashの内容を確認しながら目的のstashを探してapplyしたかったため、拡張しました。

```sh
[alias]
    sta = !git stl | xargs git stash apply
```

### <font color="Green">*git std*</font>

上記の拡張コマンド`git sta`のdropバージョンになります。

```sh
[alias]
    std = !git stl | xargs git stash drop
```

## 6. 現在のbranchのpushを楽にしたい

### <font color="Green">*git ps*</font>

現在のbranchをpushするコマンドです。

gitコマンドの`git push`は、リモートにbranchが存在しない状態でpushする際、引数でbranch名を指定する必要があります。

これが地味に面倒だったため、デフォルトで現在のbranchをpushするよう拡張しました。

```sh
[alias]
    ps = "!f() { args=$@; [ -z \"$args\" ] && git push origin HEAD || git push $args; }; f"
```

または、

```sh
[push]
    default = current
```

## その他

拡張というわけではありませんが、できるだけ入力が少なくて済むように省略形をaliasに追加しています。

```sh
[alias]
    b = branch
    c = commit
    cm = commit -m
    f = fetch
    s = status
    st = stash
    rh = reset --hard
```

## これらの拡張を導入するには？

今回の拡張はaliasに追加しているため、自身の`~/.gitconfig`のaliasに追加すれば使用できるようになります。

また、自分のdotfilesリポジトリにて、これらの拡張をまとめた`.gitconfig`を公開しているため、参考にどうぞ。
https://gitlab.com/yukiarrr/dotfiles/blob/master/.gitconfig

# まとめ

CUIに乗り換えた自分ですが、GUIツールはあらためて便利だと感じました。
特に差分の操作が素晴らしく、行単位でadd・reset・checkoutできたりします。

CUI上でもできるだけ便利にできるよう、今後も拡張を続けていきたいと思います。

Twitter: [@yukiarrr](https://twitter.com/yukiarrr)