機能ができたよ、と PRされたんだけどどうにもその branchが汚い。commitの順番がくるってるとか、commitを 2つに分けたいとかだけなら git rebase -i
でなんとかなるけど、論理的にはひとつの変更が複数の commitに分かれていたり、さらにはどこが論理的なまとまりかわからない。reviewしようにもとっかかりもない。かと言って突き返してもこれ以上改善するとも思えない。0から自分で実装する時間もないので、なんとか機能は組み込みたいけど。こまった。どうしよう。現実逃避に twitterでもみるか。
そんな状況があなたにもあるでしょう。そんなときに使える tipsを提供します、というか、単にやったことをまとめてみます。いろいろ改善点はあるだろうからツッコミも常時うけつけます。
前提
- A [*] (master trunk)
\- B0 - B1 - B2 (messy_branch)
こんな感じです。 B0
とかが、もうどうしようもない commit群です。
ちなみに図中の [*]
は current branchぐらいのいみで使ってます。
messy_branchを潰す
もう、commitの単位は意味ないので、つぶしちゃいます。
git checkout messy_branch
git reset master
git add files # stage necessary files!
git commit -m 'squashed!'
この時に、ついでに自明にいらない変更は (いらないコメントの追加、空行の追加とか) 適当に編集して直しちゃったほうが後は楽かもしれません。やりませんでしたが。
あとで気づきましたが、ここは git rebase -i
で、全部 squashしちゃうほうが、addしわすれとかなくていいかも。
あと、upstreamがあった場合、 git branch --unset-upstream
しておいたほうが unpulledがどうのこうの言われなくていいかもしれません。
refactor_branchを生やしてそこで作業。
git checkout master
git checkout -b refactor_branch
- A (master)
|\- B99 (messy_branch)
\. [*] (refactor_branch)
messy_branch からとりあえずわかる単位を引き剥がす
git checkout -p messy_branch
こうすると chunk単位で元 branchにとりこむか聞いてきます。そもそも、一つの chunkに複数の変更がはいってたりすることもあるかもしれないけど、そこは取り込んだ後、編集したりしてなんとかします。
とりあえず、依存関係のない単純な部分から引き剥がして後の作業を楽にすることを考えます。他のライブラリを導入するためだけの変更とかがまずは楽でした。
commitの順序の入れ替えとか、2つの commitを一つにまとめるとかはあとで更に refacor_branchを rebase -i
すればなんとかなるので、ここではわかりやすいものをちと小さめに引き剥がしちゃえばいいでしょう。
binary fileは checkout -p
では扱ってくれないみたいなので、git checkout messy_branch - binary_file
とかでとりこむ必要があるでしょう。
もちろん、変更を取り込んでちゃんと動くのを確認した後は commitするのを忘れずに!
- A (master)
|\- B99 (messy_branch)
\- C0 [*] (refactor_branch)
C0
が新しくできた、論理的にまとまった commitです。
messy_branchから取り込んだ内容を差っ引く
git checkout messy_branch
git rebase refactor_branch
こうやって messy_branchのなかから取り込んだ内容を差っ引きます。当然、conflictはするだろうから頑張って解消して rebase --continue
してください。
このときにも明らかに不要な変更は消しちゃうのもありです。
テストして commitすると、ツリーは以下のようになってるはず:
- A (master)
\- C0 (refactor_branch)
\- B98 [*] (messy_branch)
以下繰り返し
こうやって refactor_branch と messy_branchの間を行き来してどんどん論理的な単位を引き剥がしていきます。すると以下のようになるでしょう。
- A (master)
\- C0 - C2 - C3 - C1 - C4 (refactor_branch)
\- B95 [*] (messy_branch)
もう、B95
を rebaseしたらいらない変更しかない。そうなったら一段落です。
あとは、refactor_branchを git rebase -i master
して、適当に順序入れ替えたり、squashしたりして最後の調整してください。
まあ、これも結構時間かかりますが、確実にコードの理解は深まりますし、テスト中にさらに綺麗になったりするのでやる甲斐はある場合もあるかもしれませんよ、ということで。