GitHub Flow

Issues with git-flow

私はあちこちで人に Git を教えていますが、最近行ったほとんどすべてのクラスやワークショップで git-flow についてどう思うかと尋ねられました。 100万通りのワークフローがあり得るシステム(Git)を、十分にテストされた柔軟なワークフローとして文書化し、多くの開発者のためにかなりわかりやすい方法で機能させているのです。 これは、開発者がプロジェクト間や企業間で移動しても、この標準化されたワークフローに慣れることができるように、ある種の標準となりました。 新しい機能ブランチが master ではなく develop から開始されるのが気に入らないとか、ホットフィックスを処理する方法が気に入らないとか、そういう系統の意見をいくつか聞きましたが、それはかなり些細なことです。 フローを強制するのに役立つ大きなヘルパー スクリプトが開発されるほど複雑なのです。 これはクールなことですが、問題は、Git GUIでは実施できず、コマンドラインでしか実施できないことです。したがって、すべてのステップを手動で行う必要があるため、複雑なワークフローを本当によく学ぶ必要があるのは、コマンドラインから使用するほどシステムに慣れていない同じ人々だけなのです。 これは大きな問題です。

これらの問題の両方は、はるかに単純化されたプロセスを持つだけで簡単に解決できます。 GitHub では、git-flow を使用していません。 私たちは、ずっとシンプルなGitワークフローを使用しています。

そのシンプルさには、多くの利点があります。 ひとつは、人々が理解しやすいということです。つまり、すぐに理解することができ、滅多に失敗したり、間違ったステップを元に戻さなければならないことはありません。 もうひとつは、それを強制したりフォローしたりするためのラッパースクリプトを必要としないので、GUI などを使用しても問題ないことです。

GitHub Flow

では、なぜ GitHub で git-flow を使用しないのでしょうか。 まあ、一番の問題は、私たちが常にデプロイしているということです。 git-flow のプロセスは、主に「リリース」を中心に設計されています。 私たちは毎日、時には一日に何度も本番環境にデプロイしているので、実際には「リリース」というものはありません。 CI結果が表示されるのと同じ場所であるチャットルームのロボットを通じて、それを行うことができます。 私たちは、テストと出荷のプロセスをできるだけシンプルにして、すべての従業員が快適に行えるようにしています。

このように定期的にデプロイすることには、多くの利点があります。 数時間ごとにデプロイすると、大きなバグを大量に導入することはほとんど不可能です。 小さな問題が発生することはありますが、その場合は、非常に迅速に修正して再デプロイできます。 通常、通常のプロセスの外側で「ホットフィックス」などを行う必要がありますが、これは単に私たちの通常のプロセスの一部であり、ホットフィックスと非常に小さな機能の間に GitHub フローの違いはありません。

常時デプロイするもうひとつの利点は、あらゆる種類の問題に迅速に対処できることです。 私たちは、注意を喚起されたセキュリティ問題に対応したり、小さいけれども興味深い機能要求を信じられないほど迅速に実装したりできますが、それらの変更に対応するために、通常の、あるいは大規模な機能開発に対応するのとまったく同じプロセスを使用することが可能です。

How We Do It

では、GitHub Flowとは何でしょうか?

  • master ブランチにあるものはすべてデプロイ可能
  • 新しいことに取り組むには、master から説明的な名前のブランチを作成します(例: master から
      への移動)。
  • ローカルではそのブランチにコミットし、定期的にサーバー上の同じ名前のブランチに作業をプッシュする。
  • フィードバックや助けが必要なとき、またはブランチをマージする準備ができたと思うとき。 open a pull request
  • After someone else has reviewed and sign off on the feature, you can merge it into master
  • After it is merged and pushed to ‘master’, you can and should immediately deploy

これが全体のフローになります。 これは非常にシンプルで、非常に効果的で、かなり大規模なチームでも機能します。GitHub は現在 35 名の従業員がいますが、そのうち 15 ~ 20 名が同じプロジェクト (github.com) で同時に作業しているかもしれません。 ほとんどの開発チーム、つまりコンフリクトが発生する可能性のある同じロジックコードに同時に取り組むグループは、これくらいの規模かそれ以下だと思うんです。

では、これらのステップを順番に見ていきましょう。

