【Rails】マージしていないにも関わらずdevelopのマイグレーションが更新された話

### 1.背景
現在、オンラインスクールにて共同開発に参加しており、タスクをGitHubのissueで管理しながら
アプリを制作しています。
担当箇所の実装が終わると、マージする前にメンバー間のプルリクをローカルで確認してからメンターさんに確認して頂くようにしています。

ブランチ管理は以下のように行っており、`feature`ブランチで作業→`develop`ブランチでマージという流れです。

| ブランチ名 | 目的 | 備考 |
| :-- | :-- | :--|
| develop | 開発用 | 機能実装用のブランチはここから切る |
| feature/*** | 機能実装用 | 派生元はdevelop |

今回、マージしていない実装分の一部がdevelopブランチで更新されており、追加するかstash（回避）しないとブランチの切り替えができない状態でした。それを解消したのでまとめました。

### 2.環境
- mac.os バージョン10.15.6
- Ruby 2.7.2
- Rails 6.1.3.1
- psql (PostgreSQL) 12.6

### 3.今回起きていたこと
#### ①origin/developとdevelopで差分が生じていた
状況を把握するために、`origin/develop(リモートのdevelop)`と`develop（ローカルのdevelop）`のコミットログを確認しました。

origin/developブランチのログ

```ruby
#origin/developブランチを確認
team_project % git fetch
commit コミット番号 (HEAD -> origin/develop, origin/HEAD)
Merge: マージしたコミット番号
Author: 人 <アドレス>
Date:   日付

    Merge pull request #41 from プロジェクト名/feature/***
    
    Aを実装（プルリクのタイトル）
...
```
ローカルのdevelopブランチのログ

```ruby
#developブランチで確認
team_project % git log
commit コミット番号 (HEAD -> develop)
Author: 人 <アドレス>
Date:   日付
    
    Bを実装

commit コミット番号
Merge: マージしたコミット番号
Author: 人 <アドレス>
Date:   日付

    Merge pull request #41 from プロジェクト名/feature/***
    
    Aを実装（プルリクのタイトル）
...
```
ローカルのdevelopブランチ上で`Bを実装`というコミットをしており、ローカルのdevelopブランチが1つ進んでいる状態なので（本来は自分の作業ブランチでコミットが進んでいる以外は**origin/developとdevelopのコミットログは同じでないといけない**）、`origin/developブランチに戻す（同じ状態にする）`コマンドを実行しました。

```ruby
# developブランチ上で実行
team_project % git reset --hard origin/develop
```
developブランチの差分がなくなり、再度`rails db:migrate`するとschemaが更新され、マージしていないモデルの実装が追加されました。原因はこれではありませんでした:sob:

#### ②featureブランチでマイグレーションの更新をした後にリセットすることを忘れていた

プルリクの確認を行うため、ローカルのdevelopブランチにプルリク分を取り込みます。

```ruby
team_project % git switch develop
# プルリク番号とブランチ名を確認
team_project % git fetch origin pull/プルリク番号/head:ブランチ名
team_project % git switch feature/***

# 今回はrails gでモデルとマイグレーションファイルを作成しているのでmigrateする
team_project % rails db:migrate
```

```ruby
# feature/***ブランチで確認
team_project % rails db:migrate:status
database: team_project_development
 Status  Migration ID  Migration Name
--------------------------------------------------
  up   年月日時 　　　　 Create A
  up   年月日時         Create B
  up   年月日時         Devise create users
  up   年月日時         Devise create admin users
  up   年月日時         Create C 　★今回実装して増えた分
```
statusを確認すると、5つマイグレーションファイルが確認できます。
動作確認を行った後、そのままdevelopブランチに切り替えました。


```ruby
# developブランチで確認
team_project % rails db:migrate:status
database: team_project_development
 Status  Migration ID  Migration Name
--------------------------------------------------
  up   年月日時 　　　　 Create A
  up   年月日時         Create B
  up   年月日時         Devise create users
  up   年月日時         Devise create admin users
  up   年月日時         ********** NO FILE ********** ★今回実装して増えた分
```
developブランチではマイグレーションファイルは存在しないのでNO FILEと表示されますが、statusは引き継がれます。その結果、developブランチで`rails db:migrate`をした際に`db/schema.rb`にCモデルの内訳が更新されてしまった...ということでした。

### 4.マイグレーションを修正する対処法
#### パターン1:データベースを空にして再度入れ直す
今回の共同開発のデータはcsvデータを使用しており、またテストコードを手入力している訳ではないので
**データを空にする→再度入れ直すこと**で最新のdevelopブランチの状態にしました。

```ruby
# developブランチで行う
team_project % rails db:migrate:reset
team_project % rails db:seed
team_project % git status
# 差分が出てこなくなった
On branch develop
Your branch is up to date with 'origin/develop'.

nothing to commit, working tree clean
```
#### パターン2:rollbackを使う
featureブランチで行います。
developブランチ上で変更分を取り込むもしくはstash（回避）をしないとブランチの切り替えができないため、`git checkout .`コマンドで回避します。

```ruby
team_project % git checkout feature/***
error: Your local changes to the following files would be overwritten by checkout:
        db/schema.rb
Please commit your changes or stash them before you switch branches.

# 変更を回避する
team_project % git checkout .
team_project % git checkout feature/***
# featureブランチで行う
team_project % rails db:rollback
team_project % rails db:migrate:status
database: team_project_development
 Status  Migration ID  Migration Name
--------------------------------------------------
  up   年月日時 　　　　 Create A
  up   年月日時         Create B
  up   年月日時         Devise create users
  up   年月日時         Devise create admin users
  # 今回実装して増えた分(Create C)が消える

# developブランチに切り替えてmigrateを行う
team_project % git checkout develop
team_project % rails db:migrate
```
こちらのrollbackは**マイグレーションファイルが存在しない場合は実行ができない**ので、
今回のケース(↓)だとdevelopブランチではエラーとなります。（そのため、featureブランチでしかできませんでした。）

```ruby
# developブランチで確認
team_project % rails db:migrate:status
database: team_project_development
 Status  Migration ID  Migration Name
--------------------------------------------------
  up   年月日時 　　　　 Create A
  up   年月日時         Create B
  up   年月日時         Devise create users
  up   年月日時         Devise create admin users
  # rollbackしたくてもできない...
  up   年月日時         ********** NO FILE ********** 
```
### 5.まとめ
マージしていない場合でもマイグレーションファイルのstatusが引き継がれると知らなかったため、勉強になりました。
これからもエラーが出た際も一つ一つ検証し、解決したいと思います。

### 6.参考
1.[リモートリポジトリfetch](https://backlog.com/ja/git-tutorial/stepup/15/)
2.[gitでいろいろ取り消したい](https://qiita.com/tani-shi/items/3419600447292abf6c79)

### 7.最後に
記事の感想や意見、ご指摘等あれば伝えていただけるとありがたいです。
読んでいただき、ありがとうございました。