4

最近のいくつかのコミットを使用git resetgit rebaseて変更する必要があることがよくあります(再配置、複数のコミットを1つにマージするなど)。それには、押すときに強制オプションを使用する必要があります。残念ながら、これにより、リモートリポジトリ内の他のユーザーの変更も上書きされる可能性があります。

なぜ履歴を書き直す必要があるのですか?機能ブランチで多くの作業を行っており(具体的には、SwingからSWTに変換)、可能な限り短くする必要があるためです。これを実現するには、機能ブランチがフォークされる前に、一部のコミットをマスターに送信する必要があることがよくあります。

git pushリモートリポジトリから最新の変更を取得していない場合、強制的に失敗させるにはどうすればよいですか?

4

2 に答える 2

5

他の人がリポジトリ内の過去のコミットを見ていて、後でそれらを書き直した場合、問題が発生します。これは git の設計の一部にすぎません。

git は、コミットを書き換えたが最新のリポジトリを持っていることと、コミットを書き換えていないが、プッシュする前にマージする必要があるコミットを持っていることを実際に区別できません。最新のプッシュが検出される方法は、宛先 ref のすべてのコミットが、プッシュしている ref の履歴にあることを確認することです。これは早送りと呼ばれます。リベースすると、ローカル ブランチからコミットが削除され、新しい同様のコミットが作成されます。git は、これらの新しいコミットが履歴内の古いコミットと等しいことを確実に判断できず、保留中のマージと見なし、強制的にこれをオーバーライドして、宛先リポジトリに既にあるものをすべて上書きする必要があります。

したがって、強制すると、宛先にあるものは何でも上書きされます。これは仕様によるものです。さらに、あなたのリポジトリから引っ張ってきた他の人も、これが原因で問題に遭遇します。リポジトリ内のコミットの順序を反転するとしましょう:

A-------B-------C oldmaster
 \
  ------C'------B' master

他のユーザーがローカルに oldmaster のコピーを持っていて、master からプルすると、git はこれら 2 つのブランチをマージしようとします。C'これにより、とのパッチが二重に適用されますB'。良くない。Git はマージ時にこれらの問題を検出できる場合がありますが、正しくマージされたとしても、次のような問題が残ります。

A-------B-------C------D master
 \                    /
  ------C'------B'----

そして今、リベースされたコミットが復活しました。

rebase を使用しても役に立ちません。あなたはちょうど同じように終わることができます:

A------B------C------C'------B'

このような単純なケースでは、git は二重に適用されたパッチを検出してドロップできる可能性がありますが、保証はされていません。

結論として、他の人に見えるようになったコミットをリベースしないでください。まだローカルに保持しているプラ​​イベート ブランチである場合、または「DEVELOPMENT BRANCH - MAY BE REBASED - DO NOT BASE WORK ON THIS BRANCH」という重大な警告があるパブリック ブランチである場合は、必要なすべてのリベースを実行してください。しかし、他の誰かがその上に構築している瞬間に、歴史をいじるのをやめてください。

複数のユーザーと常に履歴をいじる必要がある場合は、 StGIT 、 guilttopgitなど使用して、機能ブランチをパッチのバッグとして操作する方がよい場合があります。その後、それらをパッチとして使用し、必要に応じてパッチを並べ替えることができます (ただし、コミット自体は変更しないでください!)。その後、変更を上流にプッシュするときが来たら、パッチを元の上流ブランチの上に線形化します。

于 2011-05-18T12:26:39.407 に答える
2

これに対する簡単な答えはわかりませんが、レポのフックで引っ張ることができる魔法があるかもしれません。それにもかかわらず、強制的な更新は、通常、マルチユーザー セットアップではお勧めできません。より良い答えは、git の使用方法を変更することだと思います。

まず、本当に歴史を書き換える必要があるのか​​?ほとんどの場合、正しい答えは履歴をそのままにして、新しいコミットのみを追加することです。

コミットを再配置する必要があると本気で考えている場合 (たとえば、コーディング標準を満たすためですか?)、それらのコミットを行った人々を最初から正しく理解するように教育することができない場合、別のセットアップを検討しましたか? 中央の "祝福された" リポジトリを 1 つ用意しますが、リリース エンジニア (または統合エンジニアやチームなど、呼び方は何でも構いません) のみがそこにプッシュできるようにします。通常のユーザーは、リポジトリを別の場所 (通常は自分のワークステーション) に公開し、プッシュする代わりに、リリース エンジニアにリポジトリからプルするように依頼します。その後、リリース エンジニアは変更をレビューし、必要に応じて再配置およびマージし、テストやその他の必要な手順を実行して、結果を bless リポジトリにプッシュします。

于 2011-05-18T12:08:06.327 に答える