53

私たちは同じプロジェクトに取り組んでいる開発者であり、プロジェクトに git を使用しています。2 人以上がたまたま同じファイルで作業していると、対処が困難な git の競合が発生します。これらの競合が発生すると、1 人の開発者が行った変更が失われることがあります。

彼らはチームで git をどのように使用していますか? git の競合を回避するための適切なフローは何ですか?

前もって感謝します。

4

8 に答える 8

62

ワークフローを深く掘り下げる前に、コミュニケーション プロセスの再構築に時間やお金を費やす前に、チームに次の 3 つの質問をしてください。

  1. 空白の規則を強制しますか?
  2. IDE を使用する場合、それらはすべて同じフォーマットとキーワード設定を使用しますか? たとえば、Eclipse はパラメーターを自動的にファイナライズできます
  3. テキストのビルド成果物を生成しますか? たとえば、js を縮小したり、.sassまたは.scssファイルから css ルールを生成したり、その場で xml 構成を構築したりしますか? チェックインしますか?

何年にもわたって対立を生み出し、集中型ワークフローで他の人がそれらを解決するのを支援してきた後、私は次の3つのことが私たちの集合的な対立の苦痛の大部分を引き起こしていると主張します。

マージ競合の原因

上の画像では、「!」スライスは正当なマージ競合を表します。ひどいマージの部分は、怠惰な空白規則または過度に攻撃的な IDE (または場合によっては過度にリファクタリングする開発者) から発生します。他のことを行う前に、IDE の設定と空白の規則を標準化してください。次に、各自のローカル リポジトリで次のコマンドを発行します。

# Enable the repository's stock pre-commit hook
mv .git/hooks/pre-commit.sample .git/hooks/pre-commit

その precommit フックは、コミットされた変更が空白エラーを導入するかどうかをチェックするコマンドgit commitのバージョンを含む、発行するたびに一連のチェックを実行します。git diff --checkその場合、コミットは拒否されます。本当にそれを回避する必要がある場合は、発行できますがgit commit --no-verify、発行しないでください。空白エラーは、バージョン管理の不発条例のようなものです。それらはマージの競合が発生するのを待っています。

空白をクリーンアップしたい場合、ファイルをリファクタリングしてインデントを改善したい場合、または純粋にフォーマットの変更を大量に行う場合は、個別のコミットで行い、競合する進行中の作業を最初にチェックインするようチームに警告します。

コード レビューを実施する場合は、すべてのレビュー担当者が最初に尋ねる質問を次のようにます。もしそうなら、レビューを不合格にします。または、それができない場合は、これらの変更が論理的な変更 (つまり、別のコミット) から十分に分離されていることを確認して、履歴が役立つようにします。

生成されたターゲットがチェックインされている場合、スタイルシート言語、RequireJS、および js ミニファイアーも競合を引き起こします。これらのテクノロジーによって作成されたファイルはビルド アーティファクトです。WAR アーカイブはチェックインしません。SASS でコンパイルされた CSS ファイルをチェックインしないでください。または、必要に応じて、.gitattributesファイルを使用して git がそれらをバイナリとして処理できるようにします。

これらすべてを行った後でもマージの競合が発生する場合は、ワークフローを改善してください。Gary Fixler の答えは完全に正しいです。正当なマージの競合が発生するのは、チームがプロジェクトの範囲についてうまくコミュニケーションできないか、うまくいかないためです。最初に、フォーマット規則が不十分に適用されていないことを確認してください。

于 2013-05-11T03:55:24.947 に答える
18

正直なところ、適切なワークフローには、適切なコミュニケーションと管理が必要です。チーム メンバーが同じことを頻繁に行って衝突を起こすべきではありません。毎日のスタンドアップや、チームの各メンバーが何をしているかを知っている気配りのあるマネージャー (少なくとも一般的には) は、多くの場合、これを制限するのに大いに役立ちます。

