git rebaseで、コミットの順番を入れ替える!
git rebase でコミットの順番を入れ替える!
タイトルにもある通り、
コミットの順番を入れ替えたい!
という時にはrebaseを使うと可能になります!
(rebaseは出来ることがありすぎるので、今回は入れ替えだけです)
説明用に、以下のように編集し、コミットしています。
1回目のコミット
1回目のコミット
2回目のコミット
1回目のコミット
2回目のコミット
3回目のコミット
1回目のコミット
2回目のコミット
3回目のコミット
4回目のコミット(今までの内容は削除しました)
4回目のコミット
5回目のコミット
4回目のコミット
5回目のコミット
この様にファイルを5回編集し5回コミットしました。
次に
$ git log --oneline
上記のコマンドを使用してコミットログを表示します。
その結果が以下になります。
02b6a6a (HEAD -> aho) 5回目のコミット
a772dcc 4回目のコミット
1f4e715 3回目のコミット ←消したいコミット
7e8a71e 2回目のコミット
8146b44 1回目のコミット
5回コミットしていることが確認できますね。
最後にコミットしたのが
02b6a6a (HEAD -> aho) 5回目のコミット
こちらになので現在のファイルの状態は↓になります。
4回目のコミット
5回目のコミット
今回は3回目のコミットを最新の状態にする。
という事をやっていきます。
どういうことかというと、
今は5回目のコミットが最新の状態になっていますが
3回目のコミット
1回目のコミット
2回目のコミット
3回目のコミット
ファイルは↑の状態に、
ログは↓の状態にしたい。ということです。
$ git log --oneline
1f4e715 3回目のコミット
915e642 5回目のコミット
1093030 4回目のコミット
7e8a71e 2回目のコミット
8146b44 1回目のコミット
実行手順 git rebase -i コミットID
まずは以下のコマンドを実行します
$ git rebase -i コミットID
[コミットID]に指定したコミット以降を編集できるようになります。
今回は、3回目のコミットを最新の状態にしたい!ということなので、
2回目のコミットIDを記述しています。
$ git rebase -i 7e8a71e
実行後の表示がこちら。
pick 1f4e715 3回目のコミット
pick a772dcc 4回目のコミット
pick 02b6a6a 5回目のコミット
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.
#
Commands:
以下にいろいろなrebaseの使い方が表示されていますが,
今回は順番を入れ替えるだけなので、なにも使いません。
3回目のコミットを最新にするということなので、
一番最後に持ってきます。("I"を入力するとvimがINSERTモードになり入力できる様になります。)
pick a772dcc 4回目のコミット
pick 02b6a6a 5回目のコミット
pick 1f4e715 3回目のコミット
こんな感じに変更後保存します。
保存方法はINSERTモードを終了し(キーボードの"esc"ボタンを押してから、":wq"と入力して"enterボタン"。)
今回だと、3回目のコミットを最後に変更したので、
2回目のコミットの次が4回目のコミットになるわけです。
そうすると、2回目のコミットと、4回目のコミットで同じ部分を編集しているので、コンフリクトが起こります。
Auto-merging hogehoge
CONFLICT (content): Merge conflict in hogehoge
error: could not apply 1093030... 4回目のコミット
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 1093030... 4回目のコミット
↑ターミナル上の表示
2回目のコミットを優先するんか、4回目のコミットを優先するんか、どっちも反映するんかどれにするねん。
という様な内容ですね。
エディター上の表示↓
<<<<<<< HEAD
1回目のコミット
2回目のコミット
=======
4回目のコミット(今まで作成したものは削除)
>>>>>>> 1093030... 4回目のコミット
正直、最新を3回目のコミットにするので
何でもいいっちゃ何でもいいのですが、
今回は順番通りに4回目を採用することにします。
注意!ここで2回目のコミットを選ぶと4回目のコミットは消えます!
色々試していて気付きました。笑
まあ、4回目のコミットを採用しないのなら別にいらないよね。という事だと思います。笑
厳密にはコミットメッセージ(内容は何もない)は残すか、コミットを消すかの操作を任意で行うことができます。
残す場合は
$ git commit --allow-empty
消す場合は
$ git rebase --skip
コマンドを実行します。
(全部実行時のターミナルに書いてます)
作業に戻ります。
コンフリクトを解消した後、以下のコマンドで状態を確認してみます。
$ git status
実行後の表示がこちら。
interactive rebase in progress; onto 7e8a71e
Last command done (1 command done):
pick 1093030 4回目のコミット
Next commands to do (2 remaining commands):
pick 915e642 5回目のコミット
pick 1f4e715 3回目のコミット
(use "git rebase --edit-todo" to view and edit)
You are currently rebasing branch 'aho' on '7e8a71e'.
(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: hogehoge
no changes added to commit (use "git add" and/or "git commit -a")
いろいろ書いてますが今回はこちら。
(fix conflicts and then run "git rebase --continue")
コンフリクトを解消したら
$ git rebase --continue
してねと書いてあるので実行します。
$ git add 〇〇
が事前に必要です。
実行結果がこちら。
4回目のコミット
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# interactive rebase in progress; onto 7e8a71e
# Last command done (1 command done):
# pick 1093030 4回目のコミット
# Next commands to do (2 remaining commands):
# pick 915e642 5回目のコミット
# pick 1f4e715 3回目のコミット
# You are currently rebasing branch 'aho' on '7e8a71e'.
#
# Changes to be committed:
# modified: hogehoge
ここでコミットメッセージを変更したければできます。
("I"を入力するとvimがINSERTモードになり入力できる様になります。)
今回は変更せずにいきます。
そうすると、またコンフリクトがおきます。
$ git rebase --continue 日 11/ 1 05:35:41 2020
[detached HEAD edfea2c] 4回目のコミット
1 file changed, 1 insertion(+), 2 deletions(-)
Auto-merging hogehoge
CONFLICT (content): Merge conflict in hogehoge
error: could not apply 1f4e715... 3回目のコミット
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 1f4e715... 3回目のコミット
4回目のコミットの次は5回目のコミットですが、
4回目と5回目のコミットは同じ箇所を変更していないので
コンフリクトが起きず通過してます。
なので実質5回目のコミットと3回目のコミットがコンフリクトが起きているということです。
ログを確認してみると
2d1d08f (HEAD) 5回目のコミット
edfea2c 4回目のコミット
7e8a71e 2回目のコミット
8146b44 1回目のコミット
現在は5回目のコミットにいることが確認できますね。
エディター上では下記の様になっています。
<<<<<<< HEAD
4回目のコミット(今まで作成したものは削除)
5回目のコミット
=======
1回目のコミット
2回目のコミット
3回目のコミット
>>>>>>> 1f4e715... 3回目のコミット
最新の状態を3回目のコミットにすることが目的だったので、
エディター上で3回目のコミットを反映すると完成です。
一応ログを確認。
$ git log --oneline
1f4e715 3回目のコミット
915e642 5回目のコミット
1093030 4回目のコミット
7e8a71e 2回目のコミット
8146b44 1回目のコミット
できてますね!!
今回はコミット履歴や、内容を消さない方向で進めていましたが
別に消してもいいから3回目のコミットを最新にしたい。
ということなら
3回目のコミットを最新にする=4、5回目のコミットはいらないので
削除して、実行しても同じ結果になります。
$ git rebase -i 7e8a71e
を実行して、pick
→d(drop)
に変更します。
d(drop)
は削除です。
pick 1f4e715 3回目のコミット
d a772dcc 4回目のコミット
d 02b6a6a 5回目のコミット
変更したら:wq
で保存してログを確認します
$ git log --oneline
1f4e715 (HEAD -> aho) 3回目のコミット
7e8a71e 2回目のコミット
8146b44 1回目のコミット
こんな感じになっていれば完成です!
他にもrebase
はいろいろできて、超便利です!
ただ、便利が故に理解せずに使うと痛い目をみます。
この時はまだ、rebaseの恐ろしさを知りませんでした。。。。。。。
その時の恐怖体験はまた別の記事で。。。。。。
思い出すだけでも胃が痛い。笑
Discussion