2011-04-12 3 views
3

は、我々はSubversionのからのgitのために来て、私の会社ではgitために新しいしている、と週末に我々はコミットは、我々がしませんでした枝の公開バージョンに行われた私たちのリポジトリにブランチに状況に走りましたそこに欲しい。は、どのように私はより良いハンドルはgitの中で「閉」の分岐を汚染コミットすることができますか?

A -> B 

をそしてで支店を置くために悪いコミットを得た:私たちが持っていた

A -> B -> C -> D 

C及びDは、そのブランチにされたことがないはずです。このブランチは "閉鎖されました"という問題があります。これは私たちのソフトウェアのリリース版であり、このブランチには新たなコミットがあってはいけません。

バックBに私を取得しますが、タイムライン上で前進私を続け
A -> B -> C -> D -> !D -> !C 

:!!のあなたがで終わるよう

はSubversionではこの種の状況のうち唯一の方法は、DとCをコミットしました枝のマスターリポジトリと同期するブランチのリモコンで誰もがCとDを取得し、論理的に類似したBのバージョン(ただしB - B 'それを呼び出す)で終わるためにそれらを元に戻す必要がありますので。

私はthis solution for reverting commits in gitに遭遇しました。私たちの公開リポジトリはA -> Bに戻っていました。しかし、それは、誰かの作業マシン上のこのブランチのクローンが間違っていて、誰もが再クローンする必要があることを意味しました。私の修正はに達した:

git checkout thebranch 
git reset --hard <<commit # associated with commit B>> 
git push --force 
私は上記のリンクのルートを行くことになった

と、それは非常に物議をかもしている。

A)あなたは捨てて、このようにgitを公開リポジトリにコミット履歴ことができます文字通りコミットの現実を書き直す。

b)ブランチ(または作成したいブランチの新しいブランチ)にC -> Dを再注入する危険がないように、誰もが再クローンしなければなりませんでした。

私はやるべきだと思う:

git revert HEAD~2 
git commit 
git push 
をしかし、クローズされることになっているため、これは A -> B -> C -> D -> Eとして枝を残しているだろうし、それは本当にそれで C -> D -> Eを持つべきではありません。

私は3つの質問持っている:私はより良いクリーンアップを処理している可能性がどのように

  1. を? resetの代わりにrevertを使用しますか?ブランチ汚染のためのベストプラクティスは何ですか?
  2. 本当に戻っ枝push --forceは公開リポジトリで歴史を破壊しましたか?またはバックBにgitのロールをしましたが、C -> Dの記録を保持し、元に戻すが、私がいくつかの点でバックBに行われていた?それコミットログに復帰が表示されないのは間違いありませんが、私のアクションの記録は別の場所に保存されている可能性があります。
  3. どのようにこれらの変更は、最初の場所でそこに得ていることができなかったようにgitに「閉」の枝を扱うのですか?コミットBでタグをリポジトリに適用しましたが、ブランチ+タグを使ってリリースのソースを取得することになっていましたが、ブランチラインに変更を表示するのは恐ろしいことですコミットBの後で変更されます。パッチリリースのためにブランチからブランチしている人は、タグを見逃してしまい、C -> Dを新しいブランチに引き込むことができませんでした。
+0

ラベルを言うとき、gitタグについて話していますよね? – idbrii

+0

@pydave:申し訳ありません、はい、私はタグを意味しました。私の言葉の中でテクノロジーの交差汚染。 :) –

答えて

5

あなたは開発のためのリリース(「閉じた枝」)と枝(「オープン支店」)用のタグを使用する必要があります。これは、問題を解決するための代替ソリューション(リリースされたコードにタグを使用するだけでよい)と、今後この問題を防ぐ方法です。

v3.1を開発している間に、v3.1ブランチを作成できます。 v3.1が完了したら、最後のコミットにタグを付け、ブランチの名前を次の開発ブランチ(v3.2)に変更します。覚えておいてください:GitはSvnではありません!ブランチは、コミットへのポインタにすぎません。ブランチを削除してもコミットは削除されません(しかし、それらのコミットが別のブランチに含まれていない場合、ブランチが削除されるため、ブランチを削除する前にタグを作成する必要があります)。

あなたはV3.1(v3.1.1)にパッチを開発したい場合は、あなたがタグV3.1でブランチを作成します。

git checkout -b v3.1.1 v3.1 

これはあなたの開発者に明確になります(支店があります開発用とタグ用はリリース用です)、この問題が再び発生しないようにしてください。


戻った枝のプッシュ--forceは本当に公開リポジトリで歴史を破壊しましたか?

いいえ、コミットDのタグまたはブランチを作成した場合、そのブランチは正常です。ヘッドの最近の変更を確認するにはgit reflogを使用してください。それらのコミットはそこにあるはずです。 (または、git fsck。)を理解するための基礎として、他のバージョン管理システムを使用していないのgitの良い議論について


PeepCode's Git Internalsを試してみてください。それは無料ではありませんが、集中管理されたバージョン管理とは別にgitを理解するのがずっと良いと思います。 (Git Community Bookは良い無料の代替手段のように見えます)

+0

ありがとうございます。これはすぐには分かりませんでした(ブランチにタグをつけてから、開発を続けるために名前を変更します)。非常に知って良い。 –

1

点2について:なし。ブランチをリセット(ローカルまたはサーバー上)しても、履歴は破壊されません。 gitでは、ブランチは特定のコミットを指しているラベルに似ています(ブランチがチェックアウトされ、新しいコミットが行われるとラベルは自動的に前方に移動します)。ブランチをリセットすると、ラベルが後ろに移動したことを意味します。コミット自体は残っていますが、他のブランチがない場合は「非表示」になります。この場合は、git reflogを使用して回復できます。これにより、ブランチのないコミットの場合でも、すべてのコミットのハッシュが表示されます。 「削除された」コミットがまだそこにあることがわかります。それらを破壊する唯一のものはgit gc(git自体によって散発的に実行される)です。これは参照されていないコミットを削除します。

以前のポイントへの分岐をリセットして、それを強制的にプッシュすると、他の開発者がgit fetch -f origin branchname:branchnameを使用して、ブランチをリセットすることができます。再クローンニングする必要はありません(ただし、インデックスを強制的にフェッチすることによってインデックスが乱れるのを防ぐため、最初に別のブランチをチェックアウトする必要があります)。しかし、これは彼らがあなたが誤ってプッシュしたもの、過去のブランチにコミットを行った場合(再び、彼らはgit reflogで見つけることができる)コミットを「失う」ことになります。ブランチはとにかく閉鎖されているはずだったので、これはおそらくあなたにとっては問題ではありませんが、もし起こると、強制的にフェッチする前に新しいブランチを作成することができます。新しいブランチは引き続き最新のコミットを指し示し、git rebaseはコミットを適切なブランチに移植することができます。

+0

私は2つの答えを受け入れることができたらいいと思う。あなたの答えの後半は素晴らしいです。ありがとうございました。 –

+0

@Ian C .:喜んで助けました。 (何とか前半を改善できますか?)) –

+0

@Aasumnd - no。 @ pydaveは私のために1と3に答えました、あなたは2に答えました.3は私にとって最も重要でした。 –

関連する問題