はじめに
作業中、過去のコミットで行った変更を元に戻す場面があった。
そのまま作業を続けてしまったが、コミット履歴がわかりにくくなっていたので、不必要になったコミットだけ削除した。
git rebase とは
今回はgit rebase
コマンドを使ってコミット履歴を修正した。
base は名詞では土台、動詞では基礎付けるという意味で、これに再起的なニュアンスを表す接頭語 re が付いている。
イメージとしては、ある枝を切り離してから別の場所に接木し直す、といった感じ。
C' - D' - E' feature
/ → - A - B - C - C' - D' - E' master
- A - B - C master rebase を実行
上の例では-C'-D'-E'
のブランチを master の先端にくっ付けている。
今回の状態
私が rebase 機能を使ったとき、作業していた feature ブランチは以下のような状態。
- A - B - C - D - E - F feature
↑
このコミットだけ消したい
E と F のコミットは残したまま、不必要な D のコミットだけ削除したかった。
そこで、-E-F
の部分を -A-B-C
の先端に移すことにした。
実行した手順
まずはgit log
で、上図の C のコミットID を取得。
git log
commit 69ec236a8acf4659bd0962a47ca843fb9623bchf (HEAD -> feature)
Author: ユーザ名 <メールアドレス>
Date: Fri Jul 2 10:13:21 2021 +0900
F のコミット(残したい)
commit ag28517f035f1b143d356335271de88c5c7136ef
Author: ユーザ名 <メールアドレス>
Date: Fri Jun 25 17:04:23 2021 +0900
E のコミット(残したい)
commit 52b81060a47202777d94aebd84cad9ae3eda20b8
Author: ユーザ名 <メールアドレス>
Date: Fri Jun 25 16:53:33 2021 +0900
D のコミット(不必要)
commit 59e85460e245827455d94oafe84cad9ae3xvm33l ←この文字列をコピー
Author: ユーザ名 <メールアドレス>
Date: Fri Jun 25 16:53:33 2021 +0900
C のコミット(ここに付け足したい)
ブランチ付け替え先のコミットID が分かったら、以下のコマンドを実行。
git rebase -i 取得したコミットID
-i
オプションを付けて実行すると、個々のコミットに対して編集や削除などを行うことができる。
このオプションがない場合、移動元のコミット全てが自動的に移植される。
今回は D のコミットを消した上で rebase したいので、-i
オプションを使用。
すると下のように出力される。
pick 52b8106 D のコミット(不必要)
pick ag28517 E のコミット(残したい)
pick 69ec236 F のコミット(残したい)
# Rebase 59e8546..69ec236 onto 59e8546 (3 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
D のコミットのみ削除したいので、最初の 3行を次のように書き換えた。
drop 52b8106 D のコミット(不必要)
pick ag28517 E のコミット(残したい)
pick 69ec236 F のコミット(残したい)
コンフリクトが無ければこれで完了。
今回はVSCode を開くとコンフリクトが発生していたので解消した。
コンフリクトを全て解消したら、git add
コマンドで変更内容をステージングエリアへ。
これで D のコミットの削除は完了したので、git rebase --continue
コマンドで次の E のコミットへ移動。
以下のように、残る 2つのコミットのみが表示される。
pick ag28517 E のコミット(残したい)
pick 69ec236 F のコミット(残したい)
E と F のコミットは残したかったため、pick
のまま続行した。
もし E や F も修正したい場合は、D のときと同様pick
を書き換えれば良い。
コミットを削除ではなく編集する際は、git add
ではなくgit commit --amend
を使うことに注意。
git rebase --continue
を続け、全てのコミットの処理が正常に終わると以下のように出力された。
Successfully rebased and updated refs/heads/feature.
git log
で履歴を確認すると、期待通り D のコミットのみが無くなっていた。
git log
commit 69ec236a8acf4659bd0962a47ca843fb9623bchf (HEAD -> feature)
Author: ユーザ名 <メールアドレス>
Date: Fri Jul 2 10:13:21 2021 +0900
F のコミット(残したい)
commit ag28517f035f1b143d356335271de88c5c7136ef
Author: ユーザ名 <メールアドレス>
Date: Fri Jun 25 17:04:23 2021 +0900
E のコミット(残したい)
commit 59e85460e245827455d94oafe84cad9ae3xvm33l ←この文字列をコピー
Author: ユーザ名 <メールアドレス>
Date: Fri Jun 25 16:53:33 2021 +0900
C のコミット(ここに付け足したい)
おわりに
rebase 機能は知識として知っていたつもりだったけれど、実際に使うとなると全く分かってなかった。
あと rebase を同一ブランチ上で実行できることも初めて知った。