自称 Git 中級者が知らなさそうな Git コマンド 5 選

## 背景

Git は、大体以下のあたりのサブコマンドを使いこなせるようになると、 
「あれ、俺もう Git なんでも知ってるんじゃね??」みたいな気持ちになってきて、 
実際 Git を使った開発でも普段困ることは無くなってきます。  
私が実際そうでした。  

* init
* status
* add/restore
* mv/rm
* clean
* commit
* fetch//pull/push/
* merge
* diff
* rebase
* remote
* branch
* tag
* log
* cherry-pick
* grep
* blame
* svn
* submodule
* config
* archive

しかし、Git にはまだまだサブコマンドがあります!! 
今回、おなじみの技術評論社さんの「ポケットリファレンス」シリーズの Git 版を読んで、 
自称 Git 中級者の筆者が知らなかった Git の機能を一覧で紹介します。

## 自称 Git 中級者が知らなさそうな Git サブコマンド 5 選

### revert : コミットの内容を取り消すコミットを作成する

今まで revert をするときは対象のコミットの差分を見て、 
普通に revert コミットを作ったりしてしまっていました。 
ですが、この revert 使えば、正しく revert コミットを作ることができます。  

#### Usage:

```
$ git revert <commit>...
```

* どんなときに使えそうか
  * revert コミットを作成するとき
    * こっちのサブコマンドをちゃんと使おうという意味で
  * すでに master へ push されているコミット の revert をする
    * ローカルだったらそもそもなかったことにすることが多いため

### reflog : リポジトリの操作履歴を確認する

今まで、一度 Git のコミットツリーから消えてしまったコミットは、 
二度と復元できないと思っていました。  

reset や rebase をしたときに、時々復元出来たらと思うことがあると思います。 
そんなときにこの reflog を使えば、リポジトリの操作履歴を閲覧できるため、 
その復元をすることができます。  

#### Usage:

例えば、以下のような形で、リポジトリの操作履歴を表示できます。  

```
$ git reflog
82f4002 HEAD@{2}: rebase -i (pick): Update DEVELOPMENT.md
7236ee6 HEAD@{3}: rebase -i (reword): Update README.md
5cf564a HEAD@{4}: rebase -i: fast-forward
93608d0 HEAD@{5}: rebase -i (start): checkout HEAD~~~
9c753d8 HEAD@{6}: rebase -i (finish): returning to refs/heads/master
9c753d8 HEAD@{7}: rebase -i (pick): Update Changes.md
df54fb4 HEAD@{8}: rebase -i (squash): Update DEVELOPMENT.md
6c3ac99 HEAD@{9}: rebase -i (start): checkout HEAD~~~
2e8b27d HEAD@{10}: commit: Update DEVELOPMENT.md
0cf8eb8 HEAD@{11}: commit: Update Changes.md
6c3ac99 HEAD@{12}: commit: Update DEVELOPMENT.md
5cf564a HEAD@{13}: commit: update README.md
93608d0 HEAD@{14}: merge refs/remotes/origin/master: Fast-forward
abda470 (tag: 0.2.0) HEAD@{15}: checkout: moving from packaging to master
```

また、以下のようにオプションで、特定の branch の操作履歴を表示することができます。  

```
$ git reflog show master
```

* どんなときに使えそうか
  * うっかり reset/rebase してコミットを消してしまった場合

* 注意点
  * ローカルリポジトリ内の操作履歴のため、リモートへ上げた誰かの操作履歴を見れるわけではない
  * デフォルト設定では 30 日で履歴は削除される
  * `git gc` を実行すると履歴は削除される

### notes : コミットに注釈を付ける

notes を使うと、コミットメッセージに表示されないコメントをコミットへ付与できます。  

#### Usage:

```
$ git notes add -m "note hogehoge" HEAD

$ git notes show HEAD
note hogehoge

$ git show HEAD
commit 8162fc328f6671beb6268aa9eee94d121a2bce29 (HEAD -> master)
Author: akif999 <aki01nf28@gmail.com>
Date:   Sun Nov 24 06:42:07 2019 +0900

    Initial

Notes:
    note hogehoge

diff --git a/a.xlsx b/a.xlsx
new file mode 100644
index 0000000..524e0c3
--- /dev/null
+++ b/a.xlsx
@@ -0,0 +1,5 @@
+[Sheet1] hoge
+[Sheet1] hoge
+[Sheet1] hoge
+[Sheet1] hoge
+[Sheet1] hoge
```

* どんなときに使えそうか
  * 使わなさそう

### update-index : インデックスの内容を操作する

update-index を使うと、一時的に Git で管理しているファイルの変更を、  
無視するように設定することができます。  

#### Usage:

```
$ git update-index [--[no-]assume-unchanged] [--[no-]skip-worktree] [<file>...]
```

オプションごとに、以下のように動きます。  

* --assume-unchanged の場合、変更を無視しつつ、merge の際は merge 先の内容上書きする
* --skip-worktree の場合、変更を無視しつつ、merge の際は merge 先の内容は無視する

```
$ git upsate-index --assume-unchanged a.c
$ git upsate-index --skip-worktree a.c
```

* どんなときに使えそうか
  * 開発のある時点では変更をするが、そのタイミング以外は変更をしない場合
  * 他の開発者が不必要に管理しているファイルがあり、それが自動的に上書きされる場合

### bisect : バグが混入したコミットを特定する

bisect では、問題のあるコミットを二分探索することを助けてくれます。  

#### Usage:

使い方は本記事で解説するには複雑なため、以下の --help オプションを参照してください。 
雰囲気的には、git が勝手に二分探索でコミットを移動してくれるので、 
その度にユーザがスクリプトか手動で問題があるかを伝えるような使い方です。  

```
$ git bisect --help
```

* どんなときに使えそうか
  * コミット数がとても多い変更からバグを探す場合

## まとめ

* 普段使わないサブコマンドも積極的に活用するようにしていくと、さらに開発がスムーズになりそう


## 参考文献

* 『【改訂新版】Gitポケットリファレンス』 技術評論社