1

事前にご協力いただきありがとうございます。

これが状況であり、gitがこれを回避する方法を提供しているかどうかを理解しようとしています:

2 人のユーザー (U1 と U2) はそれぞれ、ヒントに同期されたローカル リポジトリを持っています。

U1 は変更を行い、この変更をコミットしてリモートにプッシュします。U2 はまったく同じ変更を行い、コミットします。しかし、彼がプッシュしようとすると、プッシュできません。そこで、彼は git pull を (リベースなしで) 実行します。git は「merge branch master」メッセージを追加しました。ここで U2 がプッシュすると、彼のコミット (U1 によって行われた正確な変更) が再びリモートにプッシュされます。

これを回避する方法はありますか?ここでいくつかの重要なコマンドがありませんか?

4

2 に答える 2

3

まず、解決策 (潜在的に危険)。次に、git の使用方法に関する不要な警告:

危険な解決策

ステップ 1: リベース。

(難易度:中 --- 危険度:中)

コミット SHA や HEAD~4 などのコミットを示すコマンドを使用しgit rebase -i <something>ます(対話的にリベースするコミットの数で 4 を置き換えます)。<something>このコマンドは、対話型リベースの使用方法を説明するいくつかの段落を含むエディターを開きます。そこから重複したコミットを簡単に削除できますが、安全のためにブランチを別のブランチに保存する必要があります。git rebase -iは、使い方を学ぶのに非常に便利なコマンド/スイッチです。

ステップ 2: 強制的に押します。

(難易度: 低 --- 危険度: 高)

git push origin <branch name> --force変更をプッシュします。これは危険です。なぜなら、そのブランチからプルする人は同期しなくなり、ブランチを削除して再度フェッチする必要があるからです。ステップ 2aに従う必要があります。あなた以外に誰もそのブランチを使用していない場合は、プッシュを強制しても安全です。

ステップ 2a: 他の全員を更新します。

(難易度:中 --- 危険度:中)

git branch -D yourbranch # Delete your branch
git checkout origin/yourbranch # Check out the remote-tracking branch
git checkout -b yourbranch # Recreate the branch

GitHub と統合する CI ツールは影響を受けません。

警告

git-flowまたは同様のプロセスを使用する必要があります。2 人のユーザーが同じブランチにプッシュしないようにしてください。そうしないと、常にマージの競合が発生します。また、マスターにマージされたコミットや、複数の人がプルしたコミットをリベースしないでください。プッシュを強制する場合は、リベースされたコミットがマージされているすべてのマシンのすべてのレポのすべてのブランチにステップ 2aを適用する必要があります。マスターにあったコミットをリベースすると悪夢です。

于 2013-04-30T00:21:25.860 に答える
2

git のコミット オブジェクト (およびその SHA1) は、実際の差分だけでなく、作成者、コミッター、コミット メッセージ、コミットのタイムスタンプなどにも基づいて作成されるため、変更がまったく同じかどうかは問題ではありません。 .

U2 はpull(つまり、フェッチ + マージ) を実行し、pull --rebase(つまり、フェッチ + リベース) を実行しないため、新しいマージ コミットを取得します。ワークツリー自体)、したがってリモートにプッシュされます。以下の図は、あなたのケースで何が起こっているかを正確に示しているはずです。

State of remote(say origin)
U1C1 -- U2C2

State of U1 on start
U1C1 -- U2C2

State of U2 on start
U1C1 -- U2C2

U1 after creating a new commit
U1C1 -- U2C2 -- U1C3

U2 after creating a new commit
U1C1 -- U2C2 -- U2C3'

Remote after U1 pushes the change
U1C1 -- U2C2 -- U1C3

U2 after git pull (Merging origin/master into master)
U1C1 -- U2C2 -- U2C3' -- U2C3"
             \          /
              \ U1C3 --/

Remote after U2 does a git push
U1C1 -- U2C2 -- U2C3' -- U2C3"
             \          /
              \ U1C3 --/

U2 が代わりに a を行っていた場合git pull --rebase、U2 は少なくとも競合に気付き、コミットを取り下げたはずです。

git-flowユーザーが git ワークフローを管理するために使用できるようなツールがあります。リモートの裸のリポジトリで gitolite のようなものを使用する場合、pushいくつかのケースで操作を制御または拒否するための設定がそこにある可能性があります。

履歴を書き換えることでこの 1 回限りの修正が可能かもしれませんが、コミットが公開された後に履歴を書き換えるのはお勧めできません。古い履歴をまだ持っている可能性のあるユーザーが存在する可能性があり、それらのユーザーが相違点を見始める可能性があるからです。歴史。

于 2013-04-30T00:18:54.417 に答える