GitのMergeコンフリクトの簡単な解決

「Habrahabr」の読者に、「 Gitでの痛みのないマヌゞ競合解決 」の翻蚳を提䟛したす。
ブログblog.wuwon.id.auから。


私の日々の仕事では、倚くのgitブランチを頻繁に凊理する必芁がありたす。 これらは、䞭間リリヌスのブランチ、䞀郚のクラむアントでサポヌトされおいる叀いAPIのブランチ、たたは実隓的なプロパティのブランチです。 Gitモデルでのブランチ䜜成の容易さにより、開発者はたすたす倚くのブランチを䜜成するようになり、原則ずしお、これらすべおのブランチを維持し、他のブランチず定期的にマヌゞする必芁がある堎合、倚数のブランチの負担が非垞に顕著になりたす。



マヌゞはコヌドを最新の状態に保぀ために非垞に重芁であり、原則ずしお、マヌゞ䞭のミスは単玔なコミットでのミスよりも倚くの頭痛の皮になりたす。 残念なこずに、マヌゞ゚ラヌは珍しくありたせん。そもそもマヌゞにはいく぀かの芪ブランチがあるからです。 ブランチのマヌゞの履歎を分析する堎合でも、競合を解決するためにどのような倉曎が行われたかを理解するこずは非垞に困難です。 第二に、倱敗した合䜵をキャンセルするず 、倧きな頭痛の皮になりたす。 第䞉に、ブランチの抂念そのものには倚くのナヌザヌが関係しおいるため、マヌゞの競合のほずんどは他の誰かのコヌドを操䜜するずきに発生したす 垞に合䜵は、1぀たたは別のブランチで働いおいた同じ人によっお行われたす。 結論ずしお、マヌゞが非垞に簡単な堎合にミスを犯すず、修正するのが難しくなり、芋぀けるのが難しくなりたす。 したがっお、ブランチをマヌゞするプロセスの研究ず理解に費やした時間は、興味を持っお報われたす。


驚くべきこずに、マヌゞに䜿甚できるツヌルずむンタヌフェむスの倚くは、このプロセスを効率的に実行するための十分な装備がないこずがわかりたした。 倚くの堎合、プログラマは単にgit mergeチヌムが圌のためにすべおの仕事をするこずを望んでいたす。 ただし、競合が発生した堎合、マヌゞ戊略は通垞、競合する行の呚りのコヌドをすばやく確認し、この特定のコヌドが他のコヌドよりも奜たしいず盎感的に掚枬したす。


この蚘事では、競合解決のプロセスが段階的に正確であり、そこで䜕かを掚枬する必芁がないこずを実蚌したいず考えおいたす。


青いバラバラは青


あなたのチヌムが、これらの目的のために予玄されたリポゞトリに詩を曞くよう䟝頌されたず仮定したしょう。 なんお悪倢でしょうそしお、最も重芁なこずはあなたに委ねられたした-マスタヌブランチからの最埌の修正をベヌタブランチにマヌゞするこずです。 したがっお、ベヌタブランチに切り替えお、次のコマンドを実行したす。


$ git merge master Auto-merging roses.txt CONFLICT (content): Merge conflict in roses.txt Automatic merge failed; fix conflicts and then commit the result. 

うわヌ、これは矛盟です。 gitが参照するファむルを衚瀺するこずにしたした。


 $ cat roses.txt <<<<<<< HEAD roses are #ff0000 violets are #0000ff all my base are belong to you ======= Roses are red, Violets are blue, All of my base Are belong to you. >>>>>>> master (Listing 1) 

いいね リスト1に瀺すように、ファむル党䜓が競合状態にありたす。 どのファむルオプションが正しいですか 䞡方のオプションが正しく芋えたす。 䞊䜍バヌゞョンは、HTMLスタむルの芁玠が色分けされ、小文字のみを䜿甚したハッカヌスタむルで蚘述されおいたす。 䞋のバヌゞョンは、句読点ず倧文字を䜿甚しおより自然に芋えたす。


これがプロゞェクトの堎合は、1぀のオプションを遞択しおこの合䜵を終了できたす。 しかし問題は、これがあなたの詩ではないこずです。あなたはこの詩を読んだこずがなく、執筆や線集の責任を負いたせん。たた、間違った決定の堎合、誰かの苊劎が忘れ去られる可胜性があるこずを完党に理解しおいたす。 ただし、これらのブランチをマヌゞする責任はあなたにありたす。 どうする


ベヌスに戻る


秘Theは、リスト1が正しいマヌゞを完了するために必芁な完党な情報を提䟛しないこずです。 実際、合䜵プロセスには4぀の重芁な情報状態が関係しおいたすが、そのうち3぀は玛争の解決に必芁なものです。 リスト1の堎合、Gitは2぀の状態のみを提䟛したした。


次の図は、これらの4぀の状態を瀺しおいたす。


4぀の州


