どのGitブランチモデルが適していますか?


378

当社は現在、単純なトランク/リリース/ホットフィックス分岐モデルを使用しており、どの分岐モデルが会社または開発プロセスに最適かについてアドバイスを求めています。

  1. ワークフロー/分岐モデル

    以下は、これについて私が見た3つの主な説明ですが、それらは部分的に互いに矛盾しているか、(以下で説明するように)発生した後続の問題を整理するのに十分ではありません。したがって、これまでのところ、私たちのチームはそれほど優れたソリューションではないとしています。あなたはもっと良いことをしていますか?

  2. マージとリベース(複雑な履歴と順次履歴)

    pull --rebaseタスクが完了するまで、メインラインにマージして待機する必要がありますか?個人的には、どのベースでタスクが開始および終了したかを示す視覚的なイラストが保存されるため、私はマージに傾倒していますmerge --no-ff。この目的のためにも、私は好んで使用しています。ただし、他の欠点もあります。また、マージの有用な特性を理解していない人も多くいます-それは可換ではありません(トピックブランチをマスターにマージしても、マスターをトピックブランチにマージすることを意味するわけではありません)。

  3. 自然なワークフローを探しています

    私たちの手順は単純なルールでは特定の状況を捉えていないため、時々間違いが発生します。たとえば、以前のリリースに必要な修正はもちろん、必要なすべてのブランチに上流をマージできるように十分に下流に基づいている必要があります(これらの用語の使用法は十分明確ですか?)ただし、開発者がそれがさらに下流に配置されているはずであることに開発者が気付く前に、修正がマスターに組み込まれ、それがすでにプッシュされている場合(さらに悪いことに、マージまたはそれに基づくもの)、残りのオプションはチェリーピッキングであり、関連する危険。このような単純なルールを使用しますか?これには、他のトピックブランチを必ず除外する1つのトピックブランチのぎこちなさも含まれます(それらが共通のベースラインからブランチされている場合)。開発者は、機能を完成させて、今書いたコードがもう存在しないような別の感覚を開始したくない

  4. (cherry-pickによる)マージの競合を回避する方法

    マージの競合を発生させる確実な方法は、ブランチ間でチェリーピックすることです。ブランチを再びマージすることはできませんか?どちらのブランチでも、リバートで同じコミットを適用すると(これを行う方法は?)、この状況が解決される可能性がありますか?これは、私が大部分がマージベースのワークフローを敢えて推し進めない1つの理由です。

  5. 局所的な枝に分解する方法は?

    トピックブランチから完成した統合をアセンブルすることは素晴らしいことだと認識していますが、開発者による作業は明確に定義されていないことがあり(「ポーキング」のように単純な場合もあります)、コードがすでに「その他」のトピックに入っている場合は、上記の質問によると、それを再びそこから取り出すことはできませんか?トピックブランチの定義/承認/卒業/リリースをどのように行いますか?

  6. コードのレビューや卒業などの適切な手順はもちろんすばらしいでしょう。

    しかし、これを管理するのに十分なほど絡み合っておくことはできません。何か提案はありますか?統合ブランチ、イラスト?

以下は関連する質問のリストです:

また、Plastic SCMがタスク駆動開発に書き込む内容を確認し、Plasticを選択しない場合は、nvieの分岐モデルとそれをサポートするスクリプトを調べてください。


2
ああ、ありがとう、確かにそれは...私は実際にそのほとんどを読んだ...もの:-)。それは私が知っていることです-平凡な解決策に落ち着くのではなく、完璧を探し続けることです。多くの場合、これは間違いですが、この場合、多くの問題があり、手元にある解決策があまりにも厄介であるか不十分であるため、引き続き検討する必要があります。そこで、私はそれに関するすべての問題をリストすることにしました。
HiQ CJ 2010

プラスチックSCMブログがディスカッションに意見を投げかけました。少なくとも洞察に富んでいます。codicesoftware.blogspot.com
2010/08

