【Git/GitHub 共同開発】知っておきたいコンフリクト解消とコードレビューの基本

## 概要

業界未経験からエンジニア転職を支援するオンラインサロン「転職クエスト」にて、Railsアプリ共同開発を行った機会がありました。

そこで、ファシリテーターを務めさせてもらった際に、開発をすすめる上で全員のネックになっていたことがありました。

``Git/GitHubの共同開発的な使い方がわからない。。。``

なので、開発を進めるファシリテーターとして、``Git/GitHubをこうやって使おうぜ！``というマニュアルを用意しておこうと考えました。

本記事では``共同開発 初心者さんたちに向けたGit/GitHubのフロー``について紹介します！

```:想定読者
1. アプリの個人開発のためにGit/GitHubを使ったことはある
2. コンフリクト解消のやり方を知りたい！
3. コードレビューのやり方を知りたい！
```

<br>

## そもそも、どこがわかっていない？

``Git/GitHub を使って共同開発をする上で、ネックになる部分はどこか。``
考えるために、これまで行ってきたGit/GitHubの使い方を振り返ってみます。

```:個人開発でのGit/GitHubの使い方
1. ローカルの master でブランチ切る
2. ブランチで作業しコミット
3. リモートにブランチをプッシュして、プルリク作成
4. GitHub 上でひとり LGTM を出して、ブランチを master にマージ
5. リモートの master をローカルの master にプル
6. 1~5を繰り返す
```

さて、``このフローでしか開発をしてこなかった人が、共同開発で Git/GitHub を使う際に、初めて経験するのはどんなことでしょうか？``

僕は、次のことだと考えました。

```:初めて共同開発をする人がやったことがないこと
1. 他の人のプルリクに対するコードレビュー
2. リモートの master の変更分を、ローカルの作業中ブランチにマージ
3. その際に起きるコンフリクト解消
```

特に2, 3については、``最新に更新された master からしかブランチを切ったことがない``というのが不安の理由として挙げられます。
``共同開発では、ブランチのマージによって常に master が更新されていきますので、その更新分を自分の作業中ブランチに反映する必要があります。``

ここに焦点を当てて、``共同開発でのコンフリクト解消、コードレビューの手順を紹介していきます！``

<br>

## コンフリクト解消の例

### 場面設定

```:設定
master から同じタイミングで2つのブランチを切る
  user1.branch1 : git checkout -b new,createアクションを実装
  user2.branch2 : git checkout -b edit,updateアクションを実装
```

ちなみに今回は``「ルーティングの設定」のみを取り扱っていきます``のであしからず。

<br>

### 1. [user1] branch1でnew,createのルーティングを設定

```ruby:branch1→routes.rb
+ resources :tweets, only: [:new, :create]
```

<br>

### 2. [user1] ローカルでコミット→リモートにブランチをプッシュ

```:branch1(new,createアクションを実装)
% git add .
% git commit -m "ルーティングにnew,createを追加"
% git push origin new,createアクションを実装
```

<br>

### 3. [user1] GitHub でプルリク作成→LGTM→マージ
ここは省略します。

<br>

### 4. [user2] branch2 で edit,update のルーティングを設定

```ruby:branch2→routes.rb
+ resources :tweets, only: [:edit, :update]
```

<br>

### 5. [user2] branch2 でコミット

```:branch2(edit,updateアクションを定義)
% git add .
% git commit -m "ルーティングにedit,updateを追加"
```

``※次にmasterブランチに切り替えますが、その前に必ずここでコミットをしてください！``

<br>

### 6. [user2] リモート master (branch1 merged) → ローカル master にプル

```
# master ブランチに移動
% git checkout master

# リモートの master をローカルの master に反映
% git pull origin master
```

【今はこういう状態】

