Skip to content

Instantly share code, notes, and snippets.

@ukiuni
Forked from Gab-km/github-flow.ja.md
Last active June 3, 2016 23:39
Show Gist options
  • Save ukiuni/71a4039d11bad7234c95 to your computer and use it in GitHub Desktop.
Save ukiuni/71a4039d11bad7234c95 to your computer and use it in GitHub Desktop.
GitHub Flow (Japanese translation)

GitHub Flow

31 Aug 2011

git-flowの問題点 (Issues with git-flow)

私は人々にGitを教えるためにあちこちを飛び回っているが、最近のほぼすべてのクラスやワークショップでgit-flowについてどう思うかを尋ねられた。私はいつも、git-flowは素晴らしいと思うと答えている。何百万ものワークフローを持ったシステム(Git)を提供し、ドキュメントもあるし、よくテストされている。フレキシブルなワークフローは、実に容易なやり方で多くの開発者の役に立つ。標準的なものになりつつあり、開発者はプロジェクトや企業の間を移動しつつこの標準的なワークフローに馴染むことができる。

しかしながら、それ故の問題も抱えている。新しいフィーチャーブランチをmasterではなくdevelopから開始するとか、hotfixesを扱う方法といったことを好まないような人たちから多くの意見を聞く。

私が考える大きな問題のひとつは、それが、ほとんどの開発者や開発チームが実際に必要とするよりも複雑すぎやしないか、ということだ。フローの遂行を支援するために開発された巨大なヘルパースクリプトであり、あまりに複雑すぎる。

クールかもしれないが、GitのGUIツールには強制することができず、コマンドラインでしか使えないという問題がある。すべての手順を手動で行う必要もある。そのための複雑なワークフローをしっかりと学ばなければならない人たちが、コマンドラインでの作業に不慣れな人たちとイコールでもある。これは大きな問題点だ。

これらの問題点は、手順をもっとシンプルにするだけで容易に解決できる。GitHubでは、git-flowを使っていない。私たちが使う手順、いつも使っている手順はとてもシンプルなGitワークフローだ。

そのシンプルさには多くのメリットがある。ひとつは、簡単に理解できるということ。より素早く作業ができ、何かを台無しにしてしまうとか間違ってしまった手順をやり直すといったこともめったに起こらない。他にも、プロセスを支援するためのラッパースクリプトが必要ないため、GUIプログラムも問題なく使えるというメリットもある。

GitHub Flow

さて、なぜGitHubではgit-flowを使わないのだろうか? 私たちが常にデプロイをするから、というのが主な理由ではある。 git-flowのプロセスは主として「リリース」を中心に設計されている。 私たちはプロダクション環境へのデプロイを毎日(たいていは日に何回も)行うため、「リリース」というものがない。 私たちはチャットルーム内のロボットを通じてデプロイをすることができ、そこにはCIの結果も表示される。 私たちはテストとデプロイの手順を可能な限りシンプルにするようにしており、それらをすべての従業員が安心して行うことができる。

定期的にデプロイを行うことにはいくつかの利点がある。 数時間毎にデプロイをすれば、大きなバグが沢山入るようなことはほぼありえない。 小さなバグが入ることはあるだろうが、そういったものは素早く修正して再デプロイすることができる。 本来なら「hotfix」ブランチや普段の手順とは違う形で修正を行おうとするだろうが、私たちの場合はそれも通常のプロセスの一貫でしかない。GitHubのやり方では、hotfixと小さな機能追加とに違いはまったくない。

四六時中デプロイすることのもうひとつの利点は、あらゆる種類の問題を迅速に解決することが可能になる点だ。 私たちは、セキュリティ上の問題や、小さいけれども重要な機能の要望にとても迅速に対応することができる。 そして、それらの変更に対処する際は、普段の開発や大きな機能の開発をする際に使うのとまったく同じプロセスを使うことができる。

すべてが同じプロセスであり、すべてがとてもシンプルだ。

どうやっているのか