1
「merge --no-ff」を使用する場合は注意が必要です。注意事項があるかどうかを確認してくださいsandofsky.com/blog/git-workflow.html
Doppelganger

1
@Doppelganger投稿したリンクで説明されている問題に--no-ffが具体的にどのように寄与しているのか、興味があります。私が説明した問題には、チェックポイントコミットでのbisectの失敗と、その場合に役立つgit blameの失敗がありますが、「-no-ff」がそれを使用しないのとは対照的に、どのように変更されるかはわかりません。--no-ffを使用したマージではファイルが変更されないという著者の不満はありますが、それがなければ、ファイルも変更されません。履歴には古いコミットしか表示されませんよね?
2014

その他の分岐モデル:cactusモデル barro.github.io/2016/02/…メインラインモデル bitsnbites.eu/a-stable-mainline-branching-model-for-git。この両方の分岐モデルは、gitflow以外のアプローチを提供します。
Mathieu Momal 2017

回答:


90

DVCSの新規開発者が理解する必要がある最も厄介な機能は、公開プロセスに関するものです

  • 必要なリモートリポジトリをインポート(フェッチ/プル)できます
  • 必要な(裸の)リポジトリに公開(プッシュ)できます

それから、いくつかのルールを尊重して質問を簡単にすることができます。

  • ブランチがプッシュされていない場合(最後のリベース以降にプッシュされていない場合)のみ、ブランチをリベースします
  • ベアリポジトリのみにプッシュする(Git1.7以降は必須)
  • リベースとマージに関するLinusのアドバイスに従ってください

今:

ワークフロー/分岐モデル

各ワークフローは、リリース管理プロセスサポートするためのものであり、プロジェクトごとに調整されています。
あなたが言及しているワークフローに追加できるのは、各開発者が機能ブランチを作成するのではなく、「現在の開発」ブランチのみを作成することです。なぜなら、真実は次のとおりです。開発者は、自分のブランチが何を生成するのか正確に知らないことが多いためです。機能、いくつか(機能が複雑になりすぎたため)、なし(リリースに間に合うように準備ができていないため)、別の機能(元の機能が「変形」したため)、...

「インテグレーター」だけが「中央」リポジトリに公式機能ブランチを確立する必要があります。これは、開発者がフェッチして、その機能に適合する作業の一部をリベース/マージすることができます。

マージとリベース(もつれた対順次履歴)

私はあなたが述べた私の答えが好きです(「社内開発のためのgit使用のワークフローの説明」)

私は自然なワークフローを探しています

修正の場合、各修正をバグ追跡からのチケットに関連付けるのに役立ちます。これにより、開発者はそのような変更をコミットする場所(つまり、「修正用」の専用ブランチ)を覚えやすくなります。
次に、フックは、検証されていないバグ修正から、またはプッシュすべきでないブランチからのプッシュから中央リポジトリを保護するのに役立ちます。(ここでは特定のソリューションはありません。これらすべてを環境に適応させる必要があります)

(cherry-pickによる)マージの競合を回避する方法

JakubNarębski彼の回答で述べたように、チェリーピッキングは、それが必要とされるまれな状況のために留保されるべきです。
設定にたくさんのチェリーピッキングが含まれている場合(つまり、「珍しいことではない」)、何かがオフになっています。

同じコミットをリバートに適用しますか(これを行う方法は?)

git revert それを処理する必要がありますが、それは理想的ではありません。

局所的な枝に分解する方法は?

ブランチがまだどこにもプッシュされていない限り、開発者はコミットの履歴を再編成する必要があります(最終的に開発がより明確で安定した形になったら)。

コードレビューや卒業などの適切な手順?

統合ブランチ(専用の統合内)リポジトリは、開発者が次のことを行うのに役立ちます。

  • そのリモート統合ブランチの上に彼/彼女の開発をリベースします(pull --rebase)
  • ローカルで解決する
  • 開発をそのリポジトリにプッシュします
  • 混乱しないインテグレーターに確認してください;)

