Gitについて Part2

## はじめに
Gitについて調べたことを全3回でまとめていきます。

Part2のゴールは、ブランチとマージを使用した
管理を理解することです。

そのうえで、今回は以下の3点を説明します。
1. ブランチとマージを理解する
2. リベースを理解する
3. タグ付け、及びスタッシュを理解する

参考にしたサイト [git book]([https://git-scm.com/book/ja/v2)
（図はこちらのサイトから引用しています。ご了承ください）

## ブランチとマージ
・ブランチ
　複数人が並行して開発するための機能
　コミットを指すポインタのことで、「.git/refs」の中に作成したブランチが入っている
　
・マージ
　他人が変更した結果を自分のリポジトリへ更新する

・コンフリクト
　同じファイルに対して異なる編集を行った場合に発生

・リベース
　merge以外で、変更履歴を整えるやり方

## ローカルブランチについて
・git init コマンドでデフォルトのブランチ名「master」が作られる。
　また、最初にコミットした時点で、直近のコミットを指す 「master」 ブランチが作られる。

## リモートブランチについて
・git clone コマンドでデフォルトのリモート名「origin」が作られる。
　また、リモートブランチは<リモート名>/<ブランチ名>で表す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418028/7d00b27c-ff72-6655-fba1-25ae5d6f6033.png)


## HEADについて
・今どのブランチで作業しているかを指すポインタが「HEAD」
　新しいブランチ「testing」を加えたとしても、現在のブランチは「master」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418028/43a53501-f5ee-96a6-024f-973461295c9c.png)


## Gitコマンド ～～
### git branch
・ブランチに関するコマンド

```bash:bash
・ブランチを追加する
$ git branch <ブランチ名>

・ブランチの一覧を表示
$ git branch -a

・現在作業しているブランチ名を変更
$ git branch -m <ブランチ名>

・ブランチを削除
$ git branch -d <ブランチ名> # masterにマージされていない変更がある場合、削除されない
$ git branch -D <ブランチ名> # masterにマージされていない変更がある場合でも、強制的に削除する
```
### git checkout
・ブランチを切り替える

```bash
$ git checkout <既存のブランチ名>　　
$ git checkout -b <新しいブランチ名> # 新規ブランチを作成して、ブランチを切り替える 
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418028/0b319a5c-1523-d16a-bc3c-cea2693c191e.png)

### git merge
・作業中のブランチに他のブランチの変更をマージする

```bash:bash
$ git merge <リモート名/ブランチ名>

Ex.
$ git merge origin/master
$ git merge testing
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418028/839e4cb0-ce70-46c8-9b8b-008c6d298630.png)


## Gitコマンド　～リベース～

### git rebase
・ブランチのコミットした内容を変更する

#### 複数のブランチのコミットを統合する
```bash:bash
$ git rebase <統合するブランチ名>

Ex.
$ git checkout experiment # リベースするブランチに移動
$ git rebase master       # リベースする
$ git checkout master     # masterブランチに移動
$ git merge experiment    # mergeする
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418028/de665c29-0fb4-260a-12e3-b87a8417f04b.png)

[こちら](https://liginc.co.jp/web/tool/79390)の説明が分かりやすい
※ただし、GitHubにプッシュしたコミットをリベースしないこと！

#### 複数のコミットをやり直す
1.git rebase コマンドを実行

```base:base
$ git rebase -i <コミットID>

Ex.
$ git rebase -i HEAD~3 
```
「HEAD~」 と 「HEAD^」 の違いは[こちら](https://yu8mada.com/2018/05/30/the-difference-between-head-caret-and-head-tilde-in-git/)が理解しやすい。
「HEAD~n」は n番目の親と
「HEAD^n」は n階層目の1番目の親を指す

2.編集したいコミットの箇所を 「pick」 -> 「edit」に修正、保存する

```text
pick 17a8f6d add rebase2
pick 58fbb09 add first.txt
pick fbe208b add second.txt and third.txt
↓　
edit 17a8f6d add rebase2
pick 58fbb09 add first.txt
pick fbe208b add second.txt and third.txt
```
3.内容を修正し、再度コミット、最新のコミットに戻る

```
$ git commit --amend
$ git rebase --continue
```

#### コミットを並び替える or 削除する
1.git rebase コマンドを実行

```base:base
$ git rebase -i <コミットID>

Ex.
$ git rebase -i HEAD~3
```

2.並び替えたいコミットの順番に修正、保存する

```text
pick 17a8f6d add rebase2
pick 58fbb09 add first.txt
pick fbe208b add second.txt and third.txt
↓　
pick 6abcce7 add first.txt
pick 12b7ed6 add rebase2.txt
pick 9aa4bb6 add second.txt and third.txt
```

#### 複数のコミットをまとめる
1.git rebase コマンドを実行

```base:base
$ git rebase -i <コミットID>