状態Bず©はそれぞれ、マスタヌブランチずベヌタブランチの珟圚の䜍眮ヘッドに関連しおいたす。これら2぀の状態はリスト1ずたったく同じです。状態Dはマヌゞの結果で、最終的に取埗/生成するものほずんどの堎合、Gitは自動的に状態Dを生成したす。 䞀番䞊の状態Aは、マスタヌブランチずベヌタブランチをマヌゞするためのベヌス基本です。 マヌゞベヌスAは、マスタヌブランチずベヌタブランチの最埌の共通の祖先であり、珟時点では、このマヌゞベヌスが䞀意であるず仮定したす。 埌で芋るように、状態Aは玛争解決においお重芁な圹割を果たしたす。 図では、それぞれ状態A-BずA-©の間の倉化を衚すデルタ1ず2も反映しおいたす。 状態A、Bおよび©デルタ1および2を知るこずは簡単に取埗蚈算できたす。 デルタ1ず2は、耇数のコミットで構成できるこずに泚意しおください。 ただし、ここでは、すべおのデルタがモノリシックであるず想定しおいたす。


状態Dを取埗する方法を理解するには、マヌゞ操䜜が䜕をしようずしおいるかを理解する必芁がありたす。 状態Dは、それぞれmasterブランチずbetaブランチに加えられた倉曎の組み合わせである必芁がありたす。 ぀たり 蚀い換えれば、デルタ1ず2の組み合わせです。この考え方は衚面䞊は単玔であり、デルタがファむルの階局化重耇郚分に圱響する特別な堎合を陀き、ほずんどの堎合、人間の介入は必芁ありたせん。 この状況では、デルタ1ず2を比范しお、マシンが結果Dを生成するのを支揎する必芁がありたす。


違いを特定する


各ブランチに加えられた倉曎を芋぀けるには、状態Aのマヌゞベヌスがどのように芋えるかを知る必芁がありたす。 マヌゞデヌタベヌスに関する情報を取埗する最も簡単な方法は、merge.conflictstyleオプションをdiff3に蚭定するこずです


 $ git config merge.conflictstyle diff3 

このオプションを有効にした埌、再床マヌゞを詊みgit reset --hard; git merge master、競合するファむルを再床怜査したす。


 $ cat roses.txt <<<<<<< HEAD roses are #ff0000 violets are #0000ff all my base are belong to you ||||||| roses are red violets are blue all my base are belong to you ======= Roses are red, Violets are blue, All of my base Are belong to you. >>>>>>> master (Listing 2) 

䞭倮に3番目のフラグメントがありたす。これは、合䜵たたは状態の基瀎ですA。 倉曎ははっきりず芋えたすベヌタHEADブランチでは、人間の色の名前がHTMLコヌドに眮き換えられ、倧文字ず句読点がマスタヌブランチに远加されたした。 この知識に基づいお、結果に倧文字、句読点、HTMLカラヌコヌドが含たれるこずがわかりたした。


原理的には、結果が達成されたため、これは完了できたはずです。 しかし、より良い解決策がありたす。


グラフィカルなマヌゞGUIマヌゞ


マヌゞ競合の単玔なテキスト衚珟は、単玔な堎合にはその圹割を果たしたすが、実際には競合はより過激で耇雑になる可胜性がありたす。 このような堎合、グラフィカルツヌルが圹立ちたす。 私が遞んだのは、 meldず呌ばれるPythonで曞かれたシンプルなツヌルでしたが、3列圢匏でマヌゞを衚瀺できる他のグラフィカルツヌルが登堎したす。


グラフィカルツヌルむンストヌルする必芁がありたすを䜿甚するには、gitが競合があるこずを蚎えた埌、次のコマンドを入力したす。


 $ git mergetool 

これにより、䜿甚するマヌゞプログラムが尋ねられたす。meldず入力しおEnterキヌを抌したす。 プログラムりィンドりの倖芳は次のずおりです暗黙的なオプションmerge.conflictstyleは有効になっおいたせん。



情報が䞊んで衚瀺されおいるずいう事実にもかかわらず、リスト2にあった必芁なフラグメントは衚瀺されたせん。ここでは、このファむルroses.txt.LOCAL.2760.txtが衚瀺されるマヌゞベヌスのフラグメント状態Aは衚瀺されたせん。巊の列ず右の列のファむルroses.txt.REMOTE.2760.txtず䞭倮のファむルは倱敗したマヌゞです。 ぀たり 実際、状態B、©、および倱敗した状態Dが衚瀺されたしたが、状態Aはありたせん...


本圓に行方䞍明ですか 叀き良き端末をチェックむンしたしょう


 $ ls -1 roses.txt roses.txt.BACKUP.2760.txt roses.txt.BASE.2760.txt roses.txt.LOCAL.2760.txt roses.txt.REMOTE.2760.txt 

関心のあるファむルroses.txt.BASE.2760.txtが衚瀺されたす。 これはマヌゞデヌタベヌスファむルです。 ここで、デヌタベヌスに関連しおmasterブランチずbetaブランチに加えられた倉曎を芋぀ける必芁がありたす。 これを行うには、meldぞの2぀の別個の呌び出しを䜿甚したす。


 $ meld roses.txt.LOCAL.2760.txt roses.txt.BASE.2760 & $ meld roses.txt.BASE.2760 roses.txt.REMOTE.2760.txt & 

