web-dev-qa-db-ja.com

複雑なマージにどのようにアプローチしますか

これが契約です。私は新しい会社に加わり、ほぼ1年間触れられていない支店で作業を完了するように依頼されました。その間、マスターブランチは着実なペースで成長しています。理想的には、masterブランチからのすべての変更を機能ブランチにマージし、そこから作業を続行したいのですが、これにどのように取り組むかはあまりわかりません。

ブランチの両側で重要な変更を維持しながら、このマージを安全に実行するにはどうすればよいですか?

28
Vlad Spreys

基本的に、2つの(互換性がない可能性がある)コードを組み合わせる方法は開発の問題であり、バージョン管理の問題ではありません。 Gitマージコマンドはこのプロセスに役立ちますが、問題の形状によって異なります。

最初に両方のバージョンをベースと比較するのが最も理にかなっています。これは、これを前進させるための最良の戦略のアイデアを提供します。各ブランチの変更の性質と重複に基づいて、アプローチが異なる場合があります。

理想的なシナリオを想像してみてください。mainブランチとfeatureブランチはそれぞれ、コードの相互に排他的な部分のみを変更しているので、すべての変更をコミットして問題なく進むことができます。

もちろん、それはほとんど確かにそうではありませんが、問題は、この理想的なシナリオからどれほど離れているかということです。つまり、変更はどの程度混ざっていますか?

また、古い機能ブランチはどの程度成熟していましたか?良好な状態でしたか、それとも不明でしたか?どのくらいの機能が終了しましたか?

Mainブランチの関連コードが過去1年間で大幅に変更された場合、または機能が非常に成熟した状態にない場合、私は最新の新しいフォークを作成し、手動で古い機能を再度組み込むことを検討してください。これにより、段階的にアプローチして機能させることができます。

大量のコードを乱雑にマージしても機能しない場合は、デバッグが非常に困難になります。メインブランチがこの1年で大幅に変更された場合、大幅な設計変更が行われる可能性があります。機能させるには機能が必要です。 「競合の解決」を介してこれらの変更を行うことは適切ではありません。これは、すべての変更を一度に行い、機能することを期待するためです。この問題は、部分的に終了した古いブランチのバグの可能性によってさらに悪化します。

28
user82096

限られたgitの経験では、マスターがデタッチポイントから離れすぎている場合は、機能のブランチをもう一度再起動する方が速い場合があると言えます。

コードの背後にある履歴を知らずに2つのブランチをマージすること(プロジェクトに参加したばかりの場合)は非常に難しく、プロジェクトを最初からフォローしている開発者でさえ、マージで間違いを犯す可能性が高いと思います。

もちろん、これは機能ブランチが大きくない場合は理にかなっていますが、単純に古い機能ブランチを保持開いて、再びブランチマスターから手動で再-変更を導入その機能を構成します。私はそれが最も手動のアプローチであることを知っていますが、コードが欠落または移動した場合に完全に制御できるようにします。

この場合、シニアとペアプログラミングを行うのが最善のシナリオであり、コードをよりよく理解するのに役立ちます。
マージの競合とテスト時間を考慮に入れると、さらに速くなることもあります!

少なくとも、マージを行うために試行が明らかに最善の方法であると想定していました。うまくいかない場合や難しい場合は、チェリーピッキングを試してください。うまくいかない場合は手動で行ってください。

24
GavinoGrifoni

git-imerge は、まさにこの目的のために設計されています。 incrementalマージの方法を提供するgitツールです。段階的にマージすることで、2つのバージョン間の衝突に対処するだけでよく、それ以上は処理しません。さらに、個々のチェンジセットが小さいほど、はるかに多くのマージを自動的に実行できます。

17
Joe

メインラインヘッドを1年前の古いブランチにマージしようとすると、フラストレーションが生じ、額で机のへこみが深くなります。

メインラインは、何ヶ月にもわたって一度に到達しませんでした。開発もリリースもありました。 1つのモノリシックマージですべてを最新の状態にしようとすると、圧倒される場合があります。

代わりに、古いブランチが分割された後、最初の機能からメインラインにマージすることから始めます。 thatマージ機能を取得します。次に、次の機能がマージされます。等々。これらの機能のマージの多くは、競合することなくマージされます。古いブランチの現在の機能が、メインラインが進んだ方向との互換性を維持することを確認することは依然として重要です。

他の変更をマージする役割のために、古いブランチの先頭からブランチすることもできます。これは、誰かがそれを振り返るときのコミットと履歴が明確であり、各ブランチの役割とポリシーが何であるかを伝えることを確認することに関するものです。古いブランチは機能ブランチでした。作業しているのは、蓄積と調整のブランチです。

