Gitコマンド入門::rebase(-i,edit)「第十六回」

8 min read読了の目安(約7300字

みなさん、こんにちは! 前回は、reword でコメントの修正を行いましたけど、少しは慣れましたか? 今回は、コミットされたファイルの中身を、editで修正します。まあ~普通に、修正して、add, commit でも出来るのですが、コミット数を増やさずに、過去のコミットしたファイルの中身を修正できるのが、この、rebaseコマンドの特徴であり、便利なところなので、それぞれのシーンに合わせて、使い分けができるようになれば、最高ですね!

前回の記事はこちらから!「第十五回」

https://zenn.dev/shiozumi/articles/1a60ea4c20c5d5

まずは、git log -p で、現在の状態を確認![1]

gitレポジトリーの初期化と設定ファイルは、こちらからどうぞ!

https://gist.github.com/77ac3ba418dbafb80a11d0053b034147.git
$ git log -p
commit 1839466df61a8fd35f337024ccc798924a4334e3 (HEAD -> main)
Date:   Wed Feb 17 06:56:04 2021 +0900

    Ccc

diff --git a/README.md b/README.md
index 2204aa9..b665a22 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
 # rebase
 # AAA
 # BBB
+# CCC

commit 9a7ea356a703d68f62693bf4d57b20a5d8a329e3
Date:   Wed Feb 17 06:55:51 2021 +0900

    Bbb

diff --git a/README.md b/README.md
index 32eee12..2204aa9 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,3 @@
 # rebase
 # AAA
+# BBB

commit 41965dfb402ca1a5799c6709a108d2b7c966399c
Date:   Wed Feb 17 06:55:39 2021 +0900

    Aaa

diff --git a/README.md b/README.md
index 8c0227d..32eee12 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
 # rebase
+# AAA

commit 445c067462a0b0a3cd8f21c40798dfd60750c6fb (origin/main, origin/HEAD)
Date:   Tue Feb 16 14:37:03 2021 +0900

    1st

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8c0227d
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# rebase

それでは、git rebase -i 41965df~1 を実行!

Aaa から編集したいので、41965dfb402ca1a5799c6709a108d2b7c966399c + ~1 で選択可能です。実際には、ハッシュ値の先頭7桁指定でOK! ~1でも、^1でもどちらでも可!

$ git rebase -i 41965df~1

// vi の編集画面には、3つのコミットが選択されてます。
edit 41965df Aaa  // pick を、edit に変更!
pick 9a7ea35 Bbb
pick 1839466 Ccc
// Esc + wq で、変更、保存、終了する。

Stopped at 41965df...  Aaa
You can amend the commit now, with

  git commit --amend

Once you are satisfied with your changes, run

  git rebase --continue

Google翻訳:
今すぐコミットを修正できます。git commit --amend
変更に満足したら、実行します。git rebase --continue

それでは、README.md を修正して、git add README.mdgit commit --amend を実行してみましょう!

// ファイルの最終行に、edit test AAA を追加!
echo "# edit test AAA" >> README.md
$ cat README.md
# rebase
# AAA
# edit test AAA // <-- 追加1行!

// 毎度の、add して、今度は、修正なので、--amend を指定します!
git add README.md
git commit --amend

// vi エディターで、再び、コメントの編集を求められるので、edit test を追加!
Aaa // <-- 現在は、Aaa
Aaa edit test // <-- edit test を追加!
// Esc + wq で、変更、保存、終了する。

[detached HEAD 80c08d0] Aaa edit test
 Date: Wed Feb 17 06:55:39 2021 +0900
 1 file changed, 2 insertions(+)

これで、コミットのハッシュ値41965df [コメント:Aaa] のファイルの中身、README.mdファイルを変更して、コミット修正が完了ですね! 引き続き、'git rebase --continue' を実行してみましょう!

git rebase --continue
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
error: could not apply 9a7ea35... Bbb
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".

Google翻訳:
README.mdの自動マージ
CONFLICT(コンテンツ):README.mdの競合をマージします
エラー:9a7ea35を適用できませんでした... Bbb
すべての競合を手動で解決し、解決済みとしてマークします。

「git add / rm <conflicted_files>」を実行してから、「git rebase --continue」を実行します。代わりに、このコミットをスキップできます。「git rebase--skip」を実行します。中止して「git rebase」の前の状態に戻すには、「git rebase--abort」を実行します。

あれ~?! いったいこの状態は、、、何が起きたのでしょうか?
README.mdの自動マージが出来ないと、そう警告文のようですね。
cat README.md で、まずは確認してみましょう!

エラー:9a7ea35を適用できませんでした... Bbb

Aaa を修正したら、Bbbと競合?! 初めての体験だと、かなり理解に戸惑いますね。
でも、これって、映画とかでよくあるシナリオと同じです。そうそう、バックトゥザフューチャーとかで、過去に戻って未来を変えるっていうのと同じなんですよね。まあ、gitの場合は、それを出来てしまうのですが、つじつまが合っていないと、ファイルの整合性を、きっちと取ってくださいねと、管理上、修正を促してきます。[2]

まずは、ファイルの中身の確認を!

$ cat README.md // ファイルの中身の確認!
# rebase
# AAA
<<<<<<< HEAD
# edit test AAA
=======
# BBB
>>>>>>> 9a7ea35... Bbb

第十二回で習った、git merge を、覚えていますか?
あの時と同じように、gitが自動でマージしようとして、エラーになりましたね。

https://zenn.dev/shiozumi/articles/0a0c0c4fa53c3b

では、rebase する前の時点では!?

// 9a7ea35 Bbb
 # rebase // 41965df Aaa との差はなし
 # AAA     // 41965df Aaa との差はなし
+# BBB     // Aaaとの差分は、この一行だけ

// 41965df Aaa
 # rebase
 # AAA

rebase して、# edit test AAA が追加されたら?!

// 9a7ea35 Bbb
 # rebase // 41965df Aaa との差はなし
 # AAA     // 41965df Aaa との差はなし
+# BBB     // Aaaとの差分は、この一行だけ

// 41965df Aaa
 # rebase
 # AAA
+# edit test AAA  // この一行は、BbbとAaaとの差分として認識していない。

41965df Aaa から、9a7ea35 Bbb の差分は、+# BBB の一行であると、gitは、記録管理していたところに、Aaa の末尾行に、# edit test AAA と追加されたので、それは聞いてない、知らないよ、、、ってなったんですね。

$ vi README.md // 実際に、以下のように編集!
# rebase
# AAA
# edit test AAA
# BBB

git add README.md
git rebase --continue

// ここで、再び、コメントを求められます。
Bbb + test edit AAA // Bbb の後ろに、+ test edit AAA と追加!
// Esc + wq で、変更、保存、終了する。

さあ、どうなったのでしょうか?

$ git log --oneline
6757a96 (HEAD -> main) Ccc    // ハッシュ値のみ変更
b01b057 Bbb + test edit AAA   // ハッシュ値とコメントが変更
80c08d0 Aaa edit test      // ハッシュ値とコメントが変更
445c067 (origin/main, origin/HEAD) 1st

ハッシュ値が全て変わってる。git log -p で再確認!

$ git log -p
commit 6757a9658832505ad907d341f76943d1162cb206 (HEAD -> main)
Date:   Wed Feb 17 06:56:04 2021 +0900

    Ccc

diff --git a/README.md b/README.md
index 4404c96..a2e773b 100644
--- a/README.md
+++ b/README.md
@@ -2,3 +2,4 @@
 # AAA
 # edit test AAA // <-- Bbbの修正が、Ccc にも自動で反映されています!?
 # BBB
+# CCC

commit b01b0578b1a31ed7e4f1055c82ffe92448936861
Date:   Wed Feb 17 06:55:51 2021 +0900

    Bbb + test edit AAA

diff --git a/README.md b/README.md
index 651996c..4404c96 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
 # rebase
 # AAA
 # edit test AAA // <-- ここでのコンフィクトを、viで修正しましたね!
+# BBB

commit 80c08d00a46bc95158dc6ea0ef1f0225f17f5a01
Date:   Wed Feb 17 06:55:39 2021 +0900

    Aaa edit test

diff --git a/README.md b/README.md
index 8c0227d..651996c 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,3 @@
 # rebase
+# AAA
+# edit test AAA

commit 445c067462a0b0a3cd8f21c40798dfd60750c6fb (origin/main, origin/HEAD)
Date:   Tue Feb 16 14:37:03 2021 +0900

    1st

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8c0227d
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# rebase

6757a96 (HEAD -> main) Ccc にも、Bbbの修正内容が、しっかり反映されていますね。

$ cat README.md
# rebase
# AAA
# edit test AAA // Aaaに追加、Bbbのコンフィクト修正、なんと、Cccにも反映!
# BBB
# CCC

さあ、どうでしたか? 一度だけ、コンフィクトを解消しただけなのに、そのあとのコミットに対しても、変更されていますね。rebase っていう名前ですから、ベースを変えたら、それ以降も、すべて同じように更新してくれるのは、当然といえば、そんな気もしますけどね。何はともあれ、とても楽ちんです。そして、コミットのハッシュ値が変わっているっていうことは、勿論、git reflog コマンドを使って、元の状態のハッシュ値を、git reset --hard で指定してあければ、rebaseする前の元の状態にも戻りますね。(^^)v よければ、何回か練習してみましょう!

尚、実際には、全てのケースで、自動でコンフィクトを解決できるとは限りませんので、悪しからず。サンプルで、以下のファイルをお試しください。git rebase --continue が、最後まで続いて、全てのREADME.md を手作業で、修正することになります!(苦笑)[3]

もう一つ、サンプルのリポジトリーをUPしておきました。よければ、お試しくだしさい。

https://gist.github.com/544b33afb82d0b3b2eea202bf8cda40b.git

git reflog ハッシュ値を確認し、git reset --hard で、HEADを初期設定にしてからどうぞ!

それでは、今回はここまで、お疲れ様でした!

それにしても、少し頭が混乱してきますね。もう少しわかりやすく、次回説明できるように、まずは、私自身が学習するところからですね。(苦笑)あと、作図も作りたいなあ~

https://zenn.dev/shiozumi/articles/16a37391306777
https://twitter.com/esmile2013
脚注
  1. みなさん、それぞれに編集していると思いますので、表示の状態は異なるます。 ↩︎

  2. gitはファイルの差分管理が役目ですからね。あたり前のことでした。 ↩︎

  3. このあたりは、もう少し次回、深堀してみたいと思います。 ↩︎