内容
gitでrebaseというコマンドがあります、そのメモです。
用途
複数のコミットを1つにする
複数のコミットを1つにまとめます。
ブランチのベースを変更する(履歴を綺麗に保つ)
例えば、自分が作業しているブランチから分岐した元のブランチ(例えば、main ブラン チ)に新しい変更が加わった場合、それらの変更を自分のブランチに取り込み、まるで自分のブランチが最新のmain ブランチから分岐したかのように履歴を再構成します。
状況例
以下の状況を想定します。
・作業ブランチに複数のコミットがある
・作業ブランチはmainブランチより作っている
・mainブランチは更新されている
上記状況に対し、作業ブランチに対し、最新のmainより派生した形で、作業ブランチのコミットを一つにし対応する(作業ブランチはmainの更新を取り込んでいる)
指定された状況に対応するための手順は、まず作業ブランチのコミットを1つにまとめた後、main
ブランチの最新の変更を作業ブランチに取り込む、という流れになります。以下に、具体的なステップを示します。
ステップ1: 作業ブランチのコミットを1つにまとめる
-
作業ブランチにチェックアウトします。
git checkout <作業ブランチ名>
-
インタラクティブリベースを開始して、まとめたいコミットを選択します。ここで、
HEAD~N
はまとめたいコミットの数によって調整します。git rebase -i HEAD~N
インタラクティブリベースのエディタが開いたら、最初のコミット以外を
squash
またはs
に変更して、1つにまとめます。
○以下まとめた例です。
・ブランチ例
2つのブランチ(main、test_br)があります。
apple@appurunoMacBook-Pro git_practice % git br
main
* test_br
・複数あるコミットをま止めます、3つのコミットを1つにします。
apple@appurunoMacBook-Pro git_practice % git rebase -i HEAD~3
・こういう画面になるのでまとめたい箇所にs
もしくはsquash
を入力します。
pick 6786fd0 test3
s 047021b test4
s 584eb1f test5
# Rebase 87db741..584eb1f onto 87db741 (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 [-C | -c] <commit> = like "squash" but keep only the previous
# commit's log message, unless -C is used, in which case
# keep only this commit's message; -c is same as -C but
# opens the editor
# 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
-- INSERT --
・エディタ処理終了後、以下でコミットが1つになります。
[detached HEAD ad69c9e] test3
Date: Sat Mar 16 16:41:50 2024 +0900
1 file changed, 3 insertions(+)
Successfully rebased and updated refs/heads/test_br.
(rebase前)
ブランチ(test_br)に、mainから作成後、コミットが3つあります。
apple@appurunoMacBook-Pro git_practice % git log --graph --all
* commit 584eb1f1169847ff05000feba849de51d6f916b7 (HEAD -> test_br)
| Author: sawa <you@example.com>
| Date: Sat Mar 16 16:53:08 2024 +0900
|
| test5
|
* commit 047021b5121c21e7aa344a36c37d7afe1e0b7cdd
| Author: sawa <you@example.com>
| Date: Sat Mar 16 16:42:41 2024 +0900
|
| test4
|
* commit 6786fd094577da7a51a1e6df1083adc51a367513
| Author: sawa <you@example.com>
| Date: Sat Mar 16 16:41:50 2024 +0900
|
| test3
|
| * commit 9cbca0e69e64000df4abf1dc1bf649f64b8b0821 (main)
|/ Author: sawa <you@example.com>
| Date: Sat Mar 16 16:50:26 2024 +0900
|
| testmain修正
(rebase後)
ブランチ(test_br)に、mainから作成後、コミットが1つになりました。
apple@appurunoMacBook-Pro git_practice % git br
main
* test_br
apple@appurunoMacBook-Pro git_practice % git rebase -i HEAD~3
[detached HEAD ad69c9e] test3
Date: Sat Mar 16 16:41:50 2024 +0900
1 file changed, 3 insertions(+)
Successfully rebased and updated refs/heads/test_br.
apple@appurunoMacBook-Pro git_practice % git log --graph --all
* commit ad69c9e9038ed127fb5d8f9b597d976914ca29e4 (HEAD -> test_br)
| Author: sawa <you@example.com>
| Date: Sat Mar 16 16:41:50 2024 +0900
|
| test3
|
| test4
|
| test5
|
| * commit 9cbca0e69e64000df4abf1dc1bf649f64b8b0821 (main)
|/ Author: sawa <you@example.com>
| Date: Sat Mar 16 16:50:26 2024 +0900
|
| testmain修正
|
* commit 87db74113093458be833699f194b264d87a2ae6d
| Author: sawa <you@example.com>
| Date: Sat Mar 16 16:39:33 2024 +0900
|
| test2
|
* commit 84195f5d4fd4468624869f7353ab7af6534d5e11
ステップ2: main
ブランチの最新変更をローカルのmain
に取り込む
-
main
ブランチにチェックアウトします。git checkout main
-
main
ブランチを最新の状態に更新します。git pull origin main
ステップ3: 作業ブランチにmain
ブランチの変更を取り込む
-
再び作業ブランチにチェックアウトします。
git checkout <作業ブランチ名>
-
main
ブランチの最新の変更を作業ブランチに取り込みます。これにはgit rebase
を使用します。git rebase main
この操作により、作業ブランチが
main
ブランチの最新の変更から派生したかのように履歴が再構成されます。この過程でコンフリクトが発生した場合は、それを解決し、git rebase --continue
でリベースを続けます。
・コンフリクトが出て対応した例です。
apple@appurunoMacBook-Pro git_practice % git rebase main
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
error: could not apply ad69c9e... test3
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply ad69c9e... test3
ファイルが以下のようになっているので修正。
テスト1
テスト2
<<<<<<< HEAD
testmain修正
=======
テスト3
テスト4
テスト5
>>>>>>> ad69c9e (test3)
・修正後のstatus
apple@appurunoMacBook-Pro git_practice % git status
interactive rebase in progress; onto 9cbca0e
Last command done (1 command done):
pick ad69c9e test3
No commands remaining.
You are currently rebasing branch 'test_br' on '9cbca0e'.
(fix conflicts and then run "git rebase --continue")
(use "git rebase --skip" to skip this patch)
(use "git rebase --abort" to check out the original branch)
Unmerged paths:
(use "git restore --staged <file>..." to unstage)
(use "git add <file>..." to mark resolution)
both modified: test.txt
no changes added to commit (use "git add" and/or "git commit -a")
apple@appurunoMacBook-Pro git_practice % git add test.txt
apple@appurunoMacBook-Pro git_practice % git status
interactive rebase in progress; onto 9cbca0e
Last command done (1 command done):
pick ad69c9e test3
No commands remaining.
You are currently rebasing branch 'test_br' on '9cbca0e'.
(all conflicts fixed: run "git rebase --continue")
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: test.txt
・ステージングにあげます。
apple@appurunoMacBook-Pro git_practice % git add test.txt
・ステージング後(add後)のstatusです。
apple@appurunoMacBook-Pro git_practice % git status
interactive rebase in progress; onto 9cbca0e
Last command done (1 command done):
pick ad69c9e test3
No commands remaining.
You are currently rebasing branch 'test_br' on '9cbca0e'.
(fix conflicts and then run "git rebase --continue")
(use "git rebase --skip" to skip this patch)
(use "git rebase --abort" to check out the original branch)
Unmerged paths:
(use "git restore --staged <file>..." to unstage)
(use "git add <file>..." to mark resolution)
both modified: test.txt
no changes added to commit (use "git add" and/or "git commit -a")
apple@appurunoMacBook-Pro git_practice % git add test.txt
apple@appurunoMacBook-Pro git_practice % git status
interactive rebase in progress; onto 9cbca0e
Last command done (1 command done):
pick ad69c9e test3
No commands remaining.
You are currently rebasing branch 'test_br' on '9cbca0e'.
(all conflicts fixed: run "git rebase --continue")
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: test.txt
・リベースを続けます。
完了するとsuccessのメッセージが出ます。
apple@appurunoMacBook-Pro git_practice % git rebase --continue
[detached HEAD c76f24e] test3 test4 test5 コンフリクト解消
1 file changed, 3 insertions(+)
Successfully rebased and updated refs/heads/test_br.
・ブランチtest_brは、あたかもmainの最新から修正した履歴になりました。
apple@appurunoMacBook-Pro git_practice % git log --graph --all
* commit c76f24e58450336e8eadb6f616fd7d606ca0e5ac (HEAD -> test_br)
| Author: sawa <you@example.com>
| Date: Sat Mar 16 16:41:50 2024 +0900
|
| test3
| test4
| test5
| コンフリクト解消
|
* commit 9cbca0e69e64000df4abf1dc1bf649f64b8b0821 (main)
| Author: sawa <you@example.com>
| Date: Sat Mar 16 16:50:26 2024 +0900
|
| testmain修正
|
* commit 87db74113093458be833699f194b264d87a2ae6d
| Author: sawa <you@example.com>
| Date: Sat Mar 16 16:39:33 2024 +0900
|
| test2
|
* commit 84195f5d4fd4468624869f7353ab7af6534d5e11
Author: sawa <you@example.com>
ステップ4: 変更をリモートの作業ブランチに反映させる
リベース後の変更をリモートブランチに反映させるために、以下のコマンドを実行します。リベースを行った場合、履歴が変更されているため、通常のプッシュでは拒否される可能性があります。そのため、--force
オプション(より安全な--force-with-lease
オプションを推奨)を使います。
git push origin <作業ブランチ名> --force-with-lease
これで、作業ブランチのコミットが1つにまとめられ、さらにmain
ブランチの最新の変更が取り込まれた状態になります。これにより、作業ブランチがmain
の最新の状態から派生したように見え、その上で作業ブランチの変更が1つのコミットとして適用される形になります。
参考記事