よく使うgitコマンドメモ

自分が仕事とかでよく使ってるgitコマンドのメモ。
([追記]ファイル名と書いてますが、パス含めてのファイル名です。)
なんとなく、いつも使ってる流れ順

## fetch
```
$ git fetch origin
```
リモートリポジトリの状態をローカルに持ってくる。
上記だと分かりにくい&誤解がありそう。
自分は、ローカルで持ってる「リモートの(ブランチとかの)構成図」を最新のリモートの構成図に更新する的なイメージを持ってる。

上記コマンド例の場合、originというリモートリポジトリの状態を持ってくる。

## branch
```
$ git branch
```
ローカルに存在するブランチの一覧を表示する。
出力は、こんな(↓)感じ

```
  ID227_deleteAfunction
* ID228_addBfunction
  ID232_fixCfunction
  master
```
先頭に`*`が付いてるブランチが、現在いるブランチ

また

```
$ git branch 新規ブランチ名
```
で、現在いるブランチを元に、新しいブランチを作成できる。(移動はしない。)
新規ブランチ名のブランチが存在する場合、エラーになる。(作成できない。)
ただ自分は、あまりこのコマンドは使ってない。(checkoutのほうを使う。)


### -Dオプション
```
$ git branch -D ブランチ名
```
branchコマンドに-Dオプションをつけると、ブランチの削除ができる。
もちろんだが、自分が現在いるブランチは削除できない。
自分は、よく、気付いたらローカルブランチが大量になってるので、たまのタイミングで古いのを一気に消す。

### -Mオプション
```
$ git branch -M 新ブランチ名
```
branchコマンドに-Mオプションをつけると、ブランチのリネームができる。
上記のコマンドでは、現在いるブランチの名前を新ブランチ名に変更する。
自分ネームセンスが無いんで、よく後から変える。

## checkout
```
$ git checkout ブランチ名
```
ブランチの切り替えを行う。現在いるブランチが、ブランチ名に指定したブランチになる。
存在しないブランチを指定するとエラーになる。

```
$ git checkout ファイル名
```
とした場合、指定したファイルを現在いるブランチの最新commit状態に戻す。
書き換えたけど、やっぱ全部元に戻したい時に使える。

### -bオプション
```
$ git checkout -b 新規ブランチ名 元にするブランチ名
```
新規にブランチを作り、そのブランチに移動する。
元にするブランチ名は、ローカルでもリモートでもOK。
リモートを指定する場合は、リモート名/ブランチ名。`origin/master`こんな感じ。
また、元にするブランチ名を省略した場合、
現在いるブランチを元にして、新規ブランチを作り、そのブランチに移動する。

変更点がある場合(`git status`で、`Untracked files`以外がある時)、
その変更点が、元にするブランチと競合しない場合、変更を維持したまま、新規ブランチを作成し、そのブランチに移動する。
変更点が、元にするブランチと競合する場合、エラーになって、新規ブランチの作成もされない。

## status
```
$ git status
```
現在のブランチでのファイルの状態の一覧を表示する。
出力は、こんな(↓)感じ

```
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   src/A.hs
        deleted:    src/E.hs
        renamed:    src/F.hs -> src/G.hs
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
  (commit or discard the untracked or modified content in submodules)

        modified:   src/main.hs
        modified:   src/B.hs
        deleted:    src/D.hs
        modified:   config/settings.yml
        modified:   stack.yaml

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        app.prof
        app.log
        src/C.hs
```
読んだとおりだが、

 - `Changes to be committed:`は、ステージされた変更
`git rm`や、`git mv`、既に`git add`したファイルがここに書かれる。

 - `Changes not staged for commit:`は、ステージされて無い変更
現在いるブランチの最終commitから変更のあった、まだ`git add`されてないファイルがここに書かれる。

 - `Untracked files:`は、追跡してないファイル
現在いるブランチで、追跡していないファイルがいる場合、ここに書かれる。

変更の種類は、(これまた読んで字の通りだが)

- `modified`が中身に変更点のあるファイル

- `deleted`が削除されたファイル

- `renamed`が名前が変更されたファイル(`git mv`使った時)

## diff
```
$ git diff
```
現在のブランチの`Changes not staged for commit`にあるファイルの中身の差分を表示する。
この場合、変更のある全てのファイルの差分が表示される。

```
$ git diff ファイル名
```
とすれば、指定したファイルの差分のみ表示される。

## add
```
$ git add ファイル名
```
ファイルの変更を登録する。
`git status`で`Changes not staged for commit:`にあったファイルをcommit前に`git add`する必要がある。
この登録(?)のことをステージングというらしい。(よくわかってない勉強不足)
自分はいつも、`git status`で出てきたファイル名をスペース区切りで`git add `の後ろにコピペしてきて実行する。(パス間違えとかなくなるから)

新規追加したファイルは、`Untracked files`にいるので、忘れないように！(戒め)

## reset
```
$ git reset ファイル名
```
ファイルの変更の登録を取り消す。
`git add`するなどして登録した`Changes to be committed:`を取り消す。

## rm
```
$ git rm ファイル名
```

ファイルの削除。この場合、追跡が削除され、ファイルも削除される。
また自動で、削除したことが登録(ステージング)される。

### --cachedオプション
```
$ git rm --cached ファイル名
```
追跡のみ削除し、ファイルはその場に残す。

### 削除の取消
よく使うわけではないが、ちょっと手順があったんで、記述。
`git rm`で削除したファイルを元に戻すには、以下の手順を踏む。

1. 登録の取消

```
$ git reset HEAD ファイル名
```
　として、登録を取り消す。(`HEAD`が必要)
2. 削除の取消

```
$ git checkout ファイル名
```
として、ファイルを元に戻す。