@UncleCJ:ご覧のとおり、これは「最終的な質問」に対する最終的な回答ではありません;)
VonC 2010

私は理解しています、そして皮肉の感覚もいいです、それは大丈夫です;-)
HiQ CJ

3
@UncleCJアップストリームは、すべてのコミットが終了するところ(SVN用語ではリリースバージョンまたはトランク)のどこからでも、私の投稿から定期的にプルする場所です。下流はその下の全員です。ものをアップストリームに送信することは、それをリリースリポジトリ(linux-2.6など)にマージするプロセスであり、ダウンストリームは、そこからの変更、またはリポジトリからの変更で、そのような機能を開発している管理者があなたのミニオンに...チームを意味します。

2
@UncleCJ:「チェックインをトリミングして厳密に連続した履歴を取得するのはまだ難しいと思います」:Git1.7の方が簡単でrebase --interactive --autosquash、別のコミットメッセージの同じ先頭ですべてのコミットが自動的に移動します。それらのコミットがチケット番号を使用している場合(たとえば)、そのチケットに関連する修正がその時点で連続して行われなかった場合でも、オートスカッシュにより、それらのコミットの迅速な並べ替えが可能になります。
VonC

1
@UncleCJ:「厳密に連続した履歴(これは必要かどうか!)」:常に必要というわけではありませんが、機能の依存関係stackoverflow.com/questions/881092/…)とセマンティックコンフリクトstackoverflow.com/questions)の追跡に役立ちます/ 2514502 /…
VonC 2010

21

gitについて最も誤解されていることの1つは、その分散型の性質だと思いますし、私は間違っているかもしれません。これにより、必要に応じてSVNの動作を模倣することはできますが、動作する方法でSubversionと言うのは非常に異なります。問題は、ほとんどすべてのワークフローで実行できることです。

カーネル開発についての私の理解があれば(私はそれに焦点を当てます)、カーネルを開発するための独自のgitリポジトリがあります。Torvaldsが管理する1つのリポジトリlinux-2.6.gitがあり、リリースリポジトリとして機能します。「リリース」ブランチに対する機能の開発を開始したい場合、人々はここからクローンを作成します。

他のリポジトリはいくつかの開発を行います。アイデアは、linux-2.6からクローンを作成し、「新しい」機能が機能するようになるまで、何度でもブランチアウトすることです。次に、これが準備できたら、信頼できると考えられる誰かがこのブランチをリポジトリからプルして、メインストリームにマージすることを可能にします。Linuxカーネルでは、これはlinux-2.6.gitに到達して「カーネル」になるまで、いくつかのレベル(信頼された中尉)で発生します。

ここが混乱するところです。ブランチ名は、リポジトリ間で一貫している必要はありません。ですから、と呼ばれる私のリポジトリのブランチにあるマスターgit pull origin master:vanilla-codeからブランチを取得できoriginますvanilla-code。何が起こっているかがわかっていれば、それは本当に問題ではありません。すべてのリポジトリが互いにピアであり、SVNのような複数のコンピュータ間で共有されるだけではないという意味で分散されます。

