Git コマンドまとめ

## バージョン確認

```bash
$ git --version
```

## 設定

**確認**

```bash
$ git config --list
$ git config キー名
```

**登録・更新**

```bash
$ git config キー名 設定値 # ローカルリポジトリに設定
$ git config --global キー名 設定値 # すべてのローカルリポジトリに設定
```

**削除**

```bash
$ git config --unset キー名
```

## add

**ステージングに上げる**

```bash
$ git add ファイル名
$ git add *.txt # ワイルドカード
$ git add . # すべてのファイル
```

**取り消し**

```bash
$ git reset # 全ファイルをステージングから取り除く。ファイルの変更はそのまま残す
$ git reset ファイル名 # 指定したファイルをステージングから取り除く。ファイルの変更はそのまま残す
$ git reset --hard # 全ファイルをステージングから取り除く。ファイルの変更した箇所も変更前に戻す
```

## commit


**コミットする**

```bash
$ git commit -m "コミットメッセージ"
$ git commit -m "コメント１" -m "コメント２" # 改行する
```

**直前のコミットメッセージを修正する**

```bash
$ git commit --amend
```

**コミットを取り消す**

```bash
$ git reset --soft HEAD^ # 変更箇所はローカルで残す
$ git reset --hard HEAD^ # 変更箇所もローカルから消す
```

**空コミット**

何も変更したくないが新しい変更履歴を作りたいとき、プルリクエストを作りたいときなどに便利。

```bash
$ git commit --allow-empty -m "コミットメッセージ"
```

## add, commit してないファイル操作

**変更したファイルを戻す**

```bash
$ git checkout ファイル名 # HEADと同じ状態に戻す
$ git checkout HEAD ファイル名 # 上記同様
$ git checkout . # 全ファイルHEADと同じ状態に戻す
$ git checkout コミットID ファイル名 # # 指定したコミットIDと同じ状態に戻す
```

**管理対象ではないファイルを削除**

```bash
$ git clean -n # 削除されるファイルを確認
$ git clean -f # 削除
```

## ローカルブランチ操作

**現在のブランチ確認**

```bash
$ git branch
```

**作成**

```bash
$ git branch ブランチ名
$ git checkout ハッシュ値 -b ブランチ名 # 特定のコミットからブランチを切る
```

**移動**

```bash
$ git checkout ブランチ名
```

**作成、移動を同時に行う**

```bash
$ git checkout -b ブランチ名
$ git checkout -b ローカルブランチ名 リモートリポジトリ名/リモートブランチ名 # リモートブランチを指定したローカルブランチ名で作成して移動
```

**削除**

```bash
$ git branch -d ブランチ名
```

## マージ

**マージする**

マージ先のブランチに移動しておく。

```bash
$ git merge (-ff) マージするブランチ名
$ git merge --no-ff マージするブランチ名
```

**マージを取り消す**

```bash
$ git reset --hard HEAD
```

**競合の解決**

```bash
<<<<<<< HEAD 
commit インデックスの状態を記録する # 現在のブランチの内容
=======
pull リモートリポジトリの内容を取得する # マージしようとしたブランチの内容
>>>>>>> マージしようとしたブランチ名
```

上記ファイルを修正し、改めてadd, commitを行う。

#### fast-forward/non fast-forward でマージ

**fast-forward(早送りマージ)**

マージするブランチにマージ先のHEADを持っていく。

```
A（Master）　---------------------+
　　  　↓　　　　　 　　　　　　　　　 ↓
　　  　C（fix-branch）　- 変更 ->　C2
```

`fix-branch`を`Master`ブランチへマージするとき、`fix-branch`が作られた時からMasterブランチがかわっていなければ、MasterのHEADをC2に移動させるだけでマージできる。これでMasterにはC2のコミット履歴が含まれた状態となる。ただし、`C2というブランチがあった、という履歴が消えるので、どのブランチで作業していたのかわからなくなる`ので注意。

```
A --> C --> C2（Master、fix-branch）
```

**non fast-forward**

マージするブランチの先に新たなコミット履歴を作り、そこにマージ先のHEADを持っていく。C2のブランチは消えないので、Dのコミット履歴でC2ブランチで作業したものを判別できる。

```
A（Master）　------------->　D（新しいコミット履歴を作る）
　　  　↓　　　　　　　　　　　　↑ Masterにマージ
　　  　C　-- 変更 -->　C2　--+
```

マージすると、履歴が一本化される。

```
A --> C --> C2 --> D(Master)
```


## stash（一時退避）

```bash
$ git stash save # 現在の変更内容を退避
$ git stash save 名前 # 名前をつけて退避
$ git stash save -u 名前 # トラッキングされていないファイルも含めて退避
$ git stash list # stash一覧を表示 stash@{番号} 番号は最新のstashから0, 1, 2...とつけられる

$ git stash show stash@{番号} # 親コミットとの差分を表示する
$ git stash apply stash@{番号}  # 退避させた内容を元に戻す
$ git stash pop stash@{番号} # 退避させた内容を元に戻し、stashを削除する
$ git stash drop stash@{番号} # 退避させた内容を削除する
$ git stash clear # 退避させた内容を全て削除する
```

