Help us understand the problem. What is going on with this article?

初心者から一歩抜け出すためのGitの業 〜 git rebase -i

More than 5 years have passed since last update.

前回とは記事を分けることにした。長くなるから。
今回は、だれでもやったことがあるであろう、「え、ちょ、3つ前のコミットにtypo見つけちゃったよ!!」に対応する。

やりかたはいくつかある。例えば、最初に思いつきそうなことが、

  • そのコミットまでgit resetを繰り返して、編集して、もう一回git commitしていく

である。だけど、前の編集内容を覚えてなきゃいけないし、「Gitを使ってるくせに」的なアナログ感を感じざるをえない……ので、もっと上手い方法は無いのか。

ある。

git rebase -i

iinteractiveのことだ。多分。man git-rebaseをちゃんと読めば書いてあるのかもしれない。英語だけど気になる人は読んでみて欲しい。

で、このコマンド、何ができるのか。試しにやってみよう。
git log --onelineしたら、こんな感じのログがあった。

ee88db4 Add picture of '平塚の海岸線'
f182a59 Write the continuance of the diary
80dfd45 Add nikki

しかし、git log -pして詳細を眺めていくと、80dfd45の中に、重大なミスを発見してしまった。

俺10時って書いてるけど、10時半だよこれ!!

commit 80dfd45d305cb7b9807419e31115929781b1f94b
Author: Tatsuro Baba <harakirisoul@gmail.com>
Date:   Tue Oct 8 09:33:33 2013 +0900

    Add nikki

diff --git a/nikki b/nikki
new file mode 100644
index 0000000..0551e98
--- /dev/null
+++ b/nikki
@@ -0,0 +1,7 @@
+今、富士の某ホテルでこの日記を書いていている。
+
+朝8:40、自宅を出る。すでに出発予定時刻を40分過ぎている。普段の生活態度がうかがい知れる。
+ひたすら南に下って行く。途中自動車専用道があったので、回避したら、300m程度のとんでもない激坂があって、萎えかけた。
+そのあとはひたすら平坦な道を平塚に向かって進むだけだったので、楽しかった。時速で言うと30km/hくらいか。
+
+10時ごろに平塚に着いて、海に出てみる。

しかし、このコミット、もう3つも前のやつである。git show HEAD~2でようやく出てくるやつである。
ここまで根深いところにあると、git commit --amendでは対処できない。ふつうに修正してTypoとかfix forgotten timeとかでコミットするのも手だが、まだリモートにpushしていないところなので、(ダサいし)パパっと直してしまいたい。

というわけで前置きが長くなったが、git rebase -iの出番である。

おもむろにターミナルで、

$ git rebase -i HEAD~3

こうすることで、過去3つのコミットをrebaseの対象にできる。
前回の記事と同じく、エディタが立ち上がって、以下のように表示されるはずだ。

  1 pick 80dfd45 Add nikki
  2 pick f182a59 Write the continuance of the diary
  3 pick ee88db4 Add picture of '平塚の海岸線'
  4 
  5 # Rebase fa33ce4..ee88db4 onto fa33ce4
  6 #
  7 # Commands:
  8 #  p, pick = use commit
  9 #  r, reword = use commit, but edit the commit message
 10 #  e, edit = use commit, but stop for amending
 11 #  s, squash = use commit, but meld into previous commit
 12 #  f, fixup = like "squash", but discard this commit's log message
 13 #  x, exec = run command (the rest of the line) using shell
 14 #
 15 # These lines can be re-ordered; they are executed from top to bottom.
 16 #
 17 # If you remove a line here THAT COMMIT WILL BE LOST.
 18 #
 19 # However, if you remove everything, the rebase will be aborted.
 20 #
 21 # Note that empty commits are commented out

これの1行目、pickと書いてあるところを、おもむろにeditと書き換えよう。すると、

Stopped at 80dfd45... Add nikki
You can amend the commit now, with

    git commit --amend

Once you are satisfied with your changes, run

    git rebase --continue

と言われるはずだ。この時点でどうなっているかというと、 次にある2つのコミットは一旦よそに置いといて、80dfd45だけがコミットされた状態まで巻き戻っている、みたいな、だいたいそんな感じだ。現状はそんな程度の認識でも大丈夫。

ここまでくればあとは楽勝である。おもむろに修正したコミットを作り、

diff --git a/nikki b/nikki
index 6a66ce0..0551e98 100644
--- a/nikki
+++ b/nikki
@@ -4,4 +4,4 @@
 ひたすら南に下って行く。途中自動車専用道があったので、回避したら、300m程度のとんでもない激坂があって、萎えかけた。
 そのあとはひたすら平坦な道を平塚に向かって進むだけだったので、楽しかった。時速で言うと30km/hくらいか。

-10時ごろに平塚に着いて、海に出てみる。
+10時半ごろに平塚に着いて、海に出てみる。

さくっとamendしてやる。

$ g ad .
$ d --cached
diff --git a/nikki b/nikki
index 6a66ce0..0551e98 100644
--- a/nikki
+++ b/nikki
@@ -4,4 +4,4 @@
 ひたすら南に下って行く。途中自動車専用道があったので、回避したら、300m程度のとんでもない激坂があって、萎えかけた。
 そのあとはひたすら平坦な道を平塚に向かって進むだけだったので、楽しかった。時速で言うと30km/hくらいか。

-10時ごろに平塚に着いて、海に出てみる。
+10時半ごろに平塚に着いて、海に出てみる。
$ git commit --amend

直った!!

この後、まだやることはある。現状、2つくらいコミットがどこか俺の知らない所に旅行してしまっていて、行き先を知っているのはGitのみである。ので、Gitにコミットたちを呼び戻してもらう必要がある。
つまり、rebase中で止まっている状態なので、rebaseを継続するコマンドを打ってやればよい。

$ g rebase --continue
Successfully rebased and updated refs/heads/git-rebase.

これで全工程は完了。ちゃんとログも、

f6dfa25 Add picture of '平塚の海岸線'
f1b9f54 Write the continuance of the diary
00ea658 Add nikki

と、今までどおりだ。

git-rebaseというコマンド、他にも色々機能があって奥深い。黒魔術というほどでもないが、使えるようになって損はないと思う。
ちなみにこの業を何も知らないGit初心者の前でスラスラとやったりすると、目の前で何が起こっているのか分からずに戸惑うので、ちょっと楽しい。俺は楽しかった(でもちゃんと説明してあげよう)。

あ、あと最後に。
これ、すでにリモートにpushしちゃった後にやったりすると、チームメンバーにものすごい迷惑をかける可能性が高いので、気をつけよう。
つまり、リモートにあるやつと、あなたが今rebaseしたやつには、大きな乖離が生じていて、リモートを強制的に変更することも出来るけど、それをやってしまうと、すでにリモートをpullしていたチームメンバーからしてみたら、「俺のリポジトリとリモートが違う…」ということになってしまうからだ。
このへんのリスクとかは、別の記事にしようと思う。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away