## mv
```
$ git mv ファイル名 新ファイル名
```
ファイルの移動。この場合、ファイルのリネーム関係が登録されるので、変更点の追跡ができる。
また自動で、リネームしたことが登録(ステージング)される。

gitコマンドでなく、`$ mv ファイル名 新ファイル名`として、その変更を登録しまうと、
ファイル名のファイルを削除し、新ファイル名のファイルを追加したことになるので、変更点が追えなくなる(はず)ので、注意。

### リネームの取消
これもよく使うわけではないが、ちょっと手順があったんで、記述。
`git mv`でリネームしたファイルを元に戻すには、以下の手順を踏む。

1. リネーム後ファイルの登録の取消

```
$ git reset リネーム後ファイル名
```
　として、登録を取り消す。
2. リネーム前ファイルの登録の取消

```
$ git reset HEAD リネーム前ファイル名
```
　として、登録を取り消す。(`HEAD`が必要)
3. リネーム前ファイルの復元

```
$ git checkout リネーム前ファイル名
```
として、ファイルを元に戻す。


## commit
```
$ git commit
```

登録された変更(`git status`で`Changes to be committed`にあるファイル)をコミットする。
このコマンドを実行すると、エディタが開いて、変更のステータスが表示される。
そのファイルの先頭に書いた言葉が、コミットコメントになる。
ファイルを保存してエディタを終了すると、コミットが実行される。

### -mオプション
```
$ git commit -m コメント
```
コミットコメントを指定してコミットする。
この場合、エディタは開かず、コマンド実行後、すぐにコミットされる。

### 直前commitの修正
```
$ git commit --amend
```
で、直前のコミットをやり直せます。ただし、コミットIDは、変わるので注意。
こちらは、エディタが開く。
追加すべきファイルを追加し忘れた時などに使う。(よく追加し忘れる。)
ファイルの追加や、修正があった場合、先に、addしてから`commit --amend`する。

コメントの修正などは、

```
$ git commit --amend -m コメント
```
とする。
こちらはエディタが開かれない。

## log
```
$ git log
```
現在いるブランチのcommitログをみる。
CommitIDを調べたり、どんなブランチかを調べるのに使ってる。

## push
```
$ git push origin プッシュするブランチ名
```
ローカルのブランチを、リモートに反映する。(この場合、origin)

・リモートに、同じブランチ名のブランチがない場合は、新しく同じ名前のリモートブランチが作成される。

・リモートに、同じブランチ名のブランチがある場合で、そのリモートのブランチが先に進んでいた場合、エラーになる。
この場合、プッシュ前に、そのリモートブランチを`pull (fetch+merge)`してくる必要がある。

・リモートに、同じブランチ名のブランチがある場合で、そのリモートのブランチが先に進んでいなかった場合は、そのままプッシュされる。

・リモートに、同じブランチ名のブランチがある場合で、そのリモートのブランチに自分の権限が無かった場合、エラーになる。
その場合は、~~管理者に訴えるかあきらめる。~~ 別の名前のブランチとしてプッシュし、PullRequestを出して、管理者にマージしてもらう。

### 別名のブランチとしてプッシュする
```
$ git push origin プッシュするブランチ名:リモートでのブランチ名
```
上記のように、プッシュするローカルブランチ名の後に、`:`に続けて、リモートでのブランチ名を指定できる。
ただ、ローカルと、リモートでブランチ名変わって分かりづらい&ミスり易いのでお勧めしない。応急処置のためだけにしておいたほうがいいかと。


## rebase
```
$ git rebase リベース先ブランチ名
```
現在いるブランチの親を変える。枝分かれの元を変える。
この場合、リベース先のブランチとの差分コミット全てがリベースされる。
リベースしたコミットは、全てCommitIDが変わるので注意。

### -iオプション
```
$ git rebase -i リベース先ブランチ名
```
`-i`をつけることで、リベースするコミットを選べる。
このコマンドを実行すると、エディタが開く。
エディタでは、

- リベースするコミットの選択
- リベースするコミットのコメント修正
- リベース時に直前のコミットと融合するコミットの選択

等が行える。(他にもあるが、使ったこと無いのでわからない。)

自分は、`rebase`は、機能単位でブランチを切ってPullRequestを出す時に、
masterにリベースする感じでよく使う。
あとは、適当に名前つけて段階的に`commit`したものを、まとめたり、コメント変えたりするのに使っている。

リベースは、コミットログを大きく変えるので、基本的に、リモートにプッシュしたあとのブランチでは、行わないように気をつける。(自分しか関係ないならいいが...)

リベース時に、競合が発生することもあるので注意。
競合解決後、rebaseを再開するには、

```
$ git rebase --continue
```
「やっぱリベースやめよ」となったら

```
$ git rebase --abort
```


## merge
```
$ git merge マージするブランチ名
```
現在いるブランチに、別のブランチのcommitを取り込む。
commit単位での取り込みなら`git pick`があるが、あちらは、CommitIDが変わるので注意。
こちら`merge`は、基本的に、CommitIDはそのまま。

マージするブランチ同士で、変更点に競合が無ければ、無事自動マージされる。
変更点に競合があれば、残念。mergeが途中で止まり、
競合を解決したのち、

```
$ git merge --continue
```
で、mergeを再開する。

「競合したわ。マージやめよ(白目)」ってときは、

```
$ git merge --abort
```

### 競合の解決
競合(コンフリクト)したファイルを編集し、競合を消してから、
`add`して`commit`。

ちなみに、自分は、

```
$ git config --global alias.conflicts '!git ls-files -u | cut -f 2 | sort -u'
```
として、

```
$ git conflicts
```
で、競合したファイルの一覧を表示できるようにしている。
(よく競合したファイルがわからなくなるので。)