2014年2月4日火曜日

gitworkflowsの補足(2) - よくある誤解

gitwokflows(7)に関する補助的な解説その2です。

gitworkflowsについて、ありがちな誤解や質問について妄想してみました。なお、これはgitworkflows(7)を自分のプロジェクトに採用することを考えた場合の話で、Git本家でやっているワークフローそのものの話ではありませんのでご注意を。


誤解: nextとpuって同じでは?

以下の点で違います。
  1. rebase(masterに巻き戻して再構成する)時の周知が必要かどうか: puは黙ってrebaseされますが、nextをrebaseする場合はその上で作業してそうな人たちに対してアナウンスが必要です。
  2. rebaseする頻度: nextは基本的にはrebaseしません。nextをrebaseするとしたらmasterからリリースした直後か、どうしてもrebaseしたいイベントがおこったときです。puはリリースに関係なく、もっと頻繁にrebaseします。
もちろん、使い捨てブランチは各開発者が手元に持つから公式な使い捨てブランチ(pu)は使わない、とか、開発スピード的にnextだけあれば十分、とか、開発初期でしょっちゅうrebaseするからnextはいらない、とか状況に合わせた適用は色々考えられます。

誤解: プルリクエストを使わない(GitHubでは採用できないワークフローだ)

この文脈での「プルリクエスト」というのはGitHubの機能のことを指しているのだと思いますが、単にGit本家のプロジェクトの運用としてGitHubプルリクエストを使ってないだけで、gitworkflowsを採用した場合にプルリクエストが使えなくなるわけではありません。
「mergeワークフロー」に書かれている内容に
レシピ: Push/Pull: ブランチ/トピックを公開する
git push   を実行し、皆にfetchできる場所を知らせます。
メールのような異なる方法で他の人に知らせる必要があるでしょう。
という部分がありますが、他の人(メンテナ)に知らせる手段をGitHubプルリクエストにすればいいだけです。

重要なのは、リポジトリの場所とブランチを他の人に知らせる、という点であり、その手段は必要な情報が伝わりさえすれば何でも良いです。

GitHubプルリクエストのインターフェースが便利なのであればそれを使えばいいですし、GitHubに依存したくなければ、どこか公開リポジトリにプッシュしたあとでトピックブランチ上で
% git request-pull master http://example.org/repo.git
を実行すれば、メンテナに送るべき情報を整形してくれますので、メール、チャット、バグトラックシステム等でメンテナ宛に送ればOKです。コピパビリティ(コピペしやすさ)は下がりますがプリントアウトした後FAXまたは郵送、伝書鳩などでもやろうと思えば可能ですw

誤解: pu, nextを使わないのでgitworkflowsは使わないほうが良い

pu,nextあるいはmaintも状況に応じて省略すればOKです。

まず、gitwokflowsの目的についての記事を先に見ていただきたいのですが、gitworkflowsの目的(または採用する利点)はmasterに綺麗な歴史を残すことです。歴史が綺麗だと後から調査(git bisectを含む)するとき便利なため、可能な限り綺麗な歴史を残すべきです(後から調査しないのであれば、そもそもバージョン管理など不要ですし)。

開発者の人数や開発者間のコミュニケーションチャネルの太さによっては、pu, nextを公式なリポジトリに作らなくてもmasterの歴史を綺麗に保てる場合は多いと思いますし、pu, nextの存在が開発上の心理障壁になるのであれば公式リポジトリに作るべきではありません(開発初期とか)。あるいは利用バージョンを厳密にコントロールできる環境(Webアプリとか)だからmaintが不要とかもあるかもしれませんね。

誤解: うちではgit-flowにしてるからgitworkflowsは採用できない

ある統合ブランチ(普通はmaster)の歴史を綺麗に保ちたいという要求があるのであれば、採用は検討すべきだと思います。git-flowだとdevelopが開発の中心になると思いますのでベースとするワークフローはgit-flowのまま、gitworkflowsのフローのmasterをdevelopと読み替えて必要なフローをdevelopに適用すれば良いです。(git-flowでの開発はしたことないので想像するしかないんですが、developの歴史をできるだけ綺麗にしておきたいって思いますよね?)

誤解: リリース用のブランチを切らないと不安だ

リリース前はmasterにバグフィクス(maintを含む)ブランチだけマージするようにすれば、同じことです。例えば以下のようなシチュエーションが考えられます。
  1. masterの先端からrelease-xを切ったとします。
  2. release-xにマージすべきトピックはリリースに向けたバグフィクスだけです。
  3. release-xの状態がよくなったのでリリースしました。
  4. masterにrelease-xをマージしました。
このとき、4のマージはFast-Forwardになります。なんだ、release-xなんていらなかったんだ。
「ちょっと待てよ、リリース期間中に機能追加のトピックをmasterマージしてたらFast-Forwardにはならないだろ?」→そういった機能追加トピックはnextにマージしたらいいと思います。

誤解: rebaseする前と後でミスしてないか不安だ

普通にトピックを作っててもrebaseしたくなるシチュエーションはしょっちゅうあるので、ほとんどgitworkflowsとは関係なくなってきてますが、rebase前とrebase後でgit diff して結果的なソースに違いがないことを確認するだけでチェック可能です。

例えばnextの巻き戻し&再構成はgitworkflows(7)には
git checkout next
git reset --hard master
git merge ai/topic_in_next1
git merge ai/topic_in_next2
...
とありますが、実際には
(各トピックを最新の状態にしておく)
git branch next.bak next
git checkout next
git reset --hard master
git merge ai/topic_in_next1
git merge ai/topic_in_next2
...
git diff next.bak
(出力がないのを確認して)
git branch -D next.bak
のように実施すれば、各トピックの中身が以前のnextにマージしたときから変更されていても最終形が同じことを確認できます。

話はそれますがrebaseとdiffの組み合わせは強力で、例えば開発中のあるトピックtopicをtopicAとtopicBの2つに分割すべきだということがわかった場合、
git checkout -b topicA topic
git rebase -i master           # topicAに必要なコミットだけピックアップ
git checkout -b topicB topic
git rebase -i master           # topicBに必要なコミットだけピックアップ
git merge topicA               # topicBにtopicAをマージして
git diff topic                 # もともとのtopicと結果に差がないことを確認
git reset --hard HEAD^         # topicBをマージ前に戻す
git branch -D topic            # topicを消す
のようにすれば分割に失敗がないことを簡単に確認できます。

まとめ

gitworkflowsは○○フロー(○○にはすきなワークフローを入れてください)と対立する概念ではなく、統合ブランチの歴史を綺麗に保ちたい場合はいつでも採用を検討する価値があるものです(逆に綺麗な歴史が必要なければ採用すべきではありません)。とはいえ、以前も書いたとおり、プロジェクトごとに最適なワークフローは異なるので、自分のプロジェクトに使えるエッセンスを抽出して応用するのが最も重要だと思います。

0 件のコメント:

コメントを投稿