130

現在、比較的大規模なコードベースでSubversionを使用しています。各リリースには独自のブランチがあり、修正はトランクに対して実行され、を使用してリリースブランチに移行されます。svnmerge.py

ソース管理を改善する時が来たと思います。私はしばらくの間Mercurialをいじっています。

Mercurialを使用してこのようなリリース構造を管理することについては、2つの学校があるようです。各リリースは独自のリポジトリを取得し、リリースブランチに対して修正が行われ、メインブランチ(およびその他の新しいリリースブランチ)にプッシュされるか、単一のリポジトリ内の名前付きブランチ(または複数の一致するコピー)を使用します。

どちらの場合でも、リリースブランチに含めるために変更をチェリーピックするための移植のようなものを使用しているようです。

お願いします。各アプローチの相対的なメリットは何ですか?

4

6 に答える 6

129

最大の違いは、ブランチ名が履歴に記録される方法です。名前付きブランチでは、ブランチ名が各チェンジセットに埋め込まれているため、履歴の不変の部分になります。クローンの場合、特定のチェンジセットがどこから来たのかについての永続的な記録はありません。

つまり、クローンはブランチ名を記録したくない簡単な実験に最適であり、名前付きブランチは長期的なブランチ( "1.x"、 "2.x"など)に適しています。

また、単一のリポジトリでMercurialの複数の軽量ブランチに簡単に対応できることにも注意してください。このようなリポジトリ内のブランチはブックマークできるので、簡単に見つけることができます。次のようになったら、会社のリポジトリのクローンを作成したとします。

[a] --- [b]

あなたはハックして作っ[x][y]

[a] --- [b] --- [x] --- [y]

[c]誰かがリポジトリに入れている間を意味[d]するので、プルすると次のような履歴グラフが表示されます。

            [x] --- [y]
           /
[あいうえお]

ここでは、1つのリポジトリに2つのヘッドがあります。作業コピーには、常に単一の変更セット、いわゆる作業コピーの親変更セットが反映されます。これを確認してください:

% hg parents

報告するとしましょう[y]。あなたは頭を見ることができます

% hg heads

そしてこれは報告[y][d]ます。リポジトリをのクリーンチェックアウトに更新する場合は、次のようにします(のリビジョン番号に[d]置き換えます)。[d][d]

% hg update --clean [d]

次に、そのhg parentsレポートが表示され[d]ます。これは、次のコミットが[d]親として持つことを意味します。したがって、メインブランチで気付いたバグを修正し、チェンジセットを作成できます[e]

            [x] --- [y]
           /
[a] --- [b] --- [c] --- [d] --- [e]

チェンジセットのみをプッシュ[e]するには、次のことを行う必要があります

% hg push -r [e]

[e]チェンジセットハッシュはどこにありますか。デフォルトでhg pushは、リポジトリを比較するだけで、、、が欠落していることがわかり[x]ます[y]が、まだ[e]共有したくない場合があります。[x][y]

バグ修正も影響する場合は、それを機能ブランチとマージする必要があります。

% hg update [y]
% hg merge

これにより、リポジトリグラフは次のようになります。

            [x] --- [y] ----------- [z]
           //
[a] --- [b] --- [c] --- [d] --- [e]

[z]との間のマージはどこに[y]ありますか[e]。ブランチを破棄することもできます。

% hg strip [x]

この話の私の主なポイントはこれです:単一のクローンは開発のいくつかのトラックを簡単に表すことができます。これは、拡張機能を使用しない「plainhg」にも常に当てはまります。ただし、ブックマーク拡張機能は非常に役立ちます。チェンジセットに名前(ブックマーク)を割り当てることができます。上記の場合、開発ヘッドとアップストリームヘッドにブックマークが必要になります。ブックマークはMercurial1.6でプッシュおよびプルでき、Mercurial1.8の組み込み機能になっています。

2つのクローンを作成することを選択した場合、開発クローンは作成後に次のように[x]なり[y]ます。

[a] --- [b] --- [x] --- [y]

また、アップストリームクローンには次のものが含まれます。

[a] --- [b] --- [c] --- [d]

これでバグに気づき、修正します。hg updateここでは、アップストリームクローンを使用する準備ができているので、そうする必要はありません。あなたはコミットして作成します[e]