GitHub Flowとは何だろうか?

  • masterブランチのものは何であれデプロイ可能である
  • 新しい何かに取り組む際は、説明的な名前のブランチをmasterから作成する(例: new-oauth2-scopes
  • 作成したブランチにローカルでコミットし、サーバー上の同じ名前のブランチにも定期的に作業内容をpushする
  • フィードバックや助言が欲しい時、ブランチをマージしてもよいと思ったときは、プルリクエストを作成する
  • 他の誰かがレビューをして機能にOKを出してくれたら、あなたはコードをmasterへマージすることができる
  • マージをしてmasterへpushしたら、直ちにデプロイをする

これがフローのすべてだ。 とてもシンプルかつ効率的で、かなり大きなチームでも機能する。現在GitHubは35人で、そのうちの約15〜20人が一度に同じプロジェクト(github.com)で作業している(訳注:数字は2011年8月時点のもの)。 ほとんどの開発チーム(同時期に同じコードで作業をし、コンフリクトを発生させる可能性のある集団)はこれくらいか、もっと小さいと思う。 とりわけ、迅速に一貫したデプロイを行なうような進歩的なチームなら。

では、各ステップを順に見て行こう。

#1 - masterブランチのものは何であれデプロイ可能である

このシステムにおいて困難なルールは、おおむねこの点だけである。 明確に一貫した目的をもつ唯一のブランチがあり、それをmasterと呼ぶ。 それは、そのブランチが既にデプロイされているか、または最悪の場合でも数時間以内にはデプロイされる、ということを意味する。 ブランチが巻き戻される(作業内容を取り消すためにブランチが古いコミットを指すようにする)ことは非常に稀である − もし問題が起きたら、コミットは取り消されるか(reverted)、問題を修正した新しいコミットが行われるが、ブランチ自身がロールバックすることはほとんどない。

masterブランチは安定しており、常に、そう常にデプロイ可能かつそこから新しいブランチを作成できる状態になっている。 テストされていなかったり、ビルドを破壊するようなコードをmasterにpushした場合には、開発チーム間におけるソーシャルな取り決めを破ることになり、ちょっと気まずい思いをすることになる。 我々がpushしたすべてのブランチではテストが実行され、その結果がチャットルームに報告される。もしテストを手元で実行していない場合には、サーバー上のトピックブランチ(たいていは1つのコミットだけのブランチ)にpushして、Jenkinsがその結果を教えてくれるのを待つこともできる。

デプロイを行った時だけ更新されるdeployedブランチを用意することもできるが、我々はそのようなことはしない。 我々は、現在デプロイされているSHA(ハッシュ)をWebアプリ経由で公開するようにし、比較が必要な場合はそれを単にcurlするだけにしている。

#2 - masterから説明的なブランチを作成する

何か作業を始めたい時は、安定したmasterブランチから説明的な名前のブランチを作成する。 GitHubの今のコードでは、user-content-cache-keysubmodules-init-taskredis2-transitionといった感じだ。 このやり方にはいくつか利点がある。 fetchすると他の皆が現在作業しているトピックを知ることができる、というのが1つ。 しばらくの間ブランチを放っておいて後からその作業に戻った時に、何をしていたかすぐに思い出せるという利点もある。

GitHubのブランチリストページでは、最近どんなブランチで作業がされているのか、どれくらいの作業をしているのかを大まかに知ることができるので、その点でも素晴らしい。

github branch list

これは、もうすぐ実装される機能の一覧におおまかな現在の状況が付いているようなものだ。このページはとても素晴らしい − 現在選択しているブランチと比較して、それぞれのブランチがどのような固有の作業内容を含んでいるかだけが表示され、最も最近作業されたものが一番上に来る。興味を惹かれれば、Compareボタンをクリックして実際の差分を見たり、そのブランチ固有のコミット一覧を見ることもできる。

この文章を書いている時点では、我々のリポジトリにはまだマージされていない作業を含む44のブランチがあり、そのうち先週pushされたものが9個から10個ほどあることもわかる。

#3 - 名前をつけたブランチに定期的にpushする

git-flowとの大きな違いのひとつが、名前を付けたブランチを定期的にサーバーにpushするという点だ。我々がデプロイの観点で本当に気にしているものはmasterだけなので、サーバーへpushすることが誰かの手を煩わせたり、混乱を引き起こしたりすることはない − master以外のものはすべて、単に作業中の何かだということに過ぎない。

それによって、ノートパソコンを紛失したりハードディスクが故障した場合でも作業内容が常にバックアップされていることも確実となる。より重要なこととして、皆が定期的にコミュニケーションをとるようになる。単なるgit fetchが、皆が作業していることについてのTODOリストを与えてくれる。

$ git fetch
remote: Counting objects: 3032, done.
remote: Compressing objects: 100% (947/947), done.
remote: Total 2672 (delta 1993), reused 2328 (delta 1689)
Receiving objects: 100% (2672/2672), 16.45 MiB | 1.04 MiB/s, done.
Resolving deltas: 100% (1993/1993), completed with 213 local objects.
From github.com:github/github
 * [new branch]      charlock-linguist -> origin/charlock-linguist
 * [new branch]      enterprise-non-config -> origin/enterprise-non-config
 * [new branch]      fi-signup  -> origin/fi-signup
   2647a42..4d6d2c2  git-http-server -> origin/git-http-server
 * [new branch]      knyle-style-commits -> origin/knyle-style-commits
   157d2b0..d33e00d  master     -> origin/master
 * [new branch]      menu-behavior-act-i -> origin/menu-behavior-act-i
   ea1c5e2..dfd315a  no-inline-js-config -> origin/no-inline-js-config
 * [new branch]      svg-tests  -> origin/svg-tests
   87bb870..9da23f3  view-modes -> origin/view-modes
 * [new branch]      wild-renaming -> origin/wild-renaming

さらにそれによって、他の皆が何をしているのかを知ったり、助けを必要としていないかを確認するためにGitHubのブランチリストページを見るよう、全員が動くことにも繋がる。

#4 - いつでもプルリクエストを作る

GitHubには、残念だが十分な人々には知られていない Pull Requests と呼ばれる素晴らしいコードレビューの仕組みがある。多くの人々はオープンソースでの活動 ― プロジェクトをフォークする、プロジェクトを更新する、メンテナーにプルリクエストを送る ― にそれを使っている。しかし、プルリクエストは内部コードレビューの仕組みとして簡単に利用することもできて、我々はそうしている。

実際、我々はプルリクエストよりもブランチでの会話を見るのによりPull Requestsを使っている。GitHub上の1つのプロジェクト(パブリックまたはプライベート)において、あるブランチから他のブランチへプルリクエストを送ることができるので、「これをマージしてほしい」に加えて「こいつへの助けかレビューを必要としているんだ」と言うためにプルリクエストを使うことができる。

early pr message

JoshがBrianにレビューのためにCCして、Brianが何行かあるコードの1行へのアドバイスと共にやってきたのが分かるだろう。さらにその下ではJoshがBrianの懸念に同意して、それらに取り組むためより多くのコードをプッシュしたことが分かる。

more discussion

結局、我々はまだ試行フェーズにいる ― まだデプロイの準備ができたブランチではないということ、我々は実際にデプロイのために master にマージしたいと思うよりずっと前からコードをレビューするためにPull Requestsを使っている。

もしあなたが機能やブランチの進捗で嵌っていて助けやアドバイスが必要なら、またはもしあなたが開発者であなたの作業のレビューをしてくれるデザイナーが必要なら、あるいはたとえあなたがほとんどまたは全くコードを持っていないがスクリーンショットや一般的なアイディアがあるなら、プルリクエストをオープンするのだ。GitHubのシステム上で @ユーザ名 を追加することで人々をccすることができるので、もし特定の人のレビューやフィードバックが欲しいなら、(上でJoshがやったのを見たように)プルリクエスト・メッセージ内で単純に彼らにccすればいいのだ。

プルリクエストの機能によりunified diffや1コミット、またはプルリクエスト自体の各行にコメントを入れられて、インラインの全てを1つの会話ビューに持ってこられるので、これはクールだ。それはまたブランチにプッシュし続けられるので、もし誰かがあなたが何かをやり忘れたりコードにバグがあるとコメントすれば、あなたはそれを修正してブランチにプッシュし、GitHubが会話ビューに新しいコミットを表示して、こんな風にブランチに繰り返していられるのだ。

もしブランチがあまりに長くオープンになっていて、 master ブランチと同期しないようになってきたと感じたら、あなたのトピック・ブランチを master にマージして進み続けよう。ブランチが master に最後に更新したのがいつか、プルリクエストの議論やコミットリストで簡単に分かる。

master merge

ブランチですべてが本当に完了し、もうデプロイしてもいい頃だと感じた時、次のステップに進むことができる。

#5 - マージはプルリクエストがレビューされた後だけ

We don’t simply do work directly on master or work on a topic branch and merge it in when we think it’s done - we try to get signoff from someone else in the company. This is generally a +1 or emoji or “:shipit:” comment, but we try to get someone else to look at it.

shipit comment

Once we get that, and the branch passes CI, we can merge it into master for deployment, which will automatically close the Pull Request when we push it.

#6 - レビューのあとは直ちにデプロイする

Finally, your work is done and merged into the master branch. This means that even if you don’t deploy it now, people will base new work off of it and the next deploy, which will likely happen in a few hours, will push it out. So since you really don’t want someone else to push something that you wrote that breaks things, people tend to make sure that it really is stable when it’s merged and people also tend to push their own changes.

Our campfire bot, hubot, can do deployments for any of the employees, so a simple:

hubot depoy github to production

will deploy the code and zero-downtime restart all the necessary processes. You can see how common this is at GitHub:

our campfire logs

You can see 6 different people (including a support guy and a designer) deploying about 24 times in one day.

I have done this for branches with one commit containing a one line change. The process is simple, straightforward, scalable and powerful. You can do it with feature branches with 50 commits on them that took 2 weeks, or 1 commit that took 10 minutes. It is such a simple and frictionless process that you are not annoyed that you have to do it even for 1 commit, which means people rarely try to skip or bypass the process unless the change is so small or insignificant that it just doesn’t matter.

This is an incredibly simple and powerful process. I think most people would agree that GitHub has a very stable platform, that issues are addressed quickly if they ever come up at all, and that new features are introduced at a rapid pace. There is no compromise of quality or stability so that we can get more speed or simplicity or less process.

まとめ

Git itself is fairly complex to understand, making the workflow that you use with it more complex than necessary is simply adding more mental overhead to everybody’s day. I would always advocate using the simplest possible system that will work for your team and doing so until it doesn’t work anymore and then adding complexity only as absolutely needed.

For teams that have to do formal releases on a longer term interval (a few weeks to a few months between releases), and be able to do hot-fixes and maintenance branches and other things that arise from shipping so infrequently, git-flow makes sense and I would highly advocate it’s use.

For teams that have set up a culture of shipping, who push to production every day, who are constantly testing and deploying, I would advocate picking something simpler like GitHub Flow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment