gitに慣れ始めてきた人へ、業務で使える便利git10選

## はじめに

業務で初めてgitに出会ってから3年が経ちました。
自分より新しい人もたくさん増えて、自分が当たり前のように使っているコマンドを知らない人が周りにいることを先日知りました。
そういえば、1年目のときは全然わからなくてラージャンのような怖い先輩にいっぱい怒られて苦手で大嫌いだったgitも、今では普通に使っていて人に教えるようになっているとは・・・とちょっと感慨深くなったので、周りで苦戦しているみなさんにも知って欲しいなと思って共有します。
基本的なgitはOK！という人に、次のステップとしてぜひ習得してもらいたいgitコマンドたちです。

### 確認編

* ソース修正〜commitまでの一連の動作についておさらいです
* 普段、意図しない差分がcommitされていないか、ちゃんと最終確認していますか？
* やってない人は、今一度自分の作業を見直してみましょう :point_up: 

##### ソース修正〜commitまでの一連の動作

1. ソース修正
2. `git status`->`git diff`を繰り返し、差分を**確認**
3. 必要な差分を`git add`
4. indexに`add`された差分を`git diff --cached`で**最終確認**
5. `git commit`
6. `git show`で**もう一度確認** （ここまでできればgood！）

ここまでOKであれば、基本的なgit操作は大丈夫ですね＼(^o^)／
まだ怪しいよって人は身に染み付くまで繰り返しやってください。そうすればこの一連の作業を息をするように出来るようになると思います。

### 準備編

* よく使うコマンド、オプションはaliasに設定しておきましょう！作業効率UPです :blush: 

例

```
alias.co checkout
alias.s status
alias.b branch
alias.r remote
alias.d diff
alias.m merge --no-ff
alias.fe fetch --all
alias.up pull --rebase
alias.l log --oneline --decorate --graph --all -20
alias.lp log --oneline --decorate --graph
alias.llp log --graph --decorate --pretty='format:%C(yellow)%h%Cblue%d%Creset %s %C(black bold)%an [%ai]%Creset' -20
alias.rh reset head
alias.d1 diff HEAD~
alias.d2 diff HEAD~~
alias.d3 diff HEAD~~~
alias.d4 diff HEAD~~~~
alias.d5 diff HEAD~~~~~
```

## 1. 「さっきのブランチに戻りたいなあ〜」→ `git checkout -`

* 一つ前のブランチに戻れます
* ブランチ名に特定のプレフィックスがついてる場合など、補完しにくいときなどはこれを使えば行き来が楽です。

```.bash
(master)
$ git checkout work

(work)
$ git checkout -

(master)
$ 
```

## 2. 「この行の修正だけcommitしたいなあ〜」→ `git add -p`

* `add`を差分ごとに実行できます。
* 基本的に以下4つさえ覚えておけばたいていのことはできます。めっちゃ便利です。
    * y - この差分をindexにいれる
    * n - スキップする
    * q - 終了する
    * s - 差分を分割する
* 私のgit人生のバイブルと思っている記事を紹介します
    *  [横着で神経質な私とあなたに贈るgit add -p](http://qiita.com/crifff/items/1abf08bca4ce51db4775)
* `git add (ファイル名)`で差分単位ではなくファイルごとaddできますが、`git add -p (ディレクトリ名/ファイル名)`とすれば、`add -p`の対象を絞ることも可能です。

## 3. 「差分のあるファイルってどれだっけ？」→ `git diff --stat`

* `diff`（差分）をファイル単位で出力できます
* 差分が多くなったので確認したいとき、差分のあるファイル名をコピペしたいときなどに
* 同類で、ファイル名だけを出す場合は`--name-only`が使えます

```.bash
$ git diff --stat
 sample.rb  | 3 ---
 test.rb | 3 +++
 2 files changed, 3 insertions(+), 3 deletions(-)

$ git diff --name-only
sample.rb
test.rb
```

## 4. 「あのブランチのあのcommitが欲しい！」→ `git cherry-pick [commit番号]`

* 他のブランチに存在している、指定した`commit`を自分のブランチに取り込むことができます
* 差分が出そう、commitメッセージは変えたいという場合には、オプションとして`-n`をつければindexに取り込んでくれる便利具合です。

```.bash
$ git cherry-pick a1sd2f3 -n
```

## 5. 「あのブランチのあのファイルが欲しい！」→ `git checkout [ブランチ名] -- [ファイル名]`

* 特定ブランチの特定ファイルのみの差分をindexに引っ張ってこれます


```.bash
(master)
$ git checkout work -- test.rb

(master)
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	modified:   test.rb
```

## 6.「インデント変えただけなのに差分が大量にあって見づらいよ〜」→ `git diff -w`

* [生意気な後輩](http://qiita.com/yamamoto_hiroya)に教えてもらった秘伝オプションです。詳細は記事にある通り。
    + [git diff -bとgit diff -wの違いを調べた](http://qiita.com/yamamoto_hiroya/items/2228691d380ae525f1b9)
* `-w`で、ホワイトスペースを全部無視、`-b`でホワイトスペースの**数**を無視です
* インデント変更は意図しない差分を生みやすいので、それだけでまずcommitしてしまうのが良いですね◎

## 7.「この差分、commitしたくないけど消したくないよ〜」→ `git stash`

* 一時保存コマンド、`stash`が使えるようになればぐんと作業が捗ります
* 複数の作業ブランチを並行稼動しているときに毎回commitしなくて済むのですごく便利です
* また、同じ機能を何度も修正・開発するときなどに決まったログを仕込んで出すことがありますが、何回も消して書いてをしなくても、`stash save`して`stash apply`すれば一次保存ではなくsnippet的な利用も可能です
* レビューしているブランチでログ仕込んだり変更したり好きなようにいじって`stash`, レビュー返却してまた返って来たら`stash pop`して確認・・・とかも可能
* **ログ出力の差分をcommitなんかしたら怖い先輩に ~~殺さ~~ 怒られるのでstashを活用して絶対commitしない運用にしておきましょう**

#### 便利なstashさん一族

* `stash` -> 保存
* `stash list` -> 保存内容一覧。`stash{1}`などそれぞれに番号がついていますね。それが保存番号です。
* `stash pop` ->　保存を取り出す＆消す
    * 保存番号をつけなければ、最新の保存内容を取得します。保存番号を指定する場合は、`stash pop stash{1}`という感じに。他コマンドも同様。
    * conflictしたら消えません。正しく取り出せたら`drop`しましょう
* `stash apply` -> 保存を消さないで取り出す。後でまたその差分を使いたいときに。
* `stash drop` -> 保存を消す
* `stash show` -> 保存内容を見る
* `stash save "message"` -> 名前をつけて保存
* その他、stashについてわかりやすい記事こちら
    * [サクッと使いこなすためのgit stash Tips & stashの仕組み](http://qiita.com/ton1517/items/9888a78f6b063e748558)

`stash`を多用する人は、定期的に`stash list`して保存内容を確認・断捨離しましょう。
でないと30個とか溜まってしまったりして、周りから整理できない系女子と揶揄されます。

## 8.「このブランチを最新のmasterから切ったことにしたいな〜」→ `git rebase`

* masterブランチから切って作業を開始して、開発に時間がかかってしまうとmasterと差分がたくさん発生してしまうことがあります
* 基本的には、masterをpullして定期的にmergeするかと思いますが、merge commitが多くなると、初期のcommitが追いづらくなりますよね
* そんなときには`git rebase master`とやれば、mergeでなく最新のmasterから切ったように差分を付け替えてくれます
* また、もしworkブランチに、既にmasterにmergeされているcommitがあれば、そのcommitはスキップしてくれます
* 注意しなければいけないのは、**commit番号が再生成され、commit時間もrebaseした時間になるということ**
* commit時間を気にしなくても良いのであれば、rebaseを使っておけばlogを参照する場合には見やすくなります。どちらが良いかは好みです。

## 9.「この差分ってどのcommitに入ってたっけ？」→ `git log -S`

* `git log -S [検索したいキーワード]`とやれば、その単語の差分が入ったcommit一覧が表示されます

```.bash
$ git log -S "hello"
```

* `git blame`で追えないときに使える！
* `-p`をつければ正規表現も使える！
* `git log`系もオプションがたくさんあって楽しいgitの1つです。
    * [git log よく使うオプションまとめ](http://qiita.com/take4s5i/items/15d8648405f4e7ea303)

## 応用編

## 10.「logはきれいに整理しておきたいよ」というこだわり派のあなたに`git rebase -i`

* 俗に言う歴史書き換え系です。`push`する前の自分の作業ブランチでのみ使いましょう。
* `commit`の順番の入れ替え、統合、メッセージの変更などができます。が、その際にはcommit番号は振り直しされます。
* 細かくcommitしている場合、開発が長引く場合、ログを整理しながら組み立てておくと後々遡って確認するときにどこで間違ったか、なぜこうなっているのかがわかりやすくなります。自分の作業を整理したい場合にどうぞ。

### 使い方

* 修正したいcommitの1つ前のcommit番号を引数に指定します。 `$ git rebase -i 1a2s3d4f`
* エディタが開き、指定されたcommitよりも後のcommitが順に並びます
* 修正したいcommitの`pick`の箇所を修正する種類に応じて書き換える
    * pick -> 何もしない 
    * reword -> commitメッセージのみを修正する
    * edit -> commitした差分を編集する
    * squash -> 指定されたcommitとその1つ前のcommitを合体させる（メッセージを変更できる）
    * fixup -> 指定されたcommitとその1つ前のcommitを合体させる（メッセージは1つ前のcommitのものを使用する）
    * pick行を入れ替えれば順番を変更、pick行ごと削除すればcommitを取り除ける

``` .bash
pick 6f6ee27 test.rb作成
pick 30fab66 new.rb作成

# Rebase e32ab67..30fab66 onto e32ab67 (2 command(s))
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
```

* あ、やばいミスった！と思ったら、`rebase --abort`すれば戻せます。
* コンフリクトが発生した場合は修正が複雑になりミスする可能性が高いので中止を推奨します
* 慣れたらやりたい放題できるので、個人的には大好きなgitコマンドです٩( 'ω' )و


## やらかした人へのリカバリ集

3年もgitやってればいろんな贖罪が発生するわけです。手順間違えて共有ブランチを壊しかけたり、bundleをpushしてしまったり・・・(；´∀｀)
そんなときにも焦らずにちゃんと調べればいろんなリカバリ方法が出てきます。
実際に自分も助けてもらった記事やノウハウの一例を紹介します。

* [git add したあと、commit するの忘れてて reset --hard しちゃったけど、取り戻したい](http://qiita.com/yoshiori/items/6da867aa6871be694996)

```.bash
$ git fsck
```

gitがオブジェクトであることとか、ハッシュによる保存方法、`fsck`, `gc`っていうコマンドについて、このとき初めて学びました。
このあたりのgitの仕組みについては正直まだ勉強不足ですが、中身を知ると結構面白いです。


## 最後に

gitの便利コマンドを紹介する記事はいろいろありますが、全部を一気に覚える必要はありません。
叩いてみて、　こんなのがあるんだーというのを知って、実際に業務で困った時・不便だなと思ったときに、
「あれ、そういや◯◯を✕✕するコマンドあったな？」と思い返して、調べて使ってみる・・・を繰り返せば
そのうち自然と覚えているかと思います。

gitに慣れる、gitで思ったことがある程度出来るようになれば、それは開発が早くなる近道です。
そしてgitに慣れるには、叩いて使って失敗してリカバリして…という繰り返しの経験が必要不可欠です。
やったこと・失敗したことをぜひ手元にメモしてノウハウとして蓄積してみてください。
1年後にはきっといろんな操作がスイスイ〜っとできるはずです(｀・ω・´)！