#1 – master ブランチにあるものはすべてデプロイ可能

これは基本的に、システムの唯一のハード ルールです。 具体的で一貫した意味を持つブランチは 1 つだけで、私たちはそれを master と名付けました。 私たちにとっては、これはすでにデプロイされているか、最悪でも数時間以内にデプロイされることを意味します。 もし問題があれば、その問題を修正するためにコミットが戻されたり、新しいコミットが導入されたりしますが、ブランチ自体がロールバックされることはほとんどありません。

master ブランチは安定しており、常に、常に安全にそこからデプロイしたり、そこから新しいブランチを作成したりすることができます。 もし、テストされていない、あるいはビルドを破壊するようなものを master にプッシュしたら、開発チームの社会契約を破ることになり、普通はかなり嫌な思いをすることになります。 私たちがプッシュするすべてのブランチでテストが実行され、チャットルームに報告されます。ですから、ローカルでテストを実行していない場合は、単にサーバー上のトピックブランチ (単一コミットのブランチでも) にプッシュして、Jenkins がすべてをパスしたかどうかを教えてくれるのを待つことができるのです。

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

何か作業を開始したいときは、安定版 master ブランチから説明的な名前のブランチを作成します。 GitHub のコードベースでは、user-content-cache-keysubmodules-init-taskredis2-transition といったブランチがその例です。 この方法にはいくつかの利点があります。ひとつは、フェッチしたときに他の人が作業しているトピックを見ることができることです。 もうひとつは、あるブランチをしばらく放置しておいて、あとで戻ってきたときに、それが何だったかをかなり簡単に思い出せることです。

これは、GitHub のブランチ一覧ページに行ったときに、最近作業されたブランチとその作業量を簡単に確認できるのがよいところです。

github branch list

これは、今後の機能の一覧と現在の大まかなステータスを示すもので、ほとんど同じものです。 このページは、現在選択されているブランチに関連して、独自の作業が行われているブランチのみを表示し、最も最近作業されたものが一番上に来るようにソートしてくれます。 本当に興味がわいたら、’比較’ ボタンをクリックして、そのブランチに固有の実際の統一された diff とコミット リストを見ることができます。

つまり、この記事の時点では、リポジトリにマージされていない作業があるブランチは 44ありますが、そのうちの約 9 か 10 だけ先週にプッシュされたことが分かります。

#3 – 名前のついたブランチに常にプッシュする

もうひとつ git-flow と大きく異なる点は、サーバー上の名前のついたブランチに常にプッシュすることです。 私たちが本当に心配しなければならないのは、デプロイの観点から master だけなので、サーバーにプッシュしても誰も混乱しませんし、物事を混乱させることもありません。 さらに重要なのは、全員が常にコミュニケーションを取れるようになることです。

$ git fetchremote: 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 * charlock-linguist -> origin/charlock-linguist * enterprise-non-config -> origin/enterprise-non-config * fi-signup -> origin/fi-signup 2647a42..4d6d2c2 git-http-server -> origin/git-http-server * knyle-style-commits -> origin/knyle-style-commits 157d2b0..d33e00d master -> origin/master * menu-behavior-act-i -> origin/menu-behavior-act-i ea1c5e2..dfd315a no-inline-js-config -> origin/no-inline-js-config * svg-tests -> origin/svg-tests 87bb870..9da23f3 view-modes -> origin/view-modes * wild-renaming -> origin/wild-renaming

また、GitHub のブランチ一覧ページで、他のメンバーが何に取り組んでいるかを見ることができるので、それらを調査して、何か手伝いたいかどうかを確認できます。

#4 – いつでも Pull Request を開く

GitHub には Pull Requests という素晴らしいコードレビューシステムがありますが、あまり知られていないのではないかと心配です。 多くの人が、プロジェクトをフォークし、プロジェクトを更新し、メンテナにプルリクエストを送る、というオープンソースの作業に使っています。 しかし、内部コード レビュー システムとしても簡単に使用でき、私たちもそうしています。

実際、私たちはプルリクエストというよりも、ブランチ会話ビューとして使用しています。 GitHub では、1 つのプロジェクト (パブリックまたはプライベート) で 1 つのブランチから別のブランチにプルリクエストを送信できるので、「これをマージしてください」に加えて、「これについてヘルプまたはレビューが必要です」という場合に使用できます。

