【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ブランチのログ

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

    Merge pull request #41 from プロジェクト名/feature/***

    Aを実装(プルリクのタイトル)
...

ローカルのdevelopブランチのログ

#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ブランチに戻す(同じ状態にする)コマンドを実行しました。

# developブランチ上で実行
team_project % git reset --hard origin/develop

developブランチの差分がなくなり、再度rails db:migrateするとschemaが更新され、マージしていないモデルの実装が追加されました。原因はこれではありませんでした

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

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

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
# 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ブランチに切り替えました。

# 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ブランチの状態にしました。

# 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 .コマンドで回避します。

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ブランチでしかできませんでした。)

# 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
2.gitでいろいろ取り消したい

7.最後に

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