2021/04/21
コメントを頂き、内容を修正しました。
この記事はgit rebase
の中でも、git rebase -i
について紹介していきます。
0. はじめに
この記事ではgit rebase -i
の目的とその結果、方法を記述していきます。また、その中でも特にedit
に関する内容に触れていきます。
この記事は、私がリベースを行った際に、その結果がイメージできなかったのでまとめておこうと思いました。なのでgit rebase -i
の結果について、どう変化するのか、を伝えられればいいなと思います。
1. "git rebase -i"を行う目的
git rebase -i
の目的は過去の改竄を行うことです。
私がgit rebase -i
を行う必要性が生じたのは、「ファイル内にEメールアドレスを直接記述」し、その内容をコミットしたからです。そのミスには暫くしてから気づき、過去の改竄が必要になりました。
ちなみに、変更の差分はgit diff
を用いて確認できます。それにより、過去の変更履歴も確認が可能です。それゆえ「ファイル内にEメールアドレスを直接記述」していない過去に変更する必要があり、git rebase -i
を行いました。
2. "git rebase -i"の結果
まず初めに、git rebase
で何が起こるか確認します。git rebase
後でも、改竄を加えた部分以外は同じです。しかし、コミット履歴が変更されます。
以下にgit rebase -i
の前後のログの例を示します。
下の例では、新しく'test_branch'を用意し、commit[5555555]の内容をedit
しています。
before
git log —-oneline
7777777 (HEAD -> develop_origin, origin/develop_origin)This is commit E
6666666 This is commit D
5555555 (third-branch)This is commit C
4444444 This is 3rd commit B
3333333 (second-branch)This is commit A
2222222 This is 1st commit
1111111 (origin/master, master) Initialize repository
After
git log —-oneline
ccccccc (HEAD -> test_branch)This is commit E
bbbbbbb This is commit D
aaaaaaa This is commit C rebased!!
4444444 This is 3rd commit B
3333333 (second-branch)This is commit A
2222222 This is 1st commit
1111111 (origin/master, master) Initialize repository
3. "git rebase -i"の方法
ここでは、リベースの中でも、edit
の方法を解説します。ちなみに、私は以下の記事を参考にリベースさせて頂きました。とても分かりやすいので、おすすめです。
Git のコミット履歴を大胆に書き換えるなら git rebase -i がオススメ
リベースでeditするステップは以下の5つです。
- リベースを行う (
git rebase -i [コミット番号]
- 改竄したいコミット番号を指定する (
pick
→edit
- 過去を改竄する
- コミットし直す (
git commit —amend
- 現在に戻ってくる (
git rebase continue
以下、詳細の操作について説明していきます。ちなみに例では、2章で用いたコードを用います。
1) リベースを行う
まず、リベースのの基本的な使い方として git rebase -i <after-this-commit>
という構文で行います。このコードをするとViエディタが起動します。
git rebase -i <after-this-commit>
# ex)
git rebase -i 4444444444444..
pick 6666666 This is commit D
pick 5555555 This is commit C
# Rebase 4444444..5555555 onto 4444444 (2 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.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
<after-this-commit>
には、コミット番号を指定します。このコミット番号によりリベースする範囲を決定します。具体的には、指定したコミット番号より一つ後ろのコミット番号から、HEADまでの間の内容をリベースすることが出来ます。
例では4444444
のコミットを指定している為それ以降でHEADまでのコミットがリベース可能範囲です。
つまり、6666666
、5555555
がリベース可能になります。
2) 改竄したいコミット番号を指定する
次にViエディタで、改竄したいコミットを指定します。その方法は、改竄したいコミットの横にあるpick
をedit
変更します。そしてViエディタを:wq
で保存します。
edit 5555555 This is commit C
pick 6666666 This is commit D
# Rebase 4444444..6666666 onto 4444444 (2 commands)
#
# Commands:
# .
# 省略
# .
# However, if you remove everything, the rebase will be aborted.
2個のコミットから1番上を選択すると以下のようなターミナルに変更されます。
ちなみに、この時点でリベースをせずに中止するコマンドがあります。以下のコマンドです。
このコマンドを実行することで、リベースを行う前の状態へ戻す事が可能です
git rebase --abort
ちなみにここでは過去の改竄の為edit
を用いていますが、リベースには他にもコマンドがあり、目的に応じたコマンドをここでは選択します。
3) 過去を改竄する
ここでは改竄したい過去の内容を変更します。自分の場合は、Eメールアドレスを直接記述していたので、その変更を削除します。
:~/myapp (test_branch|REBASE 1/2)$ git diff
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -24,7 +24,7 @@ Devise.setup do |config|
# with default "from" parameter.
- config.mailer_sender = 'aiueo@abcde.com'
+ config.mailer_sender = Settings.google_account[:email]
# Configure the class responsible to send e-mails.
4) コミットし直す
変更をステージングし、コミットし直します。
注意点として、ここではコミットのやり直しを意味する—amend
オプションを付随させます。
git ci --amend
5) 現在に戻ってくる
目的通りに過去を改竄できたらリベースは終了です。リベース完了を意味する以下のコマンドを実行します。
git rebase --continue
先程の変更で、その後の変更にコンフリクトが生じていない場合は、リベース成功です。
コンフリクトが生じている場合には、コンフリクトを解消し、もう一度上記のコマンドを実行すればリベース完了です。リベース後はコミット履歴が変更されます。
git log —-oneline
ccccccc (HEAD -> test_branch)This is commit E
bbbbbbb This is commit D
aaaaaaa This is commit C rebased!!
4444444 This is 3rd commit B
3333333 (second-branch)This is commit A
2222222 This is 1st commit
1111111 (origin/master, master) Initialize repository
4. おわりに
最後まで、読んで頂きありがとうございました!
まだまだ学習中なので、間違っている部分などコメントなどして頂けると嬉しいです!
余談ですが...
私がリベースを行う必要があったのは、Githubでpublicにしたいリポジトリに裸のEメールアドレスをpushしたからです。セキュリティ的に脆弱になってしまう為、リベースを行いました。大変だったぜ。次から気をつけなければ、
リポジトリをpublicにする為には、リベースだけでなくリポジトリを一新する必要がありました。なぜかというと、リベースでは、改竄前のコミット履歴も残っている為、履歴を辿ればEメールアドレスを確認できてしまうからです。
参考