一部の変更箇所のみ退避する場合は、`-p`オプションを使用する。

```bash
$ git stash save -p # 退避する部分を対話的に選択していく
```

y: 指定ファイルの指定の変更箇所(Hunk)を退避
a: 指定ファイルの指定の変更箇所(Hunk)を退避して、ファイル内の残りの変更箇所も全部退避
n: 指定ファイルの指定の変更箇所を退避しない(= yの逆)
d: 指定ファイルの指定の変更箇所(Hunk)を退避せず、ファイル内の残りの変更箇所も全部退避しない(= aの逆)
q: 残りのファイルを全部退避しない

**stashの名前を変更する**

`-p`オプションを使用すると名前が設定できない。退避した後にわかりやすい名前をつけたいと思ってもデフォルトではrenameのコマンドがない。stackoverflow を見ていたら、以下のページでやり方が紹介されていたのでここで紹介しておく。

http://stackoverflow.com/questions/25931026/how-can-i-rename-a-git-stash

```bash
$ git config --global alias.stash-rename '!_() { rev=$(git rev-parse $1) && git stash drop $1 || exit 1 ; git stash store -m "$2" $rev; }; _'
$ git stash-rename stash@{0} 任意の名前
```

## blame（変更履歴）

```bash
$ git blame ファイル名 # 各行の変更情報を表示
```

## リモートリポジトリ・ブランチ操作

**リモートリポジトリ作成**

```bash
$ mkdir ディレクトリ名
$ cd ディレクトリ名
$ git init
$ git remote add origin リモートリポジトリURL
$ git add .
$ git commit -m "first commit" 
$ git push origin master # masterという名前のブランチを作成
```

**ローカルにコピー**

```bash
$ git clone url # リポジトリ名と同じ名前のディレクトリを作成してその中にコピー
$ git clone url 名前 # 指定した名前のディレクトリを作成してその中にコピー
```

**一覧表示**

```bash
$ git remote # ローカルに登録しているリモートリボジトリ名一覧
$ git remote -v #  ローカルに登録しているリモートリボジトリ名 + URL一覧
```

**詳細表示**

```bash
$ git remote show リモートリポジトリ名
```

**追加する**

```bash
$ git remote add リモートリポジトリ名 リポジトリURL
```

**コミットIDを確認**

```bash
$ git ls-remote リモートリポジトリ名 HEAD # 最新コミットID
```

**リモートブランチを更新**

```bash
$ git push # ローカルブランチと同名のリモートブランチがある場合、対象のリモートブランチすべてを更新。危険だからあまりやらない方がいい。
$ git push リモートリポジトリ名 ローカルブランチ名 # ローカルブランチと同名のリモートブランチを更新
$ git push リモートリポジトリURL ローカルブランチ名 # 違うリモートリポジトリを更新
$ git push -f # 強制プッシュ
```

**URL変更**

```bash
$ git remote set-url リモートリポジトリ名 URL
```

**ローカルに登録しているリモートリポジトリ情報削除**

```bash
$ git remote rm リモートリポジトリ名
```

**リモートブランチを削除**

```bash
$ git push リモートリポジトリ名 :リモートブランチ名
# または
$ git push -d リモートリポジトリ名 リモートブランチ名
```

## デフォルトのpushの設定

**matchingモードの場合（Git1.x系のデフォルト）**

```bash
$ git config push.default matching
$ git push
```

同名のブランチがリモートリポジトリに存在する場合、全てのブランチをpushする。意図しないpushをする可能性がありとても危険。

**upstreamモードの場合**

```bash
$ git config push.default upstream
$ git push
```

カレントブランチに追跡ブランチが設定されている場合に、追跡ブランチに対して pushする。

**currentモードの場合**

```bash
$ git config push.default current
$ git push
```

カレントブランチを、同名のリモートブランチにpushする。

**simpleモードの場合（Git2.x系のデフォルト）**

```bash
$ git config push.default simple
$ git push
```

カレントブランチと同名のリモートブランチが存在する、かつそれらが追跡関係にある場合に、追跡ブランチに対してpushする。

## タグ

```bash
$ git pull --tags # リモートのタグを全部取得
$ git tag # ローカルで管理しているタグ一覧
$ git checkout -b ブランチ名 refs/tags/タグ名 # タグからブランチを作成
$ git tag -a タグ名 ハッシュ値 # 特定のコミットにタグをつける
$ git push origin タグ名 # 特定のタグをpush
$ git push origin --tags # リモートに反映していないタグをすべてpush

$ git tag 新しいタグ名 コピー元タグ名 # 新しい名前をつけて新規タグ作成
$ git tag -d タグ名 # タグを削除
```

## ログ

```bash
$ git log
$ git log --grep 文字列 # 特定のコミットメッセージを検索
```

## コミット履歴を検索

```
$ git show ハッシュ値 # 特定のコミットのログを見る
$ git branch --contains ハッシュ値 # コミットが含まれているブランチを検索
```