[a] --- [b] --- [c] --- [d] --- [e]

開発クローンにバグ修正を含めるには、バグ修正をそこにプルします。

[a] --- [b] --- [x] --- [y]
           \
            [c] --- [d] --- [e]

とマージ:

[a] --- [b] --- [x] --- [y] --- [z]
           \ /
            [c] --- [d] --- [e]

グラフは異なって見えるかもしれませんが、それは同じ構造を持ち、最終結果は同じです。クローンを使用すると、精神的な簿記を少し少なくする必要がありました。

名前付きのブランチは、非常にオプションであるため、ここでは実際には登場しませんでした。Mercurial自体は、名前付きブランチの使用に切り替える前に、2つのクローンを使用して何年も開発されました。'default'ブランチに加えて'stable'というブランチを維持し、'stable'ブランチに基づいてリリースを作成します。推奨されるワークフローの説明については、wikiの標準の分岐ページを参照してください。

于 2009-05-21T00:27:38.467 に答える
29

履歴全体を1つのリポジトリにまとめたいと思います。短期レポのスポーンは短期実験用であり、リリースのような主要なイベントではありません。

Mercurialの失望の1つは、短命のブランチを作成し、それで遊んで、それを放棄し、ゴミを収集する簡単な方法がないように思われることです。ブランチは永遠です。歴史を捨てたくないということには共感しますが、超安価で使い捨ての枝は、git私が本当に見たい機能ですhg

于 2009-05-21T00:57:32.183 に答える
14

両方を行う必要があります。

@Normanから受け入れられた回答から始めます。リリースごとに1つの名前付きブランチを持つ1つのリポジトリを使用します。

次に、ビルドとテストのために、リリースブランチごとに1つのクローンを作成します。

重要な注意点の1つは、複数のリポジトリを使用している場合でも、transplant1)ハッシュを変更し、2)チェンジセット間で競合する変更がある場合に検出が非常に難しいバグが発生する可能性があるため、それらの間でチェンジセットを移動するために使用することは避けてください。移植とターゲットブランチ。代わりに通常のマージを実行する必要があります(プレマージなし:常にマージを視覚的に検査します)。これにより、@mgが回答の最後に言った結果になります。

グラフは異なって見えるかもしれませんが、それは同じ構造を持ち、最終結果は同じです。

もっと詳しく言えば、複数のリポジトリを使用する場合、「トランク」リポジトリ(またはデフォルト、メイン、開発など)には、すべてのリポジトリ内のすべてのチェンジセットが含まれます。各リリース/ブランチリポジトリは、トランク内の1つのブランチであり、古いリリースを残したい場合まで、すべてがいずれかの方法でトランクにマージされます。したがって、そのメインリポジトリと名前付きブランチスキームの単一リポジトリの唯一の実際の違いは、ブランチに名前が付けられているかどうかだけです。

それは私が「1つのリポジトリから始める」と言った理由を明らかにするはずです。その単一のリポジトリは、リリースで変更セットを探す必要がある唯一の場所です。バージョン管理のために、リリースブランチのチェンジセットにさらにタグを付けることができます。これは概念的に明確でシンプルであり、システム管理者をよりシンプルにします。これは、常に利用可能で回復可能でなければならない唯一のものだからです。

ただし、ビルドとテストが必要なブランチ/リリースごとに1つのクローンを維持する必要があります。できる限り簡単です。hg clone <main repo>#<branch> <branch repo>その後hg pull、ブランチリポジトリでは、そのブランチの新しいチェンジセット(およびマージされた以前のブランチの祖先チェンジセット)のみがプルされます。

このセットアップは、シングルプラーのLinuxカーネルコミットモデルに最適です(Lord Linusのように振る舞うのは気分が良くありません。当社ではロールインテグレーターと呼んでいます)。開発者がクローンを作成する必要があるのはメインリポジトリだけであり、プーラーは引き込む必要があります。ブランチリポジトリのメンテナンスは、純粋にリリース管理のためであり、完全に自動化できます。開発者は、ブランチリポジトリからプル/プッシュする必要はありません。


これは、このセットアップ用にリキャストされた@mgの例です。出発点:

[a] - [b]

アルファリリースに到達したら、リリースバージョンの名前付きブランチ(「1.0」など)を作成します。バグ修正をコミットします。