* master → new, createアクション
* branch2 → edit, updateアクション
![demo](https://gyazo.com/df5998f0602266000cc3254bf6b90f49/raw)

<br>

### 7. [user2] ⚠コンフリクト ローカルmaster→branch2にマージ

```
# 作業中ブランチに移動
% git checkout edit,updateアクションを定義

# ローカルのmasterを作業中ブランチにマージ
% git merge master
```

【コンフリクト発生の様子】

* Head : 現在、作業中のブランチ (branch2)
* master : マージしたローカルのmasterブランチ

![demo](https://gyazo.com/f59a78e806c2528088971d80c44dd747/raw)

<br>

### 8-1. [user2] コンフリクトの解消

```:masterを基準に修正し、コンフリクト解消したらコミット
# 編集後
% git add .
% git commit
(デフォルト名 : Merge branch 'master' into edit,updateアクションを定義)
```

基本的に、``masterと作業中ブランチのログをどちらも残し、必要な形に変えればそれでOKです。``
コミットするとデフォルトで``このブランチがマージされたよ！``というコミット名になります。

【※コンフリクト解消後のGitHub Desktopの画面】
▶commit Mergeを押せば、デフォルトのコミット名でコミットされる...はず
![demo](https://gyazo.com/bb817c2f0a5917f805ad38a6844707a8/raw)

<br>

### 8-2. [user2] わからないのでとりあえずmergeを取り消したい！

もし``「コンフリクトこわい！ 一旦戻したい！」``という方にはこちら。

```:merge取り消し方法
% git merge --abort
```

【merge取り消しの様子】
▶コンフリクト状態がリセットされます
![demo](https://gyazo.com/9c0a3643afeefe2157a2a4eb98c7456c/raw)


<br>

### 9. [user2] branch2をリモートにプッシュ→プルリク

```branch2
% git push origin edit,updateアクションを定義
```

<br>

### 小括 : コンフリクト解消

* ローカルの作業中ブランチで最新の変更をコミット
* 誰かがブランチをマージしたリモートのmasterをローカルのmasterにプル
* ブランチを切り替え、masterをマージ
* 落ち着いてコンフリクト解消→修正したらコミット

続いて、コードレビューの仕方についてです。

``branch2「edit,updateアクションを定義」のプルリクに対してコードレビューをしましょう！``

<br>

## コードレビューの例

### 1. [レビュアー] プルリクURL→File changedタブ

ここで、ファイルの変更差分について確認します。
![demo](https://gyazo.com/055b82f7a2d353ae1063fecc2af7b8fe/raw)

<br>


### 2. [レビュアー] 変更希望箇所をクリック（複数行を選択も可能）
直してほしい部分を選択して、コメントをします。
![demo](https://gyazo.com/ab306d0f275434b0195b43a0ed1d97a5/raw)

<br>

### 3. [レビュアー] コメントをする→Start a review

選択した部分についてのコメントを記載して下さい。

<br>

### 4. [レビュアー] 複数ファイルにコメント→Finish your review
そのプルリクで気になった箇所にコメントを残し終えたら、Finish your reviewを押して下さい。
![demo](https://gyazo.com/2a48de67e127b604d849ef02d5156231/raw)

* conversationsに戻るとレビューが反映されています。
* これに従って、プルリク依頼者はローカルで編集 → push → 再レビュー依頼
![demo](https://gyazo.com/e0558a2b654a73e36e669caf9ab9f494/raw)

``▶今回、レビュアー側として「showアクションを追加して下さい」とコメントをしてみました。これに沿って「プルリク依頼者側」での対応をしてみましょう。``

<br>

### 5. [依頼者側] ローカルで編集してpush

```routes.rb
#showを追加
+ resources :tweets, only: [:new, :create, :show, :edit, :update]
```

```:local-branch2
% git add .
% git commit -m "showアクションを追加"
% git push origin edit,updateアクションを定義
```

<br>

### 6.[依頼者側] 修正報告
レビューに対して「showアクションを追加しました！」とコメントしましょう。
![demo](https://gyazo.com/a4f326588b7ed343fc9963764a1f63b0/raw)

<br>

### 7. [レビュアー] LGTM→Resolve conversation(レビュー完了)

* File changedを確認
* OKなら（コメントした後に）Resolve conversation
![demo](https://gyazo.com/94ad0c2148ec808c6f252870e99c7c41/raw)

<br>

### 8. 全部でLGTMならマージ
以上のフローを繰り返し、LGTMをもらえたらマージしましょう！

<br>

### 9.ローカルのmasterにプル

```
% git checkout master
% git pull origin master
```

masterの変更分 (mergeした部分) が次のように反映されます。
![demo](https://gyazo.com/14f3ba4979ac90518021171e08a72af2/raw)

<br>

### 小括 : コードレビュー

* プルリクのFile Changedで変更差分を確認
* 必要に応じてコメント
* コメントに対してローカルブランチで作業し再レビュー
* LGTMならマージ

以上が、GitHub flowによるコードレビューの基本手順です。

<br>

## まとめ

* Git/GitHubを共同開発で使うときは、最新masterを作業中ブランチにマージする場面がくる
* 変わった部分を冷静に判断し、コンフリクトを解消
* プルリクに対してはファイルの変更差分を確認し、レビューを行う

個人とは違う部分が多く、例を出して説明するのに苦労しました。
しかし、この機会に学んでみると``Gitってすごいな！``と改めて思いました。

引き続き、共同開発がスムーズに進むよう、学習を進めていきたいです！

<br>

## 参考
* <a href="https://www.udemy.com/course/unscared_git/">Udemy | Git： もう怖くないGit！チーム開発で必要なGitを完全マスター</a>
* <a href="https://qiita.com/takeokunn/items/5bc499121a21f8c5b990">Qiita | GitHubで共同開発のためのチュートリアル</a>
* <a href="">Qiita | Gitでやりたいこと、ここで見つかる</a>