Ex.
$ git rebase -i HEAD~3
```

2.編集したいコミットの箇所を 「pick」 -> 「squash」に修正、保存する
　3つのコミットをまとめる場合

```text
pick 6abcce7 add first.txt
pick 12b7ed6 add rebase2.txt
pick 9aa4bb6 add second.txt and third.txt
↓　
pick 6abcce7 add first.txt
squash 12b7ed6 add rebase2.txt
squash 9aa4bb6 add second.txt and third.txt
```
3.コミットメッセージを修正する

#### コミットを複数のコミットに分割する
1.git rebase コマンドを実行

```base:base
$ git rebase -i <コミットID>

Ex.
$ git rebase -i HEAD~1
```

2.編集したいコミットの箇所を 「pick」 -> 「edit」に修正、保存する
　3つのコミットに分割する場合

```text
pick 6abcce7 add first.txt
↓　
edit 6abcce7 add first.txt
```
3.コミットを修正する

```base:base
$ git reset HEAD 
$ git add XXX.txt
$ git commit -m "add XXX.txt"
$ git add YYY.txt
$ git commit -m "add YYY.txt"
$ git rebase --continue
```

## コンフリクトの解決方法
・同じ箇所を変更してそれぞれのブランチでコミットする。

```bash:bash
$ git status
　・
　・
　・
　both modified:   sample.txt
　・
　・
　・
```

・ファイルの中身を確認する
  <<<<<<< HEAD 「HEADブランチで追加した内容」　======= 
　「testingブランチで追加した内容」 >>>>>>> testing
　となる。

```text:sample.txt
git_tutorial用のファイルです。
2回目のコミットです。
3回目のコミットでーす。
マージ用のコミットです。
conflict.
<<<<<<< HEAD
コンフリクトを追加
=======
conflict.
>>>>>>> testing

↓
git_tutorial用のファイルです。
2回目のコミットです。
3回目のコミットでーす。
マージ用のコミットです。
conflict.
コンフリクトを追加
conflict.
```

・git add, git commitを行う

## GitHubへのプルリクエスト
### プルリクエスト
変更内容を他人に確認したのち、マージする

### プルリクエストの手順
・ローカルリポジトリ
1. masterブランチを最新に更新
2. プルリクエスト用のブランチを作成
3. ファイルを変更
4. 変更をコミット/GitHubへプッシュ

・リモートリポジトリ（GitHub）
1. プルリクエストを確認する
　1. Pull requests
　2. base:master
　3. compare:pull_request　にする
　4. pull_requestブランチからmasterブランチにプルリクエストを送る
　5. Create pull request
　6. Reviewersにレビュワーを追加する
2. 再戻し/承認
3. プルリクエストをマージ
4. 最後にプルリクエスト用のブランチを消す

## タグ付け
### git tag
・タグ付けに関するコマンド

```base:base
・タグを作成する
$ git tag <タグ名> <コミットID>
$ git tag -a <タグ名> <コミットID> -m <"メッセージ">

・タグの一覧を表示
$ git tag

・タグのコミットデータを表示する
$ git show <タグ名> 
```

・タグをリモートリポジトリでも共有する
　GitHubのreleasesに共有したタグが格納されている

```
$ git push <リモート名> <タグ名>
$ git push <リモート名> --tags
```

## 自身の作業を隠す、消す（スタッシュ）
### git stash
・変更内容をコミットせず、一時的に隠す
  （ステージングエリア、及びワークディレクトリの変更内容を隠す）

```bash:bash
・スタッシュする
$ git stash

・メッセージをつけてスタッシュする
$ git stash save <メッセージ>

・スタッシュ中のリストを確認する
$ git stash list

stash@{0}: WIP on master: 2ca844a add third.txt
stash@{1}: WIP on master: 2ca844a add third.txt

・スタッシュのリストの変更ファイルを確認する
$ git stash show stash@{番号}    # スタッシュの変更ファイルを表示する
$ git stash show -p stash@{番号} # スタッシュのファイルの変更箇所を表示する

・スタッシュを適用する
$ git stash apply              # 最新のスタッシュを適用（ワーキングディレクトリのみ）
$ git stash apply --index      # 最新のスタッシュを適用（ステージングエリアを含む） 
$ git stash apply stash@{番号} # 指定した番号のスタッシュを適用（index指定可能）

・スタッシュを削除する
$ git stash drop              # 最新のスタッシュを削除 
$ git stash drop stash@{番号} # 特定のスタッシュを削除 
$ git stash clear             # すべてのスタッシュを削除
 
```

## Back Number
[Gitについて Part1](https://qiita.com/Shohei_miyasako/items/b353273f5941278241d9)