[a] - [b] ------------------ [m1]
         \                 /
          (1.0) - [x] - [y]

(1.0)名前付きブランチはコミットするまで存在しないため、は実際のチェンジセットではありません。(名前付きブランチが適切に作成されるように、タグの追加などの簡単なコミットを行うことができます。)

マージ[m1]はこの設定の鍵です。ヘッドの数に制限がない開発者リポジトリとは異なり、メインリポジトリに複数のヘッドを配置する必要はありません(前述の古いリリースブランチを除く)。したがって、リリースブランチに新しいチェンジセットがある場合は、すぐにそれらをデフォルトブランチ(またはそれ以降のリリースブランチ)にマージする必要があります。これにより、1つのリリースのバグ修正が、それ以降のすべてのリリースにも含まれることが保証されます。

その間、デフォルトブランチでの開発は、次のリリースに向けて継続されます。

          ------- [c] - [d]
         /
[a] - [b] ------------------ [m1]
         \                 /
          (1.0) - [x] - [y]

そしていつものように、デフォルトのブランチで2つのヘッドをマージする必要があります。

          ------- [c] - [d] -------
         /                         \
[a] - [b] ------------------ [m1] - [m2]
         \                 /
          (1.0) - [x] - [y]

そしてこれは1.0ブランチクローンです:

[a] - [b] - (1.0) - [x] - [y]

これで、次のリリースブランチを追加する練習になりました。2.0の場合、デフォルトから確実に分岐します。1.1の場合は、1.0から分岐するかデフォルトにするかを選択できます。とにかく、1.0の新しいチェンジセットは、最初に次のブランチにマージしてから、デフォルトにマージする必要があります。競合がない場合、これは自動的に実行でき、結果として単に空のマージになります。


この例が私の以前のポイントを明確にすることを願っています。要約すると、このアプローチの利点は次のとおりです。

  1. 完全な変更セットとバージョン履歴を含む単一の信頼できるリポジトリ。
  2. 明確で簡素化されたリリース管理。
  3. 開発者とインテグレーターのための明確で簡素化されたワークフロー。
  4. ワークフローの反復(コードレビュー)と自動化(自動空マージ)を容易にします。

UPDATE hg自体がこれを行います。メインリポジトリ にはデフォルトの安定したブランチが含まれ、安定したリポジトリは安定したブランチのクローンです。ただし、安定したブランチに沿ったバージョンタグはリリース管理の目的には十分であるため、バージョン管理されたブランチは使用しません。

于 2010-09-21T05:27:42.603 に答える
5

私の知る限り、主な違いはあなたがすでに述べたことです。名前付きの分岐は単一のリポジトリにあります。名前付きブランチは、すべてを1か所にまとめておくことができます。個別のレポは小さく、移動が簡単です。これについて2つの考え方がある理由は、明確な勝者がいないためです。どちらの側の議論があなたにとって最も理にかなっているのかは、おそらくあなたが一緒に行くべきものです。なぜなら、彼らの環境はあなたの環境に最も似ている可能性が高いからです。

于 2009-05-20T23:58:30.570 に答える
2

機能のサイズや再設計など、現在の状況に応じて、明らかに実用的な決定だと思います。フォークは、まだコミッターではない役割を持つ貢献者が、無視できる技術的オーバーヘッドで適性を証明することによって開発者チームに参加するのに本当に良いと思います。

于 2009-11-19T13:17:37.293 に答える
0

バージョンに名前付きブランチを使用しないことをお勧めします。それがタグの目的です。名前付きブランチは、ブランチのように、長期にわたる迂回を目的としていstableます。

では、なぜタグを使用しないのですか?基本的な例:

  • 開発は単一のブランチで行われます
  • リリースが作成されるたびに、それに応じてタグを付けます
  • そこから開発が続く
  • 特定のリリースで修正するバグ(またはその他)がある場合は、そのタグを更新し、変更を加えてコミットするだけです。

defaultこれにより、ブランチに名前のない新しいヘッドが作成されます。匿名のブランチ。hgでは完全に問題ありません。その後、いつでもバグ修正コミットをメインの開発トラックにマージして戻すことができます。名前付きブランチは必要ありません。

于 2014-08-09T14:26:20.730 に答える