2009-07-23 7 views
4

2つの類似したプロセスが同じリポジトリの別々のクローン別のコンピュータで)。プロセスが実行されるたびに、リモートから最新のタグがフェッチされ、タグに基づいて一意の番号が導出されます。gitはリモートタグの移動を許可するのはなぜですか?アトミックなテストアンドセットにgit-tagを使用できないのですか?

など。これらのタグがリモートに存在する場合:1.0 1.1 1.2 1.3 プロセスは、次の番号として1.4を選択します。

プロセスを開始する前に、それは新しいタグを作成し、リモートにこのバックをプッシュは:

$ git tag 1.4 HEAD 
$ git push origin tag 1.4 

アイデアが、これはアトミック選択番号への道であるということでした。他のプロセスが同時に見ている場合は、1.4を使用することもできますが、タグをプッシュするには、1.4がすでに存在することがわかり、代わりに1.5を選択して再試行してください。

私は、gitタグのプッシュを原子として扱うことができたと私の希望でした。

残念ながら、いくつかの奇妙な理由で、gitを使用すると、特定の状況でリモートタグを移動させることができます。

たとえば、タグ1.4がorigin/masterに置かれてプッシュされたとします。もう1つのプロセスは、タグ1.4を、たとえばorigin/master ^に置くことを望んでいます。これには、タグを後方に移動させる必要があります。 Gitは '非早送り' というエラーでこれを拒否します:

プロセスA:

$ git tag 1.4 origin/master 
$ git push origin tag 1.4 
Total 0 (delta 0), reused 0 (delta 0) 
To /repo1 
* [new tag]   1.4 -> 1.4 

プロセスB:

$ git tag 1.4 origin/master^ 
$ git push origin tag 1.4 
To /repo1 
! [rejected]  1.4 -> 1.4 (non-fast forward) 
error: failed to push some refs to '/repo1' 

[OK]を、それは大丈夫です、プロセスBがこれを使用することができますが代わりに1.5を試してください。

しかし、このような状況を検討:

プロセスA:

$ git tag 1.4 origin/master 
$ git push origin tag 1.4 
Total 0 (delta 0), reused 0 (delta 0) 
To /repo1 
* [new tag]   1.4 -> 1.4 

プロセスB:

$ git tag 1.4 origin/master 
$ git push origin tag 1.4 
Everything up-to-date 

ああ。それは残念です - このタグは既にリモートに存在することを示していませんでした。

$ git push origin tag 1.4 -v 
Pushing to /repo1 
To /repo1 
= [up to date]  1.4 -> 1.4 
Everything up-to-date 

[OK]をので、私は、標準エラー出力のリダイレクトのいくつかの並べ替えを行う「=」を検索することができ、それがプロセスBは1.4がすでに使用中であることを判断できるようになります:実際に、それは-vで、ありません。

しかし、それは少し愚かです。

プロセスA:

$ git push origin tag 1.4 
Total 0 (delta 0), reused 0 (delta 0) 
To /repo1 
* [new tag]   1.4 -> 1.4 

プロセスB:

$ git push origin tag 1.4 
Total 0 (delta 0), reused 0 (delta 0) 
To /repo1 
    fd0e09e..c6cdac9 1.4 -> 1.4 

のargGそして、それはより悪くなります!何ですか? Gitは警告なしにリモートタグを移動しました!

だから、gitのリモートタグは根本的に壊れているように思えます。明示的な要求がなくても、単に「動かす」べきではありません。もっと重要なことに、彼らはデフォルトで移動を拒否すべきです。

また、git-tagコマンドは、タグをアトミックにテストして設定する方法を提供する必要があります。

しかし明らかにそうではありません。 git fetchを最初に実行すると、まだ競合のウィンドウがあり、競合があっても、3つのシナリオのいずれかでタグが単純に動くので、助けにはなりません!

ここでは何が起こっていますか?

タグをテストして設定する別の方法はありますか?

もしそうでなければ、人々は自動ビルド環境でどのようにビルド番号を割り当てて予約しますか? 2つのプロセスが誤って同じビルド番号を取得した場合、どのようにして確実に検出しますか?

git 1.6.1.2を使用しています。

答えて

8

ローカルラベルとして設計された軽量タグではなく、実際のタグオブジェクトを使用した場合、タグ付けの戦略が最適となると思います。

あなたは、-a(または-m/-F)のいずれかを指定することにより、-sまたは-uオプション(git help tagを)タグオブジェクトを作成することができます。

git tagのすべての呼び出しに-m "1.4 tag"を追加してみてください。タグオブジェクトは他のタグオブジェクトの子孫を指示することができないので、上記で失敗するプッシュケースはすべて失敗するはずです。

+1

あなたはこれでお金を稼いでいます。タグオブジェクトは、私が期待していたとおりに動作し、移動を拒否します。私は彼らが原子資源配分に適しているかもしれないと思います。 ありがとうございます。 – meowsqueak

+1

最後のコメント1つ - 注釈付きタグを前に移動することはできませんが、既存の注釈付きタグが同じコミットにある場合は、それを再適用することは可能です。したがって、両方のプロセスが同じコミットで同じタグを選択し、両方ともそのタグをうまく適用できる小さなウィンドウがまだあります。このような状況が発生したときにキャッチする余分なロジックを追加し、プロセスの1つを中止する必要があります。 – meowsqueak

+0

私が正しく理解していれば、これはバグのようなものです。タグオブジェクトが同じコミットを参照していても、git *は新しいタグオブジェクトへのタグ更新を拒否すべきだと思います。 –

関連する問題