early pr message

ここで、Josh は Brian にレビューを依頼する cc と Brian がコードの 1 行についてアドバイスをするところを見ることができます。 さらにその下には、Josh が Brian の懸念を認め、それに対処するためにさらにコードをプッシュしている様子が見えます。

more discussion

最後に、まだ試験段階であることがわかります。

機能またはブランチの進行に行き詰まり、ヘルプやアドバイスが必要な場合、または、開発者が自分の仕事をデザイナーにレビューしてもらいたい場合 (またはその逆) 、あるいは、コードはほとんどないけれどスクリーンショットのカンプや一般的なアイデアがある場合にも、プル リクエストをオープンします。 GitHub システムでは、@ユーザー名を追加することで人を CC することができるので、特定の人のレビューやフィードバックが必要な場合は、PR メッセージで (上記の Josh のように) その人を CC するだけです。

この Pull Request 機能により、統合差分の個々の行、単一のコミット、または Pull Request 自体にコメントでき、単一の会話ビューにすべてをインライン プッシュできるのでクールです。また、ブランチにプッシュし続けることもできます。誰かが何かをやり忘れたとコメントしたり、コードにバグがあった場合、それを修正してブランチにプッシュすると、GitHub は会話ビューに新しいコミットを表示し、そのブランチで反復作業を続けることができます。 プルリクエストのディスカッションやコミットリストで、ブランチが最後に ‘master’ と同期されたのはいつなのかを簡単に確認できます。

master merge

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

#5 – pull request review の後にのみマージする

私たちは、単に master で直接作業をしたり、トピックブランチで作業をして、それが完了したと思ったらマージするのではなく、社内の他の誰かからサインオフを得ようとしています。 これは一般的に +1 や絵文字、または “:shipit:” というコメントですが、私たちは他の誰かに見てもらうようにしています。

shipit comment

それが得られ、そのブランチの CI が通れば、デプロイのために master にマージできますし、プッシュすれば自動的に Pull Request はクローズされます。

#6 – レビュー後すぐにデプロイする

最後に、あなたの仕事は完了し、master ブランチにマージされます。 つまり、今デプロイしなくても、人々はそれを元に新しい作業を行い、数時間後に行われるであろう次のデプロイで、それをプッシュすることになります。

私たちの Campfire ボットである hubot は、すべての従業員に対してデプロイを行うことができますので、シンプルに:

hubot depoy github to production

でコードをデプロイし、ゼロダウンタイムで必要なすべてのプロセスを再起動させます。 GitHub:

our campfire logs

6 人の異なる人 (サポート担当とデザイナーを含む) が 1 日で約 24 回デプロイしていることがわかります。 このプロセスはシンプルでわかりやすく、スケーラブルで強力です。 2 週間かかった 50 コミットの機能ブランチでも、10 分かかった 1 コミットでも可能です。 これは非常にシンプルで摩擦のないプロセスなので、1 回のコミットでもそれを行わなければならないことに悩まされることはなく、つまり、変更が非常に小さいか重要でない限り、プロセスをスキップまたは回避しようとする人はほとんどいません。 GitHub は非常に安定したプラットフォームであり、問題が発生してもすぐに対処され、新しい機能が急速なペースで導入されていることに、ほとんどの人が同意すると思います。

結論

Git 自体は理解するのがかなり複雑で、それを使うワークフローを必要以上に複雑にすることは、すべての人の一日に精神的なオーバーヘッドを追加することに過ぎません。 私は常に、チームのために機能する最もシンプルなシステムを使用し、それが機能しなくなるまでそうし、その後、絶対に必要な場合のみ複雑さを加えることを推奨します。

長期的な間隔(リリース間に数週間から数ヶ月)で正式リリースを行い、ホットフィックスやメンテナンスブランチ、その他出荷頻度が低いために生じることを行う必要のあるチームにとっては、git-flow は理にかなっており、私はその使用を強くお勧めします。

出荷の文化を確立し、毎日本番環境にプッシュし、常にテストとデプロイを行っているチームには、GitHub Flow のようなもっと単純なものを選ぶことをお勧めします。

Leave a Reply