したがって、これらすべてを念頭に置いてください。

  1. ブランチをどのように行うかは各プログラマ次第だと思います。必要なのは、リリースなどを管理するための中央リポジトリだけですhead。リリースはタグまたはブランチである可能性があり、ホットフィックスはおそらくそれ自体がブランチです。実際、パッチを当て続けることができるように、私はおそらくブランチとしてリリースを行うでしょう。
  2. 私はマージし、リベースしません。たとえば、リポジトリを取得し、それを複製し、ブランチして開発を行った後origin、リポジトリからプルする必要がある場合は、おそらく別のブランチを作成し、最新のものmasterをマージして、yourbranch他の誰かが最小限の労力で変更をプルできるようにします可能。私の経験では、本当にリベースする必要はほとんどありません。
  3. それは、Gitの仕組みとGitが何をすることができるかを理解する場合だと思います。時間がかかり、たくさんのよいコミュニケーションが必要です。他の開発者とgitを使い始めたとき、何が起こっているのかを本当に理解し始めただけで、今でもよくわかりません。
  4. マージの競合は便利です。私は知っています、あなたはそれがすべて機能することを望んでいますが、実際はコードの変更であり、機能するものに結果をマージする必要があります。マージの競合は、実際には単なるプログラミングです。私はそれらについて何をすべきかについて簡単な説明を見つけたことがないので、ここにあります:マージの競合があるファイルに注意して、行ってそれらを本来あるべきものに変更しgit add .、そしてgit commit
  5. しかし似合う。私が言ったように、各ユーザーのgitリポジトリは自分で操作するためのものであり、ブランチ名は同じである必要はありません。たとえば、ステージングリポジトリがある場合は、命名スキーマを適用できますが、リリースリポジトリ内でのみ、開発者ごとに行う必要はありません。
  6. これがマージ段階です。コードをレビュー/品質テストに合格したと見なした場合にのみ、リリースブランチなどにマージします。

お役に立てば幸いです。非常によく似た説明を投稿したばかりのVonCに気づきました...入力速度が足りません!

コメントからOPに関連しているように思われるので、商用設定でgitを使用する方法についてさらにいくつかの考えを編集します。

  • リリースレポジトリ(これを "レポジトリ"と呼びます)にはproduct.git、製品自体の世話を担当する多くの上級プログラマ/技術者がアクセスできます。これらは、OSSにおけるメンテナーの役割に似ています。
  • これらのプログラマーはおそらく部分的には新しいバージョンの開発を主導しているため、自分たちでコードを記述し、さまざまなリポジトリーを維持することもあります。彼らは本当に新しい機能のステージングリポジトリを管理し、独自のリポジトリを持っているかもしれません。
  • それらの下には、個々のビットの開発を担当するプログラマーがいます。たとえば、UIの作業は誰かが担当する場合があります。したがって、UI.gitリポジトリを管理します。
  • それらの下には、日常業務として機能を開発する実際のプログラマーがいます。

それで何が起こりますか?さて、誰もが「上流」のソース、つまりリリースリポジトリ(前日の開発からの最新の資料も含まれている可能性があります)から毎日の初めにプルします。誰もが直接これを行います。これは、おそらく「マスター」と呼ばれる、または私が「最新」と呼ばれる場合は、リポジトリのブランチに移動します。その後、プログラマーはいくつかの作業を行います。この仕事は彼らがよく分からないかもしれないので、彼らはブランチを作り、仕事をします。それが機能しない場合、ブランチを削除して戻ることができます。もしそうなら、彼らは現在取り組んでいるメインブランチにマージする必要があります。私たちは、これが取り組んUIプログラマであると言うでしょうlatest-ui、彼はないのでgit checkout latest-ui続きますgit merge abc-ui-mywhizzynewfeature。その後、彼は彼のテクニカルリード(UIリード)に言った、ちょっと、私はそのようなタスクを完了しました。したがって、UIリーダーはそうしgit pull user-repo lastest-ui:lastest-ui-suchafeature-abcます。次に、UIリードはそのブランチを調べて、実際にはそれは非常に良いことだと言って、にマージしui-latestます。次に、彼の下にいるすべての人に、自分のui-latest枝や彼らが付けた名前を引き抜くように言うかもしれません。そうすれば、この機能は開発者によって探求されます。チームが満足している場合、UIリーダーはテストリードにチームからプルして変更をマージするよう依頼する場合があります。これは、それをテストし、バグレポートなどを送信するすべての人(変更の下流)に伝播します。最後に、機能がテストなどに合格すると、トップテクニカルリードの1人がプログラムの現在の作業コピーにマージする可能性があります。その後、すべての変更が反映されます。等々。

これは「従来の」動作方法ではなく、SVN / CVSのような「階層的」ではなく「ピアドリブン」になるように設計されています。本質的に、誰もがコミットアクセスを持っていますが、ローカルでのみです。リポジトリへのアクセスであり、どのリポジトリをリリースリポジトリとして指定すると、階層を使用できます。


