git rebase とは?
開発をしていると、個人の観点では見えていなかった部分を指摘され、修正を行うという作業が度々発生します。先日も開発をしていて、このようなことがありました。
内容としては、Webページのフォームを追加するというものだったのですが。
私「フォームの追加が完了しました」 ↓ 先輩「この関数はまとめてしまいましょうか」私「修正しました」 ↓ 先輩「この入力値チェックは正規表現で書きましょうか」私「修正しました」 ↓ 先輩「このパターンだとエラーになりませんか?」私「修正しました」 ↓ 私「すみません、エラーチェックが一箇所実装していなかったので修正しました」 …私「修正しました」 …私「修正しました」 |
書いていて観点漏れとかそういうレベルではない気がしてきましたが、、、
私は毎回、これで問題ないと思ってコミット&プッシュをしていたので、
この開発によって ローカルもリモートも git のコミットログに不要な物が残りました。
一連の開発を追えた段階でこのブランチのコミットログはこのようになっていました。
この中で本当に必要なコミットは、たった2つだけです
- に URLのバリデーションを追加
- にメッセージ長バリデーションを追加
このように、コミットが沢山あったときに
本当に必要なコミットはたった一つだけだったとすると
そんな時にコミットの履歴を作り直したいと思いました。どうやら、
rebase という機能を使うと、それが実現できるみたいです。
ということで、今回初めて rebase という作業を行いました。
折角なので、その記録を記事として残します。
IntelliJ での rebase 作業
今回、この作業を IntelliJ (今回の場合は PyCharm) で行ってみました。
なお、この手順ですが、
公式ドキュメント
にはやり方が一応書いています。しかし、図が一枚もない上に、実際のUIとドキュメントで微妙に文言が違ったりして、正直分かりにくいです…
では、私が行った具体的な作業を書いていきます。
手順その0 ブランチを選択
まず、コミットをまとめたいブランチに移動しておきます
手順その1 まとめる際の起点となるコミットを選択
Version Control 画面にて、ここからのコミットをまとめたいというブランチを右クリックして 「Copy Revison Number」でリビジョン番号をコピーします。
この画面は設定を変えていなければ、IDE の一番下にあるメニューから開くことができます。
手順その2 Rebase 画面で対象を入力
上部メニューの「VCS」 → 「Git」 → 「Rebase」を選び、Rebase 画面を開きます。
「Interactive」にチェックが入っていることを確認したら、「Onto」の項目に先ほどコピーしたリビジョン番号をペーストします。
必要であれば「Merge Strategy」を変更します(私はこの辺りよく分かっていないので、defaultとしました)。
そして、「Rebase」をクリックします。
手順その3 必要なコミットを選択
ちょっと時間がかかったあと、Rebase Commits の画面が開きます。
Actionの項目でどのような操作を行うのかを選択します。
使用するのは次の2つです
- pick
- squash
「pick」を選択すると、そのコミットを残すことが出来ます。
「squash(=潰す)」を選択すると、そのコミットを他のコミットにまとめることができます。修正などの履歴として残す必要のないコミットを Squash しま
す。
また、画面右側の矢印を使い、時系列を入れ替えてコミットをまとめることもできます。ページAの修正をして、ページBの修正をして、またページAの修正をして…となっているものを、綺麗にページAについてのものと、ページBのもののコミットにまとめることができます。が、よくわからず入れ替えると盛大にコンフリクトが起こり、どうしようもない状態になるので、使う際は注意が必要です。(経験談)
手順その4 コミットを作り直す
なにか問題があれば、Merge 画面になります。
問題がなければ、新しくまとめたコミットのメッセージを入力する画面が出ます。Please enter the commit message for your changes. の上に新しいメッセージを入れましょう。何行もありますが、全部消して一言だけのメッセージにしてしまって大丈夫だと思います。
「Resume Rebasing」でsquashしたコミットの箇所だけ、メッセージの編集を行います。
これで、Rebase は完了します。
確認
git log コマンド で改めてコミット履歴を見てみると、先ほどのコミットが消えて pick したコミットだけになっています。
この状態でリモート push すると、コミットログがおかしなことになっていると怒られて受け付けてくれません。
- リモートのブランチを一旦削除する
- 別名のブランチとして push する
- push -f で強制プッシュする
のいずれかの方法を取ると push できます。
後日談
上のような記事を社内限定で公開したところ、何名かの方からコメントを頂きました。
意見として多く頂いたのが、下記のような「そのコードになった過程や理由が分からなくなる」といったものでした。
(以下、許可を得て転載)
主観ですが、コミットログは以下のルールで考えています。
- 社内案件の場合
- 個人で開発&コミットした後に自分で誤りに気づいたものはログを綺麗にしてもOK(プルリクエストの前に一度綺麗にする派の人とか)
- レビュー等、他人の指摘で気づいた修正はコミットログに残す
- これ以外(OSS等)
- プルリクエストの前までにログは綺麗にしよう
って感じですね。GitHubの内容をコミットログ含め成果物としてのみ考えるなら、コミットログも綺麗なほうがいいかもしれません。
しかし会社として考えた場合には、どういった経緯でその成果物が作られたのかも大切な資産だと思うので、コミットログは改ざんしないで欲しいなぁ。
会社として一つのプロダクトを作っていく上で、共有すべき情報としてコミットログというのは大きいため、必要以上のリベースは行わない方がいいのかな?と改めて考えされられました。
(それでも「修正」→「やっぱり直ってなかったので修正」みたいなコミットは歴史から消したい…)
この記事を書いた人
- まだまだ気持ちは新人です。
最近書いた記事
- 2018.03.23Windows のコンソールを使いやすくしよう
- 2018.02.23GitHubでPullRequestが出ると、Jenkinsでテストした後でEC2に自動デプロイする設定を行った
- 2018.02.21Jenkins にパラメータを渡して、Packer で引数付きビルドを行う
- 2018.01.10それ、キーボードマクロで出来ますよ(Emacs)