Rebase and merge(リベース)
変更を統合する際に履歴を綺麗に整えるための機能です。
トピックブランチに対してリベースを行うと最新のベースブランチからあたかもトピックブランチを作成したかのような履歴状態を作り出すことができます。(ブランチの基点となるコミットを別のコミットに移動します。)
なぜ「リベース」と呼ぶのか?
親コミット(ベースとなるコミット)を新たしく付け替えるためです。
マージとリベースの違い
どちらもブランチの統合を行うという意味では同じ動作になります。履歴が一直線になる点が通常のマージとは異なる点になります。
マージとリベースで使い分けではどうすれば良いか。
基本方針
基本的には下記のような方針でマージとリベースを使い分けると良いでしょう。
リベースを使うケース
- プッシュしていないローカルの変更
マージを使うケース
- プッシュしてしまったローカルの変更
- コンフリクトが発生しそうな場合
コンフリクトが発生しそうかの判断方法
他の人の開発内容を確認すること
ローカルの変更をGitHubにプッシュしてプリリクエストを作成してしまう。
GitHubが親切にコンフリクトしているかどうか判定して表示してくれるのでそれで判定できます。
マージのメリット
作業の履歴を細かく残せる。(リベースかマージか選択する上で非常に重要なポイントです。)
マージを使う上で決め手となるのはこの点になります。
コンフリクトの解決が比較的簡単
リベースの場合は、コミットそれぞれにコンフリクトを解消していかなければならないが、マージの場合はまとめて解決すれば良いだけになります。
リベースのメリット
コミットの数が減るので履歴が簡素になる。(マージコミットの数が減る)なので、履歴を簡潔にすることが重視されている場合はリベースを選択すると良いでしょう。
リベースの特徴
メリット
- 仮にトピックブランチの数が増えたとしてもコミット履歴は常に一直線になり見やすくなります。
デメリット
- 過去のコミット履歴を改版する為コミット IDも変わってしまう為、普通の方法ではプッシュができなくなります。
- リベース先のブランチが複数コミットされている場合、1コミットずつ辿っていく挙動になるのでコンフリクトもその都度解消しなければならない点(マージの場合はコンフリクトの解消は1度だけで済みます。)
リベースの禁止事項
GitHubにプッシュしたコミットをリベースしてはいけない
GitHubに一旦プッシュしてしまったブランチをローカルでリベースして再度プッシュしようとしたらプッシュ自体ができなくなってしまいます。理由としては、「リモートで管理されているコミットの親子情報」と「ローカルで管理されているコミットの親子情報」が異なっているとリモートで認識されてしまうためです。
「git push -f」は絶対に使わないこと
これをするとローカルの履歴でリモートの履歴を完全に上書きできてしまいます。しかし、リモートの履歴が壊れてしまうことを意味するのでプッシュできないからと言ってこの手段をとるのは止めるようにしましょう。
コマンド
1 |
git rebase <コミットの基点としたいブランチ名> |
例
1.トピックブランチの基点をmasterブランチの先に付け替える。
コミットの基点がmasterブランチの先につけ変わるだけでなく、masterブランチの変更内容も取り込まれます。
1 2 |
git checkout <トピックブランチ> git rebase master |
2.masterブランチとトピックブランチをマージする。
ファストフォワードでのマージになるので新しくコミットが作られることはありません。(あくまで自分のブランチのコミットを他人が編集したコミットに向き先を変える動きになります。)
1 2 |
git checkout master git merge <トピックブランチ> |
コミットログを操作
コミットを修正したい場合は下記のコマンドを実行します。
1 |
git rebase -i <コミットID> もしくは HEAD~(やり直したいコミット数) |
すると下記のようにエディタ上に直近のコミットメッセージが表示されます。
1 2 3 |
pick コミットID コミットメッセージ1 pick コミットID コミットメッセージ2 pick コミットID コミットメッセージ3 |
コミットの順番の入れ替え
上記で表示されたエディタ上のコミットメッセージの順番を入れ替えるだけでコミットログの順番まで入れ替えることが可能です。
コミットをまとめる。
pick → squashに書き換えることでそのsquashに書き換えたコミットがpickに統合されます。
1 2 3 |
pick コミットID コミットメッセージ1 squash コミットID コミットメッセージ2 squash コミットID コミットメッセージ3 |
コミットを分割する。
分割したいコミットを下記のようにeditにします。
1 |
edit コミットID コミットメッセージ1 |
下記コマンドを実行します。
1 |
git reset HEAD^ |
すると最新のコミットが取り消されてステージングすらもされていない状態にファイルが戻るので、コミットを分割したいファイルごとにステージングに追加したりしてコミットを分割します。コミットが完了したら下記コマンドを実行します。
1 |
git rebase --continue |
この記事へのコメントはありません。