幅広い回答(および投票)に感謝します。有用な情報を引き出すために、もう2回読んでいきます。しかし、私たちはOSS開発委員会ではなく会社です。そして、私は「自分のリポジトリで好きなようにいじる」よりも明確なガイドラインで私の開発者を助ける必要があります。この投稿がどこにつながるか見てみましょう。私は良い勢いを感じています。
HiQ CJ 2010

@VonCありがとう。@UncleCJは真実ですが、確かにリリースマネージャーなどがいます。リポジトリにアクセスできる人なら誰でもこれらのことを行えます。開発に関しては、開発者に理由の範囲内で分岐する自由を与えてはどうですか。マージを合意するためのプロトコルがいくつかあり、中央リポジトリに好きな名前が付けられていれば、問題はありません。そうは言っても、一般的な命名スキーマは悪い考えではありません。私は個人のブランチにはinitials-version-feature-subbranchesを使用し、ブランチにはバージョンを使用する傾向があります。

@UncleCJ会社でどのように機能するかの例を追加しました。基本的には、マネージャーに置き換えられたOSSの役割ですが、アイデアは理解できます。開発者がオフラインでも作業できるという点でSVNよりも優れています(ネットをプル/プッシュする必要があるだけです)。うまく実装すれば、機能のテストが簡単になると思います。

うわー、それは実際には良い例です。卒業のためにそのようなものを使い始めるかもしれません。私はそれほど私がOSSを行っていないので誰もが規制されなければならないので、私たちは実際にはかなり小さくて平らなチームですが、私たちは厳しいスケジュールで効率的に協力し、チームとして学ぶ必要があることをあまり意味しませんでした。それが私がここでこれらの愚かな質問をしている理由で、後でチームの他のメンバーを助けることができます:-)。また、#gitから、不適切に定義されたベースラインとリードタイムを短縮するためのプレッシャーが組み合わさって、足を踏みにじっていることに気づきました。
HiQ CJ 2010

それは十分に公平です-私は最近それを試してみて、そして多くの失敗によって、そして私がその例を拾い上げた方法と同じように最近そこにいます...そしてまた、いくつかのOSSプロジェクトの働き方に適応しています。本当に重要なのは、どのようにブランチを作成し、リポジトリをどこに置くかは関係ないということです。あなたが望む方法でこれらを定義することができます。しかし、それはあなたがいくつかの興味深いことをすることを可能にします。とにかく、頑張って楽しんでください!

9

私が良い結果で使用したモデルは次のとおりです:

「祝福された」レポは、基本的にクライアント/サーバートポロジーです。

マスターブランチがないため、開発者はコードを「メインライン」にプッシュできません。

すべての開発はトピックブランチで行われます。誰がそれを担当しているのかを簡単に検出できるように名前空間に名前を付けました。

ホワイトボード上のブランチとカンバン/スクラムカードの間には、ほぼ1対1のマッピングがあります。

ブランチを解放するために、それは祝福されたレポにプッシュされ、かんばんカードはレビューの準備ができるように移動されます。

次に、ブランチがレビューで承認された場合、リリースの候補になります。

承認されたブランチのセットがマージされ、バージョン番号がタグ付けされたときにリリースが発生します。

祝福されたレポに新しいタグをプッシュすることで、新しい機能の新しいベースが可能になります。

マージの競合を回避するために、開発者は、リリースされていないブランチを最新のリリースタグに更新(マージ)してください。


2

個人的には、masterブランチにはリリース可能なコードのみを保持するようにしています。

新しい機能やバグ修正に取り組むときは、ブランチでそれを行います。また、ブランチでユニットテストを行います。すべてが正常に機能する場合は、マスターに再度マージ/リベースします。

私は、次のような一般的なブランチ命名規則も使用してみます。

  • バグ修正/再帰ループ
  • バグ修正/ sql_timeout
  • feature / new_layout
  • feature / enhanced_search
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.