古い機能またはリリースブランチがまだ存在し、簡単にアクセスできる場合、これの多くはより簡単になります(一部の場所では、ブランチのリストが圧倒されないように、ある日付より古いブランチの名前をクリーンアップするポリシーがあります。 )。

このすべてにおいて重要なことは、メインライン履歴の各部分を適切にマージした後で、テストと修正を確実に行うことです。競合せずに何かがマージされても、それはcodeが競合しなかったことを意味します。古い機能へのアクセス方法が廃止または削除された場合は、マージが成功した後で修正が必要になる場合があります。

余談ですが、これは他のバージョン管理システムでも機能します。特定の機能のsvnコミットの特定のグループをブランチ(チェリーピッキング)にマージし、その機能で動作するようにブランチを修正してから、ホールセールsvnを実行するのではなく、svnコミットの次のグループをマージする必要がときどきありましたマージ。

1つのcanがここでgit cherry-pickを実行し、特定のコミットを取り込むことを許可しますが、これにはいくつかの欠点がありますプロセスを複雑にします。チェリーピックには、選択したコミットに関する情報は表示されません(コミットメッセージに追加できます)。これにより、実際に履歴のコミットを追跡することが難しくなります。

さらに、マスターを古くなったブランチに効果的に再生しないことを意味します。不完全な機能を選択する可能性があり、これらの機能が順序どおりに再生されない可能性があります。

履歴コミットから古いブランチにマスターするマージする必要がある主な理由は、古いブランチを保持できるようにすることです。これを、古いブランチの「将来の履歴」と呼びますあなたはそれについて推論することができます。履歴から古いブランチへのマージと、機能を再統合するための修正を明確に見ることができます。機能は、マスターするのと同じ順序で追加されます。そして、完了し、最後にマスターのヘッドから古いブランチにマージを行うと、everythingがマージされ、コミットを見逃していません。

6
user40980

ステップ1.コードについて学び、そのアーキテクチャーを分析し、最新の共通の祖先から両方のブランチで行われた変更を行います。

ステップ2.機能がおおむね独立しているように見え、主にコードのさまざまな領域に触れ、マージ、競合の修正、テスト、修正などを行う場合。これで十分です。それ以外の場合は、ステップ3に進みます。

ステップ3.競合の領域を分析し、機能への影響と理由を詳細に理解します。ここで明らかになるビジネス要件の競合が簡単に発生する可能性があります。 BA、他の開発者と適宜話し合います。干渉の解決に伴う複雑さを感じてください。

ステップ4.上記に照らして、競合しない部分のみをマージ/チェリーピック/カットアンドペーストすることを目的とするかどうか、および競合する部分を書き直すかどうかを決定します。OR機能全体を最初から書き直すため。

1
Brad Thomas

1。メインの開発者/リリースブランチとして使用されるブランチに切り替えます。

これは、システムへの最新の変更を含むブランチです。 mastercoredevにすることができます。会社によって異なります。あなたの場合、それはおそらく直接masterです。

git checkout master
git pull

プルして、メインの開発ブランチの最新バージョンを取得していることを確認します。

2。チェックアウトして、終了するはずの作業を含むブランチをプルします。

プルして、ブランチの最新のコンテンツが実際にあることを確認します。最初にローカルで作成せずに直接チェックアウトすることで、master(またはメインの開発ブランチ)からの新しいコンテンツが含まれないようにします。

git checkout <name of the obsolete branch>
git pull Origin <name of the obsolete branch>

。メインの開発ブランチを廃止されたブランチにマージします。

次のコマンドを実行する前に、git branchまたはgit statusと入力して、廃止されたブランチにいることを確認してください。

git merge master

git mergeコマンドは、指定されたブランチ(この場合はmaster)のコンテンツを現在のブランチにマージしようとします。

強調しようとしますを強調します。マージの競合が発生する可能性があります。これは、あなたとあなただけが解決する必要があります。

4。マージの競合を修正し、コミットしてプッシュして競合を修正

存在するすべてのファイルのマージ競合を修正した後、競合解決をOriginにステージングし、コミットしてプッシュします。

git add .
git commit -m "fixed the merge conflict from the past year to update the branch"
git Push

通常、git add .を呼び出して、コミットするすべてのファイルをステージングできます。マージの競合を処理する場合、必要なすべてのファイルを更新する必要があります。

追記

マージの競合を解決するのは面倒な作業になる場合があります。特にあなたが会社で新しい場合。まだすべてのマージ競合を解決するための適切な知識さえまだないかもしれません。

作業を続行する前に、時間をかけて慎重にすべての競合を調べ、適切に修正してください。


それが起こる可能性があるので、1年前のブランチで作業を開始し、現在の開発状態をブランチにマージします。マージの競合はまったく発生しません。

これは、システムが1年で大幅に変更されたにもかかわらず、1年前のブランチで実際に変更されたファイルに誰も触れていない場合に発生します。

0
Andy