LoginSignup
9
8

More than 5 years have passed since last update.

大きすぎるPullRequestを小分けにする

Last updated at Posted at 2018-04-24

解決したい問題

色々試しながら実装してて、ふと気づくと...

ヤベェ差分がめちゃくちゃデカい。。。

スクリーンショット 2018-04-04 11.12.53.png
自分がレビュアなら殺意を覚えるレベル:skull:

なんとか小分けにできないものか:confused:

どうしよう?

cherry-pickとかで分けられないかと考えてみたものの、
試行錯誤しながらcommitしてたので、ログを見ても何を取ればいいのかさっぱり。

そんな折、先駆者を発見:exclamation:
https://brewing-bits.com/blog/splitting-big-merges/
これ参考に、git rebase -iを使って細かくしてみる。

大まかな流れ

  1. 作業ブランチを新たにmasterから切る
  2. 大量の変更の中から、何がしかひとまとまりの変更をピックアップして1のブランチにcommit
  3. PR(PullRequest)作成
  4. 今いるブランチをベースに新たにブランチを切る
  5. 同じようにひとまとまりの変更をピックアップし、commit
  6. PR(PullRequest)作成
  7. 4〜6を繰り返し

使うコマンド

git log --oneline --reverse HEAD..huge_update_branch -- path/to/file/
で関係するコミットのhash commit-messageを取得。
git rebase -i HEAD
のエディタにコピペして、rebaseの各種コマンドで「このコミット使う」や「使わない」やを決める。

...まぁやってみよう:fist:

トライ

ここで、どでかい変更を加えたブランチをhuge_update_branchとする。

まずはmasterからブランチを切る。

git checkout -b huge_update_branch_part1
ここにピックアップしたひとまとまりの変更を加える。

何をピックアップするか、diffを眺める。。。:eyes:
末端のutility的なクラスからにしよう。

開始〜

git log --oneline --reverse HEAD..huge_update_branch -- path/to/util/

ababcdcd1 utilに新しいメソッド追加したよ 
efefghgh2 ファイル名変えたよ
ijijklkl3 タイポ

大量変更があるブランチ(huge_update_branch)と今のブランチ(huge_update_branch_part1)との差分ログの中で、path/to/file/以下のファイルに変更があったコミットログが一覧で出た。
これをrebaseで使う。

git rebase -i HEAD

  1 noop
  2 
  3 # Rebase abcdefg..abcdefg onto abcdefg (1 command)
  4 #
  5 # Commands:
  6 # p, pick = use commit
  7 # r, reword = use commit, but edit the commit message
  8 # e, edit = use commit, but stop for amending
  9 # s, squash = use commit, but meld into previous commit
 10 # f, fixup = like "squash", but discard this commit's log message
 11 # x, exec = run command (the rest of the line) using shell
 12 # d, drop = remove commit
 13 #
 14 # These lines can be re-ordered; they are executed from top to bottom.
 15 #
 16 # If you remove a line here THAT COMMIT WILL BE LOST.
 17 #
 18 # However, if you remove everything, the rebase will be aborted.
 19 #
 20 # Note that empty commits are commented out

当然差分ないので、最初はこんな感じのが出る。
さっきのコミットログ貼る。

  1 ababcdcd1 utilに新しいメソッド追加したよ 
  2 efefghgh2 あ、utilの新しいメソッドにコミットし忘れ
  3 ijijklkl3 タイポ
  4 # Rebase abcdefg..abcdefg onto abcdefg (1 command)
  5 #
  6 # Commands:
(以下略)

各コミットに対してコマンド決める。

  1 pick ababcdcd1 utilに新しいメソッド追加したよ 
  2 fixup efefghgh2 あ、utilの新しいメソッドにコミットし忘れ
  3 fixup ijijklkl3 タイポ
  4 # Rebase abcdefg..abcdefg onto abcdefg (1 command)
  5 #
  6 # Commands:
(以下略)

一つ目のログだけ使う(pick)ようにして、あとの二つは一つ目にがっちゃんこ(fixup)。

できたー。
スクリーンショット 2018-04-24 8.43.48.png

次〜

あとは基本的にこれの繰り返し。

今いるブランチ(huge_update_branch_part1)から新しいブランチを切る。
(ここあまりよくわかってない。masterからでも良いような気もする。)
git checkout -b huge_update_branch_part2

じゃあ次はmodelへの変更だけをピックアップ。
git log --oneline --reverse HEAD..huge_update_branch -- path/to/model/

同じように、rebaseのエディタにペロッと貼ってコマンド指定。
git rebase -i HEAD

  1 pick ababcdcd1 modelのrecord変えたよ 
  2 pick efefghgh2 リネーム
  3 fixup ijijklkl3 タイポ
  4 drop mnmnopop4 もう一つリネーム
  5 drop qrqrstst5 revert:もう一つリネーム
  6 # Rebase abcdefg..abcdefg onto abcdefg (1 command)
  7 #
  8 # Commands:
(以下略)

以降繰り返して。。。

細かいPRに分けられたー!ヽ(´▽`)ノワーイ♪
スクリーンショット 2018-04-24 8.43.48.png
スクリーンショット 2018-04-24 10.23.45.png
スクリーンショット 2018-04-24 10.23.52.png
スクリーンショット 2018-04-24 10.23.58.png
スクリーンショット 2018-04-24 10.24.06.png
スクリーンショット 2018-04-24 10.24.14.png
スクリーンショット 2018-04-24 10.24.23.png
スクリーンショット 2018-04-24 10.24.32.png
スクリーンショット 2018-04-24 10.24.53.png
スクリーンショット 2018-04-24 10.25.42.png
スクリーンショット 2018-04-24 10.26.36.png
スクリーンショット 2018-04-24 10.26.44.png
スクリーンショット 2018-04-24 10.26.52.png
スクリーンショット 2018-04-24 10.27.01.png
スクリーンショット 2018-04-24 10.27.11.png
スクリーンショット 2018-04-24 10.27.21.png
全16弾に及ぶPR完成:sweat_smile:
これもこれで大変だけど、さくさくマージは進んだ。
(途中1000行越えもあるが、renameとかがメインなので数字ほどのインパクトはない)

感想など

  • 変更の仕方によっては割とコンフリクト出る。
    • 地道に解決するしかない。
    • これ割と辛い。
    • なので、ベストプラクティスは、「こんなことになる前に、なんとかしろ
  • テストコードへの変更は、最後のPRでまとめて直したのは楽で良かった。
    • ということは、最後のPRまではビルドはコケ続ける。
    • ので、いきなりmasterではなく、developブランチへ全てのPRを投げた。
    • で、全部揃ってテストも通った段階でmasterへのPR。
  • 「最終的にテスト通ればいいよね」は、ある程度テストカバレッジ無いと怖すぎる。
  • 参考ページに書いてあったgit show-branchは上手く使えなんだ。
    • 「大元のブランチと差分ないか確認するだけなら、git diffでもよくね?」と思って使わなかった。
  • 複数クラスに同じように修正したけど、バラバラでコミットしちゃったりした時も、整理してからpushできるから、git rebase -iイイネ!
9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8