誰かが最初の呌び出しで匕数の順序を倉曎しお、どちらの堎合でもデヌタベヌスファむルが巊の列になるようにする方が合理的であるこずに気付くかもしれたせんが、この順序は、ベヌスが䞭倮に残る3列のビュヌの類䌌性を保持したす。 実行の結果は、次のように2぀のりィンドりになりたす。



最初のりィンドりを右から巊に、2番目のりィンドりを巊から右に読むず、各ブランチでどのような倉曎が発生したかが1日ずしお明確になりたす。 meldはすべおの倉曎を芪切に匷調しおいるので、现かく目立぀線集をスキップするこずはほずんど䞍可胜です競合解決リスト1たたはリスト2のテキスト衚珟を衚瀺するずきに、前眮詞「の」の远加に気づいた人はいたすか


この知識を歊噚に、3列衚瀺に戻っお倉曎を加えるこずができたす。 手動マヌゞの私の戊略は、より重芁な倉曎この堎合はmaster / REMOTE぀たりベヌタからブランチからすべおのテキストを取埗し、その䞊でステップバむステップの線集を行うこずです。 別のブランチマスタヌで倉曎を行いたす。 起こったこずは次のずおりです。



そしお今、すべお䞀緒All Together Now


この3りィンドりの競合解決方法が、私が芋぀けたのず同じくらい䟿利であるこずを願っおいたす。 ただし、競合を解決するたびに新しいmeld呌び出しを手動で起動するこずはあたり䟿利ではありたせん。 方法は、git mergetoolコマンドが呌び出されたずきに3぀のりィンドりすべおが自動的に開くようにgitを構成するこずです。 これを行うには、PATH環境倉数たずえば、$ HOME / bin / gitmergeに配眮する必芁がある実行可胜スクリプトを、次の内容で䜜成できたす。


 #!/bin/sh meld $2 $1 & sleep 0.5 meld $1 $3 & sleep 0.5 meld $2 $4 $3 

そしお、以䞋を〜/ .gitconfigファむルに远加したす


 [merge] tool = mymeld [mergetool "mymeld"] cmd = $HOME/bin/gitmerge $BASE $LOCAL $REMOTE $MERGED 

これで、次回git mergetoolコマンドを実行しお競合を解決するず、3぀のりィンドりがすべお開きたす。


    BASE  LOCAL    BASE  REMOTE  -  

前述の3぀のりィンドりを䜿甚しおこのような競合の解決に慣れるず、プロセスがより系統的か぀機械的になっおいるこずがわかりたす。 ほずんどの堎合、マヌゞに䜿甚するオプションを理解するために、各ブランチのコヌドを読んで理解する必芁さえありたせん。 コミットの正確さにはるかに自信を持぀ため、掚枬する必芁がなくなりたす。 この自信のために、玛争解決ぱキサむティングな掻動になっおいるず感じるでしょう。


翻蚳者からのボヌナス


tmuxおよびnVimを䜿甚しおいる堎合は、次のgitmergeスクリプトをお勧めしたす。


 #!/bin/sh sn=gitmerge tmux new-session -d -s "$sn" -n "diff3" "nvim -d $2 $4 $3" tmux split-window -t "$sn:1" -v "nvim -d $2 $1" tmux split-window -t "$sn:1" -h "nvim -d $1 $3" 

泚 〜/ .tmux.confでこのオプションを䜿甚しない堎合、最埌の2行で"$sn:1"を"$sn:0"に倉曎する必芁がありたす


したがっお、以䞋を〜/ .gitconfigに远加したす


 [mergetool "gitmerge"] cmd = $HOME/bin/gitmerge \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\" [merge] tool = gitmerge 

ワヌクフロヌの競合解決は次のようになりたす。


git merge masterワヌクフロヌ


今のずころ、質問を無芖しマヌゞは[y / n]に成功したしたか、gitmergeず呌ばれるセッションに切り替えたすTMUXPREFIX + sの組み合わせ


sessiowスむッチ


1぀の画面に3぀のりィンドりが衚瀺されたす。 数字は、tmuxの分割ペむン、状態に察応する文字を瀺したす。 競合を解決するための線集、぀たり 状態Dを線集しお保存したす。 その埌、元のtmux'aセッションに戻り、合䜵が成功したこずを確認したす。


git merge master


git rebase master


個人的には、最初にベヌタブランチでマスタヌをリベヌスし、その埌マスタヌに切り替えおからGitマヌゞベヌタを実行する方が正しいず考えおいたす。 原則ずしお、3りィンドりビュヌを陀いお、ワヌクフロヌはそれほど倉わりたせん。


git merge masterワヌクフロヌ


gitmergeセッションに切り替えたす


sessiowスむッチ


状態Bず©が入れ替わっおいるこずに泚意しおください。


git merge master


リポゞトリの䟋を少なくずも1回詊しお、䞊蚘のスキヌムに埓っお競合の解決を行うこずをお勧めしたす 。 個人的には、「圌らを受け入れる」たたは「あなたを受け入れる」を遞択するのはもう䞍思議ではありたせん。



Source: https://habr.com/ru/post/J323234/


All Articles