前置き
業務ではこまめにコミットをするようにしているのですが
「あの修正入れ忘れた!」
とか
「あ!コミットメッセージが誤字ってる!!」
とかありますよね(私はよくあります)
それを修正するためのコマンドを毎回調べるのも面倒なので備忘録のためまとめました
この記事が私と同じおっちょこちょいな人の手助けになれば幸いです🙇♂️
前提として本記事はリモートリポジトリにpushしてない状態での説明となります
push済みだとpush -f
を使わないと修正出来ないのでオススメしません
素直に新しくコミットを作ってpushしましょう
2個以上前のコミットの修正の説明をより理解しやすくするために
先に1個前のコミットの修正を説明しようと思います
そんなん知ってるわ!早く教えてくれーって方は
こちらをクリックでジャンプ出来ます
(そんな人はこんな記事見ないと思いますが…😅w)
1個前のコミットの修正
これはとてもシンプル
git commit --amend
を使います
どうやって使うか具体例で見てみましょう
↓
e.g.) さっきのコミットにBの変更を入れ忘れた
$ git log -1 --name-only
commit 509bab5e2596d88b469bb692b9dc23bdbc1287e7 (HEAD -> xxx, origin/xxx
Author: xxxx <xxx@test.com>
Date: Thu Mar 10 10:02:00 2022 +0900
Aを追加
app/views/A.html
$ git status
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: app/views/B.html
no changes added to commit (use "git add" and/or "git commit -a")
「あ!!今のコミットにBの変更を入れ忘れた!!」
落ち着いてください
直前のコミットの変更は簡単ですよ
このBの変更をさっきのコミットに滑り込ませるには
$ git add app/views/B.html
$ git commit --amend
これだけ!
他にも変更を入れたいなら普通に作業してgit add
すればOKです
git commit --amend
を実行すると
vimが立ち上がりコミットメッセージの修正画面が出ます
オプションなしでgit commit
を実行したときの画面ですね
ちょっと違うのは1個前のコミットメッセージが表示されています
つまりコミットメッセージの修正もここで出来るということです
今回は
- 入れ忘れたBの修正を追加
- 追加でCの修正も追加
- コミットメッセージを「AとBとCを追加した」に修正
これらの変更をしました
$ git add app/views/B.html app/views/C.html
$ git commit --amend
コミットメッセージの変更をしない場合はそのまま:q
で終了でOKです
コミットメッセージ修正画面を終了するとちゃんとコミットが追加されています
確認してみましょう
$ git log -1 --name-only
commit 509bab5e2596d88b469bb692b9dc23bdbc1287e7 (HEAD -> xxx, origin/xxx
Author: xxxx <xxx@test.com>
Date: Thu Mar 10 10:47:22 2022 +0900
AとBとCを追加した
app/views/A.html
app/views/B.html
app.views/C.html
ちゃんと追加出来ました👏
2個以上前のコミットの修正
いよいよ表題のgit rebase -i
を使います
ちょっとだけ手順が増えるので順を追って具体例で見てみましょう
↓
e.g.) 3個前のコミットにDの変更を入れ忘れた
先ほどの修正から少し開発も進みコミットも何個か積んできました
ふと思いつきます
「あの時のコミットにDの変更含めておけば良かった…」
$ git log --oneline
7d6fd8904 (HEAD -> xxx, origin/xxx 1個前のコミット
55074c0d9 2個前のコミット
509bab5e2 3個前のコミット <- これに含め忘れたい
.
.
なんと2個以上前のコミットの修正にはgit commit --amend
は使えません
「でもまた新たにコミットを作ると履歴が汚くなるし嫌だな…」
大丈夫です
ここではgit rebase -i(interactive mode)を使って
N個前のコミットを取得してから編集するという流れで修正できるので説明します
-iオプション
はgit rebase
をinteractiveモードで起動できるオプション
interactiveは対話とか対話式と訳されたりするようです
編集だけでなくコミットをまとめたり削除したりも出来ます
Rubyのコンソールであるirbもinteractive Rubyの略
たしかにコンソールってinteractiveですよね💡
1. 対象のコミットを取得
git rebase -i HEAD~N
(NにはN個前のコミットまで対象にするかで適宜数値を入れてください)
$ git rebase -i HEAD~3
を実行するとvimが立ち上がり
pick 0d2711298 3個前のコミット
pick 55074c0d9 2個前のコミット
pick 7d6fd8904 1個前のコミット
.
.
こんな感じでN個で指定した分だけコミットが取得出来ます
(今回はHEAD~3
を指定したので3個分のコミットが取得出来ましたね)
HEAD
は今現在自分が作業している場所を示すポインタです
つまり今現在の作業~3個前のコミットを取得したわけです
次に各コミットの左端にpick
となっている部分をedit
に変更します
(今回は3個前のコミットを修正したいので3個前のやつを変更ですよ)
edit 0d2711298 3個前のコミット
pick 55074c0d9 2個前のコミット
pick 7d6fd8904 1個前のコミット
:q
で終了すると
~/dir branch_name|rebase-i
$ |
こんな感じでプロンプトにrebase-i
と表示されるようになります
各々の環境によって表示のされ方には違いがあります
もしrebase-iなどのgitの状態が表示されないなら改善をオススメします
2. 実際に追加したい修正作業をする
ここまで来たらもう簡単です
ほとんど1個前のコミットの修正と同じです
追加し忘れたファイル以外にも新たに別の変更を追加してもOKです
何度も修正しなくていいように慎重に作業しましょうw
3. 修正をコミットし直す
修正作業が終わったのでいよいよコミットを修正します
といってもgit rebaseで該当コミットの編集モードに入っているので
git add .
git commit —-amend
お馴染みのこれでOKです
同じくコミットメッセージを修正する画面になるので
適宜操作して終了したらコミットの修正は完了です
(今回はコミットメッセージを3個前のコミットにDを追加
に変更してみました)
確認してみましょう
$ git log -1 --name-only
commit 509bab5e2596d88b469bb692b9dc23bdbc1287e7 (HEAD -> xxx, origin/xxx
Author: xxxx <xxx@test.com>
Date: Thu Mar 10 10:47:22 2022 +0900
3個前のコミットにDを追加
app/views/A.html
app/views/B.html
app/views/C.html
app/views/D.html
ちゃんと出来てるー👏
4. interactiveモードから抜ける
忘れずがちです
ちゃんと最後はinteractiveモードから抜けましょう
下記コマンドで抜けられます
$ git rebase --continue
interractiveモードを中止したい場合は
git rebase --abort
を実行すると
gitのリポジトリはgit rebaseを実行する前に戻ります
gitだけに限らずCUIでの操作は今どの状態にいるかを意識して作業しましょう
思わぬ事故を防ぐためには大事です
長くなりましたが説明は以上になります
お疲れ様でした!
まとめ
- 1個前のコミットの修正は
git commit --amend
を使う - 2個以上前のコミットの修正は
git rebase -i HEAD~N
とgit commit --amend
を使う - rebaseを中止したい場合は
git rebase --abort
を使う