gitマージ作業の個人的なメモ

git 初心者です。

Android(Java)のSPDY&HTTP/2.0対応通信ライブラリOkHttp-1.5に複数のバグがあり、それらがfixされたコミットをマージする作業が若干複雑だったのでメモしておく。

#前提

OkHttp-1.5には下記2つのバグがあった。

- Android2.2で動作しない [#618](https://github.com/square/okhttp/issues/618)
- Android4.1以降で受信データサイズが大きい場合に処理が停止する [#623](https://github.com/square/okhttp/issues/623)


##最初のブランチ構成

```
------X-- square/okhttp/master    OkHttp-2.0向けmaster
   \----- square/okhttp/okhttp_15 OkHttp-1.5メンテ用ブランチ

 ※X は OkHttp-2.0 開発作業のコミット
```

ここで #618 は OkHttp-2.0 には対応不要(OkHttp-2.0はAndroid2.2をサポートしなくなるため)なので okhttp-15 ブランチのみで修正される。#623 は master で修正され、それが okhttp-15 にマージされる(予定)。

既に OkHttp は OkHttp-2.0 向けの開発が始まっていたが、私個人が欲しいのは OkHttp-1.5 系でこれらの修正が行われた版なので、マージ作業が必要であった(OkHttp-1.5.1を先取りしたい)。


## #618対応後のブランチ構成
 #618 の修正作業を[私が行い](https://github.com/square/okhttp/pull/622)、プルリクを送ったのでこんな構成になった。

```
------X----- square/okhttp/master              OkHttp-2.0向けmaster
   \-------- square/okhttp/okhttp_15           OkHttp-1.5メンテ用ブランチ
      \--A-- takke/okhttp/okhttp_15_android2_2 #618対応用ブランチ

 ※A は #618 の修正コミット。
   これは元は 3 つのコミットで、これを 1コミットに squash する作業も大変だったんだけど、それはまた別の記事で。
```

2014/3/10 12:00 時点では A は okhttp/okhttp_15 にマージされていない。

## #622対応後のブランチ構成
 #622 の修正作業が master ブランチで行われた。

```
------X-----B-- square/okhttp/master              OkHttp-2.0向けmaster
   \----------- square/okhttp/okhttp_15           OkHttp-1.5メンテ用ブランチ
      \--A----- takke/okhttp/okhttp_15_android2_2 #618対応用ブランチ

 ※B は #622 の修正コミット。
```

# 欲しいもの

前述の通り、#618 と #622 が修正された OkHttp-1.5 系が欲しい。つまり、okhttp_15+A+Bが欲しい。

```
------X-----B------ square/okhttp/master              OkHttp-2.0向けmaster
   \--------------- square/okhttp/okhttp_15           OkHttp-1.5メンテ用ブランチ
      \--A--------- takke/okhttp/okhttp_15_android2_2 #618対応用ブランチ
             \--B-- takke/okhttp/okhttp_15_improved   #618と#622が対応されたブランチ

 ※A は #618 の修正コミット
 ※B は #622 の修正コミット
```


# 行った作業

## okhttp_15_improved ブランチを作る

okhttp_15_android2_2 から okhttp_15_improved ブランチを作る。
GitHub のWeb上で行った。

![github1.png](https://qiita-image-store.s3.amazonaws.com/0/39221/2c0f9030-2d1f-ad89-6a4d-ecb5f01c66c0.png)

okhttp_15_android2_2 (正確には okhttp_15_fix_for_android2_2) を選んで、

![github2.png](https://qiita-image-store.s3.amazonaws.com/0/39221/6845c2cf-a5b4-74ff-b2f4-8e3e1d5632c5.png)

名前入力するだけ。ラクチンやねー。


## ローカルにcheckoutする

```git remote add``` は[この記事](http://qiita.com/xtetsuji/items/555a1ef19ed21ee42873)を参考に実行済みで、ローカルはこんな構成。

```
$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
...
  remotes/origin/okhttp_15
  remotes/origin/okhttp_15_fix_for_android2_2
...
  remotes/upstream/master
  remotes/upstream/okhttp_13
  remotes/upstream/okhttp_15
```

GitHub上で作った okhttp_15_improved を反映する。

```
$ git fetch
From github.com:takke/okhttp
 * [new branch]      okhttp_15_improved -> origin/okhttp_15_improved
```

```
$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
...
  remotes/origin/okhttp_15
  remotes/origin/okhttp_15_fix_for_android2_2
  remotes/origin/okhttp_15_improved                ←増えた！
...
  remotes/upstream/master
  remotes/upstream/okhttp_13
  remotes/upstream/okhttp_15
```

で、checkout する。

```
$ git checkout -b okhttp_15_merge_work origin/okhttp_15_improved
Branch okhttp_15_merge_work set up to track remote branch okhttp_15_improved fro
m origin.
Switched to a new branch 'okhttp_15_merge_work'

$ git branch
  master
* okhttp_15_merge_work
```

```
$ git log -2
commit 933c900d52515bae32e3540821645d2a9ca4046b
Author: takke <takke30@gmail.com>
Date:   Sun Mar 9 13:12:19 2014 +0900

    enable to work on android 2.2

commit bf77f22b4504054b6a30af667b69eabf88f5696a
Author: Jake Wharton <jw@squareup.com>
Date:   Fri Mar 7 14:59:54 2014 -0800

    [maven-release-plugin] prepare for next development iteration
```

確かに A がコミットされている。


## B をマージ(cherry-pick)する

Bのハッシュを探す

```
$ git log upstream/master -2
commit 945619c3f451bba092f772adbd62cd0a6fd7ec3b             ← これがB
Merge: 3587b4b 818d17e
Author: Adrian Cole <adrian.f.cole@gmail.com>
Date:   Sun Mar 9 10:39:29 2014 -0700

    Merge pull request #625 from square/jwilson_0309_peersettings

    Use the peer's settings for outgoing window updates.

commit 818d17e3650f5c0fa048ae52279c559cd255f738             ← これがX
Author: Jesse Wilson <jwilson@squareup.com>
Date:   Sun Mar 9 13:23:02 2014 -0400

    Use the peer's settings for outgoing window updates.
```

普通に ```git merge upstream/master``` すると X と B がマージされてしまう。
そこで、[この記事](http://qiita.com/takc923/items/8e2d87d692f840b14464) を参考に、Bだけをマージする。

```
$ git cherry-pick -rn -m 1 945619
```

ここで ```-rn``` オプションを付けることで即時コミットされないようにする。また、Bがマージコミットなので-mで親を指定する。

```
$ git commit
```

エディタ(例えばvim)が立ち上がって、

```
Merge pull request #625 from square/jwilson_0309_peersettings

Use the peer's settings for outgoing window updates.

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch okhttp_15_merge_work
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   okhttp-tests/src/test/java/com/squareup/okhttp/internal/spdy/SpdyConnectionTest.java
#       modified:   okhttp/src/main/java/com/squareup/okhttp/internal/spdy/SpdyStream.java
#
```

という画面に。適当に編集してコミット。

```
$ git commit
[okhttp_15_merge_work 6ba8f0d] Merge from square/master
 2 files changed, 2 insertions(+), 3 deletions(-)
```

ブランチのログを確認する。

```
$ git log -2
commit 6ba8f0dc31d4dbfecebb3a33784dd9c555044d2c
Author: takke <takke30@gmail.com>
Date:   Mon Mar 10 13:14:06 2014 +0900

    Merge from square/master

    ---
    Merge pull request #625 from square/jwilson_0309_peersettings

    Use the peer's settings for outgoing window updates.

commit 933c900d52515bae32e3540821645d2a9ca4046b
Author: takke <takke30@gmail.com>
Date:   Sun Mar 9 13:12:19 2014 +0900

    enable to work on android 2.2
```

## リモートに反映(に失敗したのでリモートブランチを削除する)

```
$ git push origin okhttp_15_merge_work
Counting objects: 39, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (12/12), done.
Writing objects: 100% (22/22), 2.63 KiB, done.
Total 22 (delta 6), reused 0 (delta 0)
To git@github.com:takke/okhttp.git
 * [new branch]      okhttp_15_merge_work -> okhttp_15_merge_work
```

これだとリモートに okhttp_15_merge_work が作られちゃった。
なので削除した。

```
$ git push origin :okhttp_15_merge_work
To git@github.com:takke/okhttp.git
 - [deleted]         okhttp_15_merge_work
```

## リモートに反映(今度こそ)

```
git push origin okhttp_15_merge_work:okhttp_15_improved
Counting objects: 39, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (12/12), done.
Writing objects: 100% (22/22), 2.63 KiB, done.
Total 22 (delta 6), reused 0 (delta 0)
To git@github.com:takke/okhttp.git
933c900..6ba8f0d  okhttp_15_merge_work -> okhttp_15_improved
```

無事完成

![github3.png](https://qiita-image-store.s3.amazonaws.com/0/39221/9d1e0def-d087-5f09-7369-39e1eafd4b52.png)


# cherry-pick で -rn オプションを付けない場合

GitHub上で okhttp_15_android_2_2 から okhttp_15_improved2 ブランチを作り、下記を実行。

```
$ git fetch origin
$ git checkout origin/okhttp_15_improved2
Note: checking out 'origin/okhttp_15_improved2'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

...

HEAD is now at 933c900... enable to work on android 2.2

$ git cherry-pick -m 1 945619
[detached HEAD 00fb5cc] Merge pull request #625 from square/jwilson_0309_peerset
tings
 Author: Adrian Cole <adrian.f.cole@gmail.com>
 2 files changed, 2 insertions(+), 3 deletions(-)

$ git push origin HEAD:okhttp_15_improved2
...
To git@github.com:takke/okhttp.git
   933c900..00fb5cc  HEAD -> okhttp_15_improved2
```

こんな感じになった。

![github4.png](https://qiita-image-store.s3.amazonaws.com/0/39221/29deb0ec-8ff9-fda0-86cb-90dc841da900.png)

なるほど、コミットB がそのままここに入ってくる感じなのね。


# 作業後の network graph

GitHub の network graph はこんな感じになった。シンプルですね。

![github_network1.png](https://qiita-image-store.s3.amazonaws.com/0/39221/482496c9-bb79-47a2-6276-3057088acb8c.png)


# おまけ : OkHttpのビルド

できあがった okhttp_15_improved2 をビルドしました。

testは長いしローカルサーバ用意できてないのでskipで。

```
D:\Src\workspace_twitter4j-takke\okhttp-merge-work>mvn install -Dmaven.test.skip=true
...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] OkHttp (Parent) ................................... SUCCESS [  1.673 s]
[INFO] OkHttp ............................................ SUCCESS [  5.315 s]
[INFO] MockWebServer ..................................... SUCCESS [  2.941 s]
[INFO] OkHttp Apache HttpClient .......................... SUCCESS [  0.725 s]
[INFO] OkHttp Tests ...................................... SUCCESS [  0.299 s]
[INFO] Samples (Parent) .................................. SUCCESS [  0.157 s]
[INFO] Sample: Guide ..................................... SUCCESS [  0.483 s]
[INFO] Sample: Simple Client ............................. SUCCESS [  0.660 s]
[INFO] Sample: Static Server ............................. SUCCESS [  1.375 s]
[INFO] Benchmarks ........................................ SUCCESS [  1.458 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 15.282 s
[INFO] Finished at: 2014-03-10T13:52:51+09:00
[INFO] Final Memory: 76M/838M
[INFO] ------------------------------------------------------------------------

D:\Src\workspace_twitter4j-takke\okhttp-merge-work>dir okhttp\target\*.jar
2014/03/10  13:52           310,153 okhttp-1.5.1-SNAPSHOT.jar
...
```

というわけでコレを使えば A と B に暫定対応した OkHttp-1.5 を利用できるわけでした。
長かったー。


# 参考

- [GitHubでFork/cloneしたリポジトリを本家リポジトリに追従する - Qiita](http://qiita.com/xtetsuji/items/555a1ef19ed21ee42873)
- [git - merge commitをcherry-pickする - Qiita](http://qiita.com/takc923/items/8e2d87d692f840b14464)
- [git - リモートで消されたブランチが手元で残ってしまう件を解消する - Qiita](http://qiita.com/yuichielectric/items/84cd61915a1236f19221)