Git操作に慣れ始めた人のためのGitTips


これは[Yahoo! JAPAN 18 新卒 Advent Calendar 2018](https://adventar.org/calendars/3388)の24日目の記事です！
前回は@rykgyさんの「[PlatformViewを使ってiOSのネイティブビューを表示するFlutter Pluginを作成する](https://qiita.com/rykgy/items/24c710e1c83be436ac69)」でした。

今回はGit操作に慣れ始めた人のためのGitTipsというタイトルで記事を書かせていただきます！  

## はじめに
みなさんGit使ってますか？
Gitを利用されている方は多いかと思いますが、ちょっとしたコマンドやコミットを汚してしまった時のコマンドなどを、これを気にまとめようと思いこの記事を書きました！
少しでも参考になれば幸いです。

## 対象者
* Gitをある程度触っている人
* 基本的なコマンドがわかる人
* ちょっと違うことをしようとするとよくわからなくなる人

## 言葉の整理
今回、書いていくに当たってここで出てくる言葉について少しおさらいしておきます。  

* ワーキングディレクトリ
  * 普段操作している場所のこと
* ステージエリア
  * addされた時に追加される場所のこと
* HEAD(インデックス)
  * 現在の作業ブランチの先頭コミット

## 削除、取り消し、無視

### リモートで既に削除されているブランチを手元に反映させたい
作業ブランチをマージして削除後、ローカルの作業ブランチを削除したい時に利用できます。

```
# リモートで削除されているブランチを削除
$ git fetch --prune

# 以下も同じ
$ git pull --prune

# また、以下も同じ
$ git fetch
$ git remote prune origin
``` 

参考
* https://qiita.com/yuichielectric/items/84cd61915a1236f19221


### commitしてないファイルの変更を元に戻したい
前回のコミットから変更したものの変更がいらなくなった時などに利用するコマンドです。
ステージエリアに上がってない変更後のファイルを元に戻します。

正確に言うとワーキングディレクトリ内のファイルにHEAD状態のファイルへ変更を行ってます。

```
# 全ての変更を元に戻す
$ git checkout .

# 単一ファイルだけ
$ git checkout [ファイル名]
```
参考
* http://www-creators.com/archives/1388

### 指定したファイルの変更を一時的に無視したい

```
# 一時的に無視
$ git update-index --assume-unchanged [ファイル名]
# 無視したファイルをgit管理下に戻す
$ git update-index --no-assume-unchanged [ファイル名]

# 以下でもできるようです（挙動に違いあり）
# 一時的に無視
$ git update-index --skip-worktree [ファイル名]
# 無視したファイルをgit管理下に戻す
$ git update-index --no-skip-worktree [ファイル名]
```

参考
* https://qiita.com/usamik26/items/56d0d3ba7a1300625f92


## 差分を見る

### ワーキングディレクトリとステージエリアとの差分を見る
addする前の差分を見る時に見ます。

```
# 差分を見る
$ git diff

# ファイルの差分を見る
$ git diff [ファイル名]

# ファイル名のみ
$ git diff --name-only
```

参考
* https://qiita.com/imai/items/09b8a72e5f8c34b432e8
* https://qiita.com/shibukk/items/8c9362a5bd399b9c56be

### 現在のブランチの最新コミット（HEAD）との差分を見る
add後の変更を見る時につかいます。

```
# 差分を見る
$ git diff --staged
```

参考
* https://qiita.com/shibukk/items/8c9362a5bd399b9c56be

### ブランチ間の差分を見る
ブランチ間の差分を見るときに利用します。  

```
# 全ファイルのブランチ間の差分
$ git diff [ブランチ名A] [ブランチ名B]

# ブランチ間で差分があるファイル名
$ git diff --name-only [ブランチ名A] [ブランチ名B]

# 単一ファイルのブランチ間の差分
$ git diff [ブランチ名A] [ブランチ名B] [ファイル名]
```

参考
* https://easyramble.com/git-diff-between-branches.html
* https://qiita.com/shibukk/items/8c9362a5bd399b9c56be

## ブランチ間移動

### 前回いたブランチに移動したい

```
$ git checkout -
```
参考
* https://qa.atmarkit.co.jp/q/2730

### ワーキングツリーでの作業中ファイルを一時退避したい
編集中などに別ブランチで作業する必要がある時などに利用できます。
別ブランチに編集中のファイルを持っていきたいときにも利用可能です。

```
# 編集中ファイル一時退避
$ git stash

# 退避中のファイルを取り出す
$ git stash pop
```

参考
* https://qiita.com/fukajun/items/41288806e4733cb9c342

## 別ブランチから持ってくる
### 一部別ブランチからファイルを持ってくる

別のブランチからファイルを持ってきたいときなどに利用できます。
これも[commitしてないファイルの変更を元に戻したい](https://qiita.com/music431per/private/49dd209db9393e46318b#commitしてないファイルの変更を元に戻したい)で述べたように
ワーキングディレクトリに指定したブランチ名のファイルを持ってくるような動きをしています。

```
# 確認
$ git show [ブランチ名]:[ファイル名]

# 単一ファイルを持ってくる
$ git checkout [ブランチ名] -- [ファイル名]

# ディレクトリで持ってくることも可能
$ git checkout [ブランチ名] -- [ディレクトリ名]
```

参考
* https://qiita.com/oret/items/b646fcada9d89ed308c4

### 別ブランチから特定のコミットを持ってくる
別ブランチで作業していたものが必要なとき特定のコミットのみの変更を持ってくることができます。  

```
# コミットの内容を取り込む
$ git cherry-pick [コミットID]

# 複数のコミット内容を取り込みたい場合
$ git cherry-pick [始点のコミットID]..[終点のコミットID]
```

参考
* https://dackdive.hateblo.jp/entry/2016/06/06/203542


## コミットを綺麗にしたい

### 間違えてaddしてしまった
コミットしない予定のファイルを間違えてaddしてしまった時
addしたファイルをステージエリアから取り除くことができます。

```
# 全てのファイルをステージから取り除く
$ git reset HEAD

# 単一のファイルをステージから取り除く
$ git reset HEAD [ファイル名]
```

参考
* http://tweeeety.hateblo.jp/entry/2015/06/10/212631

### addし忘れてコミットしちゃった
```
# addし忘れたファイルをステージにあげる
$ git add [addし忘れたファイル名]
# 一つ前のコミットに変更を加える
$ git commit --amend

# コミットメッセージは編集しない場合
$ git commit --amend --no-edit
```
参考
* https://qiita.com/piruty/items/402b5bf83479f7e3480a

### コミットをまとめる
いくつかのコミットをまとめたい場合  

```
# 三つ分のコミットをまとめる場合
$ git rebase -i HEAD~3

# 現在のブランチ全てのコミットをまとめてマージする場合
# まとめる用のブランチを作成(マージ予定のブランチから生やす)
$ git checkout -b [まとめるブランチ名]
# そこから作業ブランチを作成
$ git checkout -b [たくさんコミット予定の作業ブランチ]
# 作業後、まとめるブランチに移動
$ git checkout [まとめるブランチ名]
# コミットをまとめる
$ git merge --squash [たくさんコミットした作業ブランチ]
```
rebaseを利用する場合、すでにまとめるコミットがpush済みだと強制pushする必要があるので注意。。。
また、githubを利用している場合はPR後のマージ時にsquash mergeのオプションがあるのでPR単位でのsquash mergeならそっちの方が楽です。  

<img width="385" alt="スクリーンショット 2018-12-19 0.58.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/64452/ebf7874e-58af-02db-bf43-6484685d348e.png">


参考
* https://dev.classmethod.jp/tool/git/git-rebase-fixup/
* https://www.granfairs.com/blog/cto/git-merge-squash


## 環境

### リポジトリ管理
管理するリポジトリが増えてきた方などは
`ghq`+`peco`を利用するのがおすすめです。

参考
* https://qiita.com/strsk/items/9151cef7e68f0746820d

## エイリアス
自分はコマンド打ち込む量も多くなってくるのでaliasを設定してます。
自分はzshでプラグインをzplugで管理しているので
oh-my-zshのgit pluginを利用しています。

参考
* https://qiita.com/takc923/items/45f005d700895907ecf5

## おまけ

### Githubで草が生えない
Githubでコミットしても草が生えない方
設定にgithubのメールアドレスを追加することで草が生えるようになります。

```
# セットされているメールアドレスを確認
$ git config user.email

# メールアドレスをセット
$ git config user.email [メールアドレス]
```

参考：https://qiita.com/endo_hizumi/items/49edf021b8b9189b4f88


## 最後に

今回調べてみて、知らなかった機能もたくさんあり結構いろんなことができることを改めて知ることができました。他にもいろいろと便利な機能等あるかと思いますが少しでも参考になれば幸いです。

間違え等は無いように気をつけていますが何かあればコメントや修正依頼をお願い致します。

明日は最後の一枚、Shion Fukushimaさんの「openFrameworksでpix2pixを実装する」です。
では、良いクリスマスを！