Gitでコミットした後に、「コミットする順番を間違えた」「コミット履歴をわかりやすい順番に整理したい」ということがあります。
このような場合は、git rebase -i(インタラクティブリベース)を利用すると、過去のコミットの順番を入れ替えることができます。
例えば、次のようなコミット履歴があるとします。
commit A
↓
commit B
↓
commit C
↓
commit D
git rebase -iを使用すると、次のようにコミットの順番を変更できます。
commit C
↓
commit B
↓
commit A
↓
commit D
この記事では、git rebase -iを用いてコミットの順番を入れ替える方法について、初心者向けにわかりやすく解説します。
あわせて読みたい
「git rebaseコマンドの意味や基本的な使い方」については、以下の記事で詳しく説明しています。興味のある方は下記のリンクからぜひチェックをしてみてください。
git rebase -iでコミットの順番を入れ替える方法
まず、現在のコミット履歴を確認します。
今回は、次のようなコミット履歴があるとします。
$ git log --oneline --reverse
...(略)
e988a35 commit A
216dd56 commit B
8019534 commit C
35b43cf (HEAD -> main) commit D
--reverseオプションを付けているため、古いコミットから新しいコミットの順番で表示されています。
今回は、git rebase -iを使用してcommit Aとcommit Cの順番を入れ替え、次の順番に変更してみましょう。
commit C
commit B
commit A
commit D
コミットの順番を入れ替える手順は、次のとおりです。
git rebase -iコマンドを実行する- テキストエディタでコミットの順番を入れ替える
git logコマンドでコミットの順番を確認する
それぞれの手順について順番に説明します。
git rebase -iコマンドを実行する
git rebase -i(または、git rebase --interactive)コマンドを実行します。
git rebase -i HEAD~~~~
# 以下のコマンドでも可能
git rebase --interactive HEAD~~~~
git rebase -i HEAD~4
git rebase --interactive HEAD~4
上記のコマンドは、HEADから4つ分のコミットを対象にinteractive rebaseを開始するコマンドです。
HEAD~~~~とHEAD~4は、どちらも現在のHEADから4つ前のコミットを表しています。
例えば、今回のコミット履歴を簡単に表すと次のようになります。
○ --- commit A --- commit B --- commit C --- commit D
↑ ↑
編集対象 HEAD
git rebase -i HEAD~4を実行すると、HEAD~4より後にある直近4つのコミットであるcommit A、commit B、commit C、commit Dが編集対象になります。
つまり、直近4つのコミットを編集したい場合はHEAD~4、直近3つのコミットを編集したい場合はHEAD~3のように指定します。
テキストエディタでコミットの順番を入れ替える
git rebase -i HEAD~4を実行すると、Gitで設定されているテキストエディタが開き、対象となる4つのコミットが表示されます。
例えば、次のように表示されます。
pick e988a35 commit A
pick 216dd56 commit B
pick 8019534 commit C
pick 35b43cf commit D
# Rebase b8a1a26..35b43cf onto b8a1a26 (4 commands)
(以下略)
git rebase -iの編集画面では、コミットが適用される順番に上から並んでいます。
今回はcommit Aとcommit Cの順番を入れ替えたいので、行そのものを次のように並べ替えます。
pick 8019534 commit C
pick 216dd56 commit B
pick e988a35 commit A
pick 35b43cf commit D
# Rebase b8a1a26..35b43cf onto b8a1a26 (4 commands)
(以下略)
コミットの順番を変更するだけであれば、先頭のpickを変更する必要はありません。pickの行そのものを希望する順番に並べ替えます。
並べ替えが完了したら、ファイルを保存してテキストエディタを終了します。
使用するテキストエディタや保存・終了方法は、Gitの設定や利用している環境によって異なります。
例えば、Vimが起動した場合は、iキーでインサートモードに切り替えて編集し、編集後にEscキーを押します。その後、:wqと入力してEnterキーを押すと、保存してVimを終了できます。
テキストエディタを閉じると、Gitが指定した順番でコミットを適用し直します。
git logコマンドでコミットの順番を確認する
rebaseが完了したら、git logコマンドを実行してコミットの順番を確認します。
今回も古いコミットから確認しやすいように、--reverseオプションを付けて実行します。
git log --oneline --reverse
例えば、次のように表示されます。
...(略)
feb2a9a commit C
39ef5ca commit B
4b9093c commit A
7603fb9 (HEAD -> main) commit D
変更前はcommit A、commit B、commit C、commit Dという順番でしたが、変更後はcommit C、commit B、commit A、commit Dとなり、commit Aとcommit Cの順番が入れ替わっていることが確認できます。
git logに--reverseを付けている理由
通常、git log --onelineを実行すると、新しいコミットから古いコミットの順番で表示されます。
例えば、今回の例では次のように表示されます。
35b43cf (HEAD -> main) commit D
8019534 commit C
216dd56 commit B
e988a35 commit A
一方、git rebase -iの編集画面では、コミットを適用する順番である「古いコミットから新しいコミット」の順番で表示されます。
pick e988a35 commit A
pick 216dd56 commit B
pick 8019534 commit C
pick 35b43cf commit D
そのため、この記事ではコミットの順番を比較しやすくするために、git logへ--reverseオプションを付けています。
git log --oneline --reverse
--reverseを付けることで、git rebase -iの編集画面と同じように、古いコミットから新しいコミットの順番で履歴を確認できます。
コミットの順番を入れ替えるとコミットハッシュが変わる
git rebase -iでコミットの順番を入れ替えると、対象となるコミットのコミットハッシュが変わります。
変更前は次のようになっていました。
e988a35 commit A
216dd56 commit B
8019534 commit C
35b43cf commit D
しかし、コミットの順番を変更した後は、例えば次のようになります。
feb2a9a commit C
39ef5ca commit B
4b9093c commit A
7603fb9 commit D
これは、git rebaseが既存のコミットをそのまま移動しているのではなく、指定した順番でコミットを適用し直しているためです。
Gitのコミットハッシュは、コミットの内容だけではなく、親コミットなどの情報ももとに生成されます。そのため、コミットの順番を変更して親コミットが変わると、コミットハッシュも変わります。
git rebase -iによるコミットの並べ替えは、既存のコミット履歴を書き換える操作です。
コミットの順番を入れ替えるとコンフリクトする場合がある
コミット同士の変更内容によっては、順番を入れ替えたときにコンフリクトが発生することがあります。
例えば、次のようなコミットがあるとします。
commit A:sample.txtを作成する
commit B:sample.txtを修正する
この場合、commit Bはcommit Aで作成されたsample.txtが存在することを前提としています。
そのため、単純に次の順番へ変更しようとすると、正常にコミットを適用できない可能性があります。
commit B:sample.txtを修正する
commit A:sample.txtを作成する
このように、コミット同士に依存関係がある場合は、自由に順番を入れ替えられるとは限りません。
合わせて読みたい
git rebase -iでコンフリクトが発生した場合の対応方法については、以下の記事で詳しく説明しています。興味のある方は下記のリンクからぜひチェックをしてみてください。
本記事のまとめ
この記事では「git rebase -iでコミットの順番を入れ替える方法」について、以下の内容を説明しました。
git rebase -i HEAD~nで直近n個のコミットを編集対象にできる- コミットの順番を変更する場合は、
pickの行そのものを希望する順番に並べ替える git log --oneline --reverseを使用すると、古いコミットから順番に履歴を確認できる- コミットの順番を変更すると履歴が書き換えられ、コミットハッシュも変わる
- コンフリクトした場合は
git rebase --continue、中止する場合はgit rebase --abortを使用する
お読みいただきありがとうございました。
合わせて読みたい
git rebase -iではコミットの順番を変更する以外にも、複数のコミットを1つにまとめたり、過去のコミットメッセージを変更したりできます。
それぞれの方法については、以下の記事で詳しく説明しています。