はじめに
※ 以前git rebase -i して何か失敗して痛い目にあったりした
※ これ。
※ でも最近ちゃんとgitを理解し出したので再挑戦したらgit rebase -i がやっぱりイケてる
前提
※ .zshrc (.bash_profile?) にて、gitのデフォルトエディタを設定しときます
.zshrc
export GIT_EDITOR=vim
※ あと、念のためローカルbranchは新しく切って試します
% git branch * develop master % git branch rebase_test % git branch rebase_test * develop master % git checkout rebase_test
※ ぜんぜん関係無いけど、tigあるとちょっと幸せかも
そもそもgit rebase って何
そもそもgit rebase とは、今あるブランチの根元を設定しなおす、というコマンドっぽい。なるほど、baseを再構築するのでrebaseね。具体的には以下みたいな感じ。
たとえばcommit0までを反映しているブランチmasterから、ある時点でdevelopブランチ切って、開発を進めてcommit1, commit2, commit3, commit4を加えたとする。しかしその間誰かがmasterブランチにcommit5を加えていたら、masterブランチとdevelopブランチはお互いに知らないcommitを持っていて、コンフリクトがあり得、安易にmergeなど出来ない可能性がある。図1
図1
なので「commit5まで知っているmasterブランチから切られたdevelopブランチ」にしたいことがある。これをやるコマンドが、
% git checkout develop #developブランチに移動
% git rebase master
これで、自分がいるdevelopブランチが、今参照したmasterブランチのHEADを根元としたブランチにrebaseされたということになる。図2
図2
それってつまり、
% git branch * develop master % git log COMMIT4 COMMIT3 COMMIT2 COMMIT1 COMMIT0 %git checkout master % git log COMMIT5 COMMIT0 % git branch devleop_new % git checkout develop_new % git branch develop * develop_new master % git log COMMIT5 COMMIT0 % git cherry-pick COMMIT1 % git cherry-pick COMMIT2 % git cherry-pick COMMIT3 % git cherry-pick COMMIT4 % git branch develop * develop_new master % git log COMMIT4 COMMIT3 COMMIT2 COMMIT1 COMMIT5 COMMIT0
ということになるのかな
で、-i って何
iオプションというのは、--interactiveの略で「対話的」という意味です。対話的に現在のブランチの元およびコミットログを構築し直してくれるです。「どこがどー対話的やねん」と思って分からなかったのですが、どこがどー対話的なのかが味噌だったようです。
どこがどー対話的かというと、、、
- git rebase -i HEAD~n というコマンドで「HEADからn個のコミットを構築し直すよ」と伝える
- git が、伝票を出してくるので、それを編集して終了(提出)する
- git が、提出された伝票を元に、ひとつひとつのコミットごとに「で、具体的に何すんの?」という態度で待ち構える
- コミットログを編集したりして rebase --continueする
- これ何回かやってrebase成功!
では、
ブランチに乗ってるcommitを確認します
% git branch * develop master % git log | vim -
その結果
こんな感じ。これは別にtigで代用してもいいよ。
たとえばこれの、
「最近から三つのcommitをひとつにまとめてコミットログを変える」ことをしてみようと思ったら
1. git rebase -i HEAD~n というコマンドで「HEADからn個のコミットを構築し直すよ」と伝える
% git rebase -i HEAD~3
その結果
これがその "伝票"
2. git が、伝票を出してくるので、それを編集して終了(提出)する
なので、vimで開かれてる伝票を編集する。2行目のコミットと3行目のコミットを1行目のコミットにまとめたいので、2行目と3行目に青字で書かれてる「pick」を「squash」に書き換える。書き換えたら、いつものvimのように、:wpで伝票を閉じましょう!
3. git が、提出された伝票を元に、ひとつひとつのコミットごとに「で、具体的に何すんの?」という態度で待ち構える
今回は三つのコミットをまとめてコミットログを書き換えたいので、
として:wq
4. コミットログを編集したりして rebase --continueする
今回はsquashしたいだけなので、ここは無いのかな。
5. rebase成功!
今回はこれで成功
よくやる使い方
よくやる、って言っても最近やっとちゃんと使いこなせるようになったのでアレですけど
- リモートのmasterをローカルのmasterにpull => ローカルのmasterを最新にする
- ローカルのmasterからhoge_tempブランチを切って開発進める
- 進めてるうちにmasterに変更があったりするので、その気付いたらローカルのmasterに反映させて、hoge_tempをrebase masterする => hoge_tempブランチの根元が常に最新のmasterになる
- 何度もhoge_tempにローカルcommitを重ねる
- 完成したら、もっかいhoge_tempをrebaseする
- 最後に、hoge_tempに溜まったコミットを rebase -i で改ざんする
するとどうなるかってーと
githubのネットワーク図でこんな感じになる
これってつまり
「すげーこのひとサクッとブランチ切ってバチッと開発してシュッとマージしてプロジェクトcloseさせてるじゃーん」って見た目。
でもじつはこんな感じ。
じつは結構前からブランチ切ってたし、コミット単位もめちゃくちゃで汚いんだけど、rebaseして最新のmasterがが根元かのように改ざんして、ローカルコミットもrebase -i でsquashとかしちゃって綺麗にしてるというワケさ。
雑感
この方が安全だし、コミットログも見やすいし、万が一不具合発覚して切り戻しが必要になったときもやり易いし。まーあと、他人とリモートでコンフリクトしないように。
Gitが、おもしろいほどわかる基本の使い方33〈バージョン管理、SourceTree、Bitbucket〉
- 作者: 大串肇,久保靖資,豊沢泰尚
- 出版社/メーカー: エムディエヌコーポレーション
- 発売日: 2015/05/26
- メディア: 単行本
- この商品を含むブログ (3件) を見る
- 作者: Travis Swicegood,でびあんぐる
- 出版社/メーカー: オーム社
- 発売日: 2009/08/12
- メディア: 単行本(ソフトカバー)
- 購入: 25人 クリック: 305回
- この商品を含むブログ (101件) を見る