もちろん、それは製品の正確な性質に依存しますが、これは git の問題というよりは組織の問題です。実際、対立はしばしば「良い」ものと見なされます。なぜなら、人々が机から立ち上がったり、お互いに電話して対立が起こった理由や今後どうすべきかを話し合ったりするからです。これは、1 人の人物が 1 つの領域または一連のファイルを所有するか、または少なくともそのセクションの変更について話し合うための連絡先になるべきかを判断する機会です。

事前の計画を立てる以外に、git の競合を回避する方法はありませんが、これはどのバージョン管理システムでも同じ問題です。2 人の人がコードの同じセクションを変更するたびに、どちらが勝つかを判断する必要があります。これが、ソリューションのバージョナーに目を向けることが実際には適切ではなく、チームの方法と実践に目を向けることが適切である理由です。2台の車が同時に交差点を通過することはできませんが、互いに通過できる車を発明することは非常に難しいため、代わりに一時停止標識と信号機の制御システムを発明しました。これは同様の問題です。競合しないで同じものに 2 つの変更を加えることは実際にはできないため、ファイルの操作方法を制御する必要があります。

git でのロックを可能にするフロントエンドの 1 つを考えることができますが、マージ不可能なファイルタイプ以外では、その概念にはあまり同意しません。より良いチーム ワークフローを考え出す方が良いと思います。また、これを機会に、ファイルのマージが本当に上手になるようにします。私はそうしました、そして今それを何ヶ月もした後、紛争は私にとって動揺するものではありません.

于 2013-05-10T22:40:32.693 に答える
13

競合を回避する方法は 1 つしかありません。異なる人が同じファイルを同時に編集しないようにすることです。基本的に、各ファイルには、すべての編集に責任を持ち、所有権を別のユーザーに渡すことができる所有者がいます。ファイルの所有権は、所有権が明確である限り、特定の機能/ブランチに基づいて、または日常的に渡すことができます。

各ファイルに 1 人の所有者を割り当てることができない場合は、次のようにします。

  • 1 人の所有者に割り当てることができる小さなファイルにファイルを分割する必要があります。
  • GIT の競合が解決されることを絶対に要求します (個々の競合を解決するためにすべての編集者が一緒に座っています)。
  • 優れたマルチマージ ツールを使用して競合を視覚化し、解決します。
于 2013-05-12T00:13:11.423 に答える
5

注文。

他にも役立つ可能性のあることがいくつかあります。別々に投稿するとより明確になります。

新しいものを挿入する場所は、競合が発生するかどうかを判断するのに役立ちます。

従業員の名前のリストを想像してください

Andy, 
Oliver, 
Ivan,

その後、Brad と Patrick が参加し、その名前がリストに追加されます。あなたはブラッドを追加し、私はパトリックを追加します. リストの一番下に名前を追加し、git を使用してリストをマージします。結果は git ユーザーにはおなじみです:-

Merge branch 'Patrick' into Brad

Conflicts:
    names.txt

@@@ -1,4 -1,4 +1,8 @@@
  Andy, 
  Oliver, 
  Ivan,
  <<<<<<< HEAD
 +Brad,
  =======
+ Patrick,
  >>>>>>> Patrick

ここで、同じことを行ったものの、単純なアルファベット順の順序規則をリストに課したとします。2 つのブランチをマージすると、結果はもう少し快適になります:-

Andy,
Ivan,
Oliver,

1 つの名前を自分で追加してから、他の人の変更を git にマージして、別の名前を追加します。

Auto-merging names.txt
Merge made by the 'recursive' strategy.
 names.txt | 1 +
 1 file changed, 1 insertion(+)

そして、私たちは得る

Andy,
Brad,
Ivan,
Oliver,
Patrick,

次に誰が入社するかわからないので、効果的にリストにランダムに追加し、ランダムな場所に挿入することで、ファイル内の場所の競合が発生する可能性が低くなります。

于 2015-11-05T15:39:41.063 に答える
4

追加されたブロック開始を使用する

このようなソフトウェアでは...

function chess() 
{
    while (!end_of_game)
    {
        make_move()

左中括弧でブロックを開始する行は、単一の左中括弧で構成されるソフトウェア内の他の行と簡単に混同されます。同じソフトウェアをこのように書くと、ブロックの追加が前の行に開始されます...

function chess() {
    while (!end_of_game) {
        make_move()

私は個人的には好きではありませんが、Git は好きです。Git に似ていて、互いに間違われる行がはるかに少ないです。つまり、Git は編集を私たちと同じように認識する可能性が高く、競合がはるかに簡単になります。解決。

ブロックエンディングのコメント

コメントを使用して、似たような行を区別できるようにします。

JavaScript と JSON をたくさん書くと、このような行がたくさんあるかもしれません。

            }
        }
    }
)

物事をコメントすると、それらを区別できるようになります。

            }
        }
    }
) // end of weekdays()

            }
        }
    }
) // end of weekend()

git と同じように見えなくなりました。これは、git が変更をよりよく理解するのに役立ちます。のようなものを追加すると、

function a()
{
    ...
} // end of a()

git は、それを変更の単位として認識し、次のようなものを追加したとは思わない可能性が高くなります。

}

function a()
{
    ...

他の関数の終了直前。これで競合が防げない場合でも、git が変更を適切に (つまり、私たちが精神的に見る方法で) 認識して提示する場合、競合をより簡単に解決できる可能性があります。関数が何をするか、関数が取るパラメーターなどをコメントする説明的なヘッダーは、Git が隣接する関数の内容を混同するのを防ぐのにさらに役立ちます。

于 2015-11-05T16:12:02.973 に答える
1

誰が何を編集しているかを気にせずにバージョン管理の競合の数を減らすには、小さな変更を加えて段階的にコミット/プッシュするだけです。ファイルをすばやく変更してトランクに戻すことができるように、問題を十分に小さな断片に分割します。ブランチの寿命が短いほど、マージの競合が発生する可能性は低くなります。

それでも、ある時点で、2 人の人が同時に同じファイルを編集することがあります。それが起こったときの明らかな問題は次のとおりです。

「git の競合を解決する際の苦痛をどのように取り除くことができますか?」

答えは、トランクを引っ張ってブランチを頻繁にリベースする必要があるということです。競合がまだ小さいうちに、できるだけ早く競合に気付くことができます。この時点で、両方の開発者が一緒に座って、変更が新鮮なうちに進行する最善の方法について冷静に話し合う必要があります。

このアプローチは、開発者が少し前に行ったすべての変更の背後にある考え方を思い出すのに苦労しているリリース期限の直前に、パニック状態で巨大な存続期間の長いブランチの競合を解決しようとすることとは対照的です。

于 2016-02-11T16:37:48.240 に答える
1

変更をプッシュしたときに同僚に知らせる

競合の痛みを軽減するもう 1 つの方法は、変更をプッシュしたときに同僚に知らせることです。これにより、変更をプルし、その場でいくつかの競合を解決できます。あなたの最近の変化、あなたの心に新鮮なものと、彼らが取り組んでいること、彼らの心に新鮮なものとの間に矛盾が生じる可能性があります.

大規模な開発が完了するまで main ブランチから変更をプルせず、多くの人が同じ領域で行った変更と競合する場合、解決が難しくなります。

マージツールを使用する

ここに画像の説明を入力

Git の目的の 1 つはバージョン管理です。その他のプログラムは、ファイルのマージと競合の解決に特化しています。git と一緒に使用するように mergetool を構成すると、git が競合と見なす多くの問題を自動的に解決できます。または、少なくとも検査するのに非常に適切な推測を行い、問題がないように見える場合、またはツールを信頼している場合はそのままにしておくことができます。 .

これにより、解決のために賢明な決定を必要とする真の対立が少なくなります。

小さいファイルを使用する

mycontrollers.jsの下部に新しいコントローラーを追加し、 yourcontrollers.jsの下部に新しいコントローラーを追加します。問題ありません。

両方とも、 allcontrollers.jsの下部に新しいコントローラーを追加します: conflict.

(ただし、アルファベット順に並べることに関するアドバイスも覚えておいてください。M で始まる myNewController() はファイルの途中に配置され、Y で始まる yourNewController() は同じファイルの最後に配置される場合がありますが、ここでも競合は発生しません。)

于 2016-06-23T16:10:36.990 に答える