Posted at

git rebaseを勉強してみた

More than 5 years have passed since last update.


はじめに

前回mergeをやってみました。今回はrebaseです。

前回と重複しますが、git initから始めます。


テストリポジトリの作成

一気にいきます。



  • masterブランチの作成

  • feature/worldブランチに分岐


  • worldメソッド追加しコミット


  • masterブランチに戻り


  • helloメソッドを追加しコミット


Hello.java

class Hello {

public static void main(String[] args) {
System.out.println("hello");
}
}

*.class

$ git init ./

Initialized empty Git repository in /Users/kenta_suzuki/project/rebase/.git/

$ git add ./

$ git status
On branch master

Initial commit

Changes to be committed:
(use "git rm --cached <file>..." to unstage)

new file: .gitignore
new file: Hello.java

$ git commit -m '初めてのコミット'
[master (root-commit) 9a69391] 初めてのコミット
2 files changed, 8 insertions(+)
create mode 100644 .gitignore
create mode 100644 Hello.java

$ git branch
* master

$ git log --decorate=full
commit 9a693911726510a15e2c5276dc438eaacccb3106 (HEAD, refs/heads/master)
Author: kenta <kenta_suzuki@dwango.co.jp>
Date: Wed Dec 11 22:22:47 2013 +0900

初めてのコミット

$ git checkout -b feature/world master
Switched to a new branch 'feature/world'

$ git log --decorate=full
commit 9a693911726510a15e2c5276dc438eaacccb3106 (HEAD, refs/heads/feature/world)
Author: kenta <kenta_suzuki@dwango.co.jp>
Date: Wed Dec 11 22:22:47 2013 +0900

初めてのコミット

$ vim Hello.java
(ここで以下のdiffになるように修正)

$ git diff
diff --git a/Hello.java b/Hello.java
index 8bf82a8..eae3d39 100644
--- a/Hello.java
+++ b/Hello.java
@@ -2,5 +2,9 @@ class Hello {
public static void main(String[] args) {
System.out.println("hello");
}
+
+ public static void world() {
+ System.out.println("world");
+ }
}

$ git commit -a -m 'worldメソッドを追加'
[feature/world 3dfd7cf] worldメソッドを追加
1 file changed, 4 insertions(+)

$ git log --decorate=full
commit 3dfd7cf5be7fe5f20880d31db3b926d092d3160e (HEAD, refs/heads/feature/world)
Author: kenta <kenta_suzuki@dwango.co.jp>
Date: Wed Dec 11 23:19:09 2013 +0900

worldメソッドを追加

commit 9a693911726510a15e2c5276dc438eaacccb3106
Author: kenta <kenta_suzuki@dwango.co.jp>
Date: Wed Dec 11 22:22:47 2013 +0900

初めてのコミット

$ git checkout master
Switched to branch 'master'

$ git log --decorate=full
commit 9a693911726510a15e2c5276dc438eaacccb3106 (HEAD, refs/heads/master)
Author: kenta <kenta_suzuki@dwango.co.jp>
Date: Wed Dec 11 22:22:47 2013 +0900

初めてのコミット

$ vim Hello.java
(ここで以下のdiffになるように修正)

$ git diff
diff --git a/Hello.java b/Hello.java
index 8bf82a8..1c9343b 100644
--- a/Hello.java
+++ b/Hello.java
@@ -2,5 +2,9 @@ class Hello {
public static void main(String[] args) {
System.out.println("hello");
}
+
+ public static void hello() {
+ System.out.println("hello");
+ }
}

$ git commit -a -m 'helloメソッドを追加'
[master afd434d] helloメソッドを追加
1 file changed, 4 insertions(+)

$ git log --decorate=full
commit afd434d6e9ba7b1a86e8d870ab3e5ba9edb8fbf9 (HEAD, refs/heads/master)
Author: kenta <kenta_suzuki@dwango.co.jp>
Date: Wed Dec 11 22:39:22 2013 +0900

helloメソッドを追加

commit 9a693911726510a15e2c5276dc438eaacccb3106
Author: kenta <kenta_suzuki@dwango.co.jp>
Date: Wed Dec 11 22:22:47 2013 +0900

初めてのコミット

はー、長かった。早速rebase行ってみましょう。

$ git rebase feature/world

First, rewinding head to replay your work on top of it...
Applying: helloメソッドを追加
Using index info to reconstruct a base tree...
M Hello.java
Falling back to patching base and 3-way merge...
Auto-merging Hello.java
CONFLICT (content): Merge conflict in Hello.java
Failed to merge in the changes.
Patch failed at 0001 helloメソッドを追加
The copy of the patch that failed is found in:
/Users/kenta_suzuki/project/rebase/.git/rebase-apply/patch

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".

$ git status
rebase in progress; onto 3dfd7cf
You are currently rebasing branch 'master' on '3dfd7cf'.
(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 reset HEAD <file>..." to unstage)
(use "git add <file>..." to mark resolution)

both modified: Hello.java

no changes added to commit (use "git add" and/or "git commit -a")

$ vim Hello.java
(コリジョンしているので修正する)

$ git diff
diff --cc Hello.java
index eae3d39,1c9343b..0000000
--- a/Hello.java
+++ b/Hello.java
@@@ -3,8 -3,8 +3,12 @@@ class Hello
System.out.println("hello");
}

+ public static void hello() {
+ System.out.println("hello");
+ }
++
+ public static void world() {
+ System.out.println("world");
+ }
}

$ git branch -a
* (no branch, rebasing master)
feature/world
master

$ git status
rebase in progress; onto 3dfd7cf
You are currently rebasing branch 'master' on '3dfd7cf'.
(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 reset HEAD <file>..." to unstage)
(use "git add <file>..." to mark resolution)

both modified: Hello.java

no changes added to commit (use "git add" and/or "git commit -a")

$ git add ./

$ git rebase --continue
Applying: helloメソッドを追加

$ git log --decorate=full
commit 4cb8b98dbd79de7e9be6c067f90dd223bb4cab7e (HEAD, refs/heads/master)
Author: kenta <kenta_suzuki@dwango.co.jp>
Date: Wed Dec 11 22:39:22 2013 +0900

helloメソッドを追加

commit 3dfd7cf5be7fe5f20880d31db3b926d092d3160e (refs/heads/feature/world)
Author: kenta <kenta_suzuki@dwango.co.jp>
Date: Wed Dec 11 23:19:09 2013 +0900

worldメソッドを追加

commit 9a693911726510a15e2c5276dc438eaacccb3106
Author: kenta <kenta_suzuki@dwango.co.jp>
Date: Wed Dec 11 22:22:47 2013 +0900

初めてのコミット


Hello.java(コリジョンを起こしたファイル)

class Hello {

public static void main(String[] args) {
System.out.println("hello");
}

<<<<<<< HEAD
public static void world() {
System.out.println("world");
=======
public static void hello() {
System.out.println("hello");
>>>>>>> helloメソッドを追加
}
}


commit 2889d24c5422fd145946ebd771aac193df7a3bb5 (HEAD, refs/heads/master)

Merge: ea93e48 08ffb74
Author: kenta <kenta_suzuki@dwango.co.jp>
Date: Wed Dec 11 09:57:19 2013 +0900

worldメソッドをマージ

commit ea93e4833c20246ea80d72761feab523c45ee8be
Author: kenta <kenta_suzuki@dwango.co.jp>
Date: Wed Dec 11 09:29:25 2013 +0900

helloメソッドを追加

commit 08ffb7444eafe390ea5ce8582b6c2ec0f2dd8a3f (refs/heads/feature/world)
Author: kenta <kenta_suzuki@dwango.co.jp>
Date: Wed Dec 11 09:20:56 2013 +0900

worldメソッドを追加

commit 67c809018dd292c5c84d957d0ae6c5eb03622dcd
Author: kenta <kenta_suzuki@dwango.co.jp>
Date: Tue Dec 10 22:29:07 2013 +0900

初めてのコミット

commit 4cb8b98dbd79de7e9be6c067f90dd223bb4cab7e (HEAD, refs/heads/master)

Author: kenta <kenta_suzuki@dwango.co.jp>
Date: Wed Dec 11 22:39:22 2013 +0900

helloメソッドを追加

commit 3dfd7cf5be7fe5f20880d31db3b926d092d3160e (refs/heads/feature/world)
Author: kenta <kenta_suzuki@dwango.co.jp>
Date: Wed Dec 11 23:19:09 2013 +0900

worldメソッドを追加

commit 9a693911726510a15e2c5276dc438eaacccb3106
Author: kenta <kenta_suzuki@dwango.co.jp>
Date: Wed Dec 11 22:22:47 2013 +0900

初めてのコミット


  • merge


    • コミットが時系列に並んでいる

    • 分岐した時点からの差分がコミットログとして残っている



  • rebase


    • 分岐後のmasterのコミットを取り込んだ後の差分が残る



どちらにも利点があるし欠点があるのでしょう。

ローカルで一時的な修正をコミットしたとき、修正自体が間違ってて後で直した場合、意味のあるコミットにまとめるためrebaseする。

masterにマージする際はmergeを使って分岐時点からの差分を詳細に残す。

というような使い方でいいような気がしてきた。

もっと、深く踏み込んで、「○○の時はmergeで△△の時はrebaseだよねー」とかっていえるように、勉強続けます。

次回ももうちょい mergeとrebaseについて考察していきます。