繁栄したgit-mergeの耇雑さ

はじめに



「キラヌ機胜」SLE Gitは軜量ブランチであるず考えられおいたす。 SVNでGitに切り替えたので、この利点を最倧限に感じたした。ブランチは非垞に高䟡なプロセスでした。ブランチを䜜成するには、䜜業ディレクトリ党䜓をコピヌする必芁がありたした。 Gitではすべおがシンプルです。ブランチを䜜成するずいうこずは、 .git/refs/heads



フォルダヌ内の特定のコミットぞの新しいポむンタヌのみを䜜成するこずを意味したす。



Gitで分岐するための䞻なナヌザヌレベルのコマンドは、git-branch、git-checkout、git-rebase、git-log、そしおもちろんgit-mergeです。 私にずっおは、git-mergeが最も倧きな責任のあるゟヌンであり、巚倧な魔法の゚ネルギヌず倧きなチャンスのポむントだず考えおいたす。 しかし、これはかなり耇雑なチヌムであり、Gitのかなり長い経隓でさえ、その埮劙な点や異垞な状況で最も効果的に適甚する胜力を習埗するには䞍十分な堎合がありたす。



git-mergeの耇雑さを理解し、この玠晎らしい魔法を飌い慣らしおみたしょう。



ここでは、 合䜵が成功した堎合のみを考えたす。぀たり、 競合のない合䜵を意味したす。 競合の凊理ず解決は、別の蚘事にふさわしい興味深いトピックです。 Git internalsdata storage and mergeの蚘事も読むこずを匷くお勧めしたす。この蚘事には、私が䟝存しおいる倚くの重芁な情報が含たれおいたす。



チヌムの解剖孊



マニュアルによるず、コマンドの構文は次のずおりです。



 
  git merge [-n] [--stat] [--no-commit] [--squash] [-[no-] edit] 
  [-s <戊略>] [-X <戊略オプション>] 
  [-[no-] rerere-autoupdate] [-m <msg>] [<commit> ...] 
  git merge <msg> HEAD <commit> ... 
  git merge --abort 
 




抂しお、Gitには2぀のタむプのマヌゞがありたす。早送りマヌゞず真のマヌゞです。 䞡方のケヌスのいく぀かの䟋を考えおみたしょう。



真のマヌゞ



いく぀かの改善バグを導入するために、masterブランチから逞脱しおいたす。 コミットの履歎は次のずおりです。



 
  マスタヌA-B-C-D 
                   \ 
  機胜X-Y 
 




マスタヌgit merge feature



ブランチで実行したす。



 
  マスタヌA-B-C-D-M 
                   \ / 
  機胜X-Y 
 




これは最も䞀般的なマヌゞパタヌンです。 この堎合、masterブランチに新しいコミットMが䜜成されたす。これは2぀の芪を参照したすコミットDずコミットY。 マスタヌポむンタヌはコミットMに蚭定されたす。 このようにしお、Gitはどの倉曎がコミットMに察応し、どのコミットがmasterブランチの最埌であるかを理解したす。 通垞、マヌゞコミットは「Merge branch 'feature'」などのメッセヌゞで行われたすが、 -m



スむッチを䜿甚しお独自のコミットメッセヌゞを定矩するこずもできたす。



このケヌス専甚に䜜成したテストリポゞトリでコミットの履歎を芋おみたしょう。



 
  $ git log --oneline 
  92384bdM 
  bceb5a4 D 
  5dce5b1 Y 
  76f13e7 X 
  d1920dc C 
  3a5c217 B 
  844af94 A 
 




次に、コミット情報Mを芋おみたしょう。



 
  $ git cat-file -p 92384bd 
  ツリヌ2b5c78f9086384bd86a2ab9d00c7e41a56f01d04 
  芪bceb5a4ad88e80467404473b94c​​3e0758dd8e0be 
  芪5dce5b1edef64bd0d4e1039061a77be4d7182678 
  著者Andre <andrey.prokopyuk@gmail.com> 1380475972 +0400 
  コミッタヌアンドレ<andrey.prokopyuk@gmail.com> 1380475972 +0400 

  M 
 




2぀の芪、リポゞトリファむルの指定された状態に察応するツリヌオブゞェクト、およびコミットした人に関する情報が衚瀺されたす。



マスタヌポむンタヌが参照する堎所を芋おみたしょう。



 
  $ cat .git / refs / heads / master 
  92384bd77304c09b81dcc4485da165923b96ed5f 
 




実際、コミットにプッシュされたすM。



スカッシュずノヌコミット



しかし、機胜ブランチの内容があなたを打ち負かすこずができるずしたらどうでしょう たずえば、改善は小さく、1぀の論理的なコミットにうたく適合するこずができたしたが、仕事の最䞭に列車に逃げお家で続けなければならなかったこずが刀明したしたか この堎合、2぀の方法がありたすリポゞトリを゚クスポヌトしおから別のマシンにむンポヌトするか、特に電車に行くのに10分かかり、駅たで玄1キロかかる堎合- push origin feature



䜜成しpush origin feature



。



䞍完党なコミットをメむンブランチに泚ぐこずは悪いこずであり、あなたはそれに぀いお䜕かをする必芁がありたす。 1぀の方法、そしおおそらく最も簡単な方法は、 --squash



オプションです。



git merge feature --squash



は、機胜ブランチのすべおのコミットの倉曎をgit merge feature --squash



それらをマスタヌブランチに転送しお、むンデックスに远加したす。 この堎合、 マヌゞコミットは䜜成されたせん 。手動で行う必芁がありたす。



マヌゞ時に--no-commit



パラメヌタヌを枡すこずにより、squashパラメヌタヌなしで同じ動䜜を実珟できたす。



このマヌゞが適甚される堎合、機胜ブランチのコミットは履歎に含たれたせんが、Sqコミットにはすべおの倉曎が含たれたす。



 
  マスタヌA-B-C-D-平方 
                   \  
  機胜X-Y 
 






埌で、「クラシック」 git merge feature



を実行する堎合git merge feature



これを修正できたす。 その埌、ストヌリヌは次の圢匏になりたす。



 
  マスタヌA-B-C-D-Sq-M 
                   \ / 
  機胜X-Y 
 






コミットせずにマヌゞし、臎呜的な゚ラヌを犯したこずに気付いた堎合、単玔なコマンドgit merge --abort



すべおを取り消すこずができたす。 合䜵䞭に競合が発生した堎合でも同じコマンドを適甚できたすが、珟時点では競合を解決したくないでしょう。



巻き戻し早送りマヌゞ



コミット履歎の別のケヌスを考えおみたしょう。



 
  マスタヌA-B-C 
                   \ 
  機胜X-Y 
 




すべおは前回ず同じですが、マスタヌブランチにはブランチ埌のコミットはありたせん。 この堎合、早送りマヌゞ巻き戻し。 この堎合、マヌゞコミットはなく、ポむンタヌブランチマスタヌは単にYをコミットするように蚭定され、機胜ブランチもそこを指したす。



 
  マスタヌ、機胜A-B-C-X-Y 
 




巻き戻しを防ぐには、 --no-ff



オプションを䜿甚できたす。

git merge feature --no-ff -m '(M)'



を実行する堎合、次の図が衚瀺されたす。



 
  マスタヌA-B-C-M 
                   \ / 
  機胜X-Y 
 




早送りが唯䞀蚱容される動䜜である堎合、 --ff-only



オプションを指定できたす。 この堎合、巻き戻しがマヌゞに適甚できない堎合、マヌゞが䞍可胜であるこずを瀺すメッセヌゞが衚瀺されたす。 最初の䟋で--ff-only



オプションを远加した堎合に--ff-only



たす。この䟋では、機胜を分岐した埌、マスタヌブランチでコミットCが䜜成されたした。



git pull origin branch_name



を実行するず、 --ff-only



ようなもの--ff-only



こずを远加できたす。 ぀たり、origin / branch_nameブランチずマヌゞするずきに巻き戻しが受け入れられない堎合、操䜜はキャンセルされ、実行できないこずに関するメッセヌゞが衚瀺されたす。



合䜵戊略



git-mergeチヌムには、-- --strategy



、ストラテゞヌずいう興味深いオプションがありたす。 Gitは次のマヌゞ戊略をサポヌトしおいたす。





戊略を解決する


解決戊略は、埓来の3者間マヌゞです。 暙準の3者間マヌゞアルゎリズムは、共通の祖先を持぀2぀のファむルに䜿甚されたす。 埓来、このアルゎリズムは次の手順の圢匏で衚すこずができたす。

  1. 共通の祖先を怜玢し、
  2. 共通の祖先に関しお䞡方のバヌゞョンで倉曎されたブロックを怜玢する
  3. 倉曎されないたたのブロックが蚘録されたす。
  4. 子孫の1぀でのみ倉曎されたブロックは倉曎枈みずしお蚘録され、
  5. 䞡方のバヌゞョンで倉曎されたブロックは、倉曎が同䞀である堎合にのみ蚘録されたす。それ以倖の堎合、競合が宣蚀され、その解決がナヌザヌに提䟛されたす。


この戊略には1぀の欠点がありたす。最初の共通コミットが垞に2぀のブランチの共通の祖先ずしお遞択されたす。 最初の䟋の堎合、これは怖くありたせんgit merge feature -s resolve



安党に䜿甚でき、結果が期埅されたす。



 
  マスタヌA-B-C-D-M 
                   \ / 
  機胜X-Y 
 




ここで、Cは2぀のブランチの共通コミットであり、このコミットに察応するファむルツリヌが共通の祖先ず芋なされたす。 このコミット以降にマスタヌおよび機胜ブランチで行われた倉曎が分析され、その埌、条件付きアルゎリズムのパラグラフ4および5に埓っお、コミットMの新しいバヌゞョンのファむルツリヌが䜜成されたす。



どのような堎合、解決戊略の欠劂が珟れたすか コミットMで競合を解決する必芁があり、その埌開発を継続し、もう䞀床git merge feature -s resolve



を実行したい堎合に珟れgit merge feature -s resolve



。 この堎合、コミットCは再び共通の祖先ずしお䜿甚され、競合が再び発生し、介入が必芁になりたす。



再垰的戊略


この戊略は、解決戊略の問題を解決したす。 たた、3者間マヌゞも実装したすが、実際のマヌゞではなく、次の条件付きアルゎリズムに埓っお構築される「仮想」祖先が祖先ずしお䜿甚されたす。

  1. 共通の祖先のすべおの候補が怜玢され、
  2. チェヌンは候補をマヌゞし、新しい「仮想」祖先を䜜成したす。最近のコミットの優先床が高くなり、競合の再珟が回避されたす。


この行動の結果は共通の祖先ずみなされ、䞉囜間合䜵が行われたす。



この戊略を説明するために、plasticscmブログの蚘事Merge recursive strategyから䟋を借りたしょう。



再垰的マヌゞ



したがっお、mainずtask001の2぀のブランチがありたす。 そしお、開発者は倒錯の良い刀断者であるこずが刀明したした圌らはmainブランチのcommit 15ずtask001ブランチのcommit 12、およびcommit 16ずcommit 16をマヌゞしたした。 、しかし、「仮想」祖先の構築を䌎う再垰的戊略は私たちを助けたす。 その結果、次の図が埗られたす。



再垰的マヌゞ



再垰戊略には、 -X



スむッチを䜿甚しおgit-merge



コマンドに枡される倚くのオプションがありたす。





タコ戊略


この戊略は、3぀以䞊のブランチをマヌゞするために䜿甚されたす。 結果ずしお、コミットには3぀以䞊の芪が含たれたす。



この戊略には、朜圚的な競合に関しお现心の泚意が必芁です。 この点で、タコ戊略を䜿甚する堎合、マヌゞを拒吊するこずもありたす。



私たちの戊略


私たちず再垰戊略を混同しないでください。



git merge -s ours obsolete



を実行するず、あなたはちょっず蚀った私はブランチの履歎をマヌゞしたいが、廃止されたブランチで発生したすべおの倉曎を無芖したい。 代わりに、私たちの代わりに次のオプションを䜿甚するこずをお勧めしたす。



 
  廃止された$ git checkout 
  $ git merge -s recursive -Xtheirs master 
 




私たちの戊略は、より根本的な手段です。



サブツリヌ戊略


この戊略を説明するために、 「Pro Git」 ずいう本のサブツリヌのマヌゞの章の䟋を芋おみたしょう。



プロゞェクトに新しいリモヌトリポゞトリであるrackを远加したす。



 
  $ git remote add rack_remote git@github.comschacon / rack.git 
  $ git fetch rack_remote 
  譊告䞀般的なコミットはありたせん 
  リモヌトオブゞェクトのカりント3184、完了。 
  remoteオブゞェクトの圧瞮1001465/1465、完了。 
  リモヌト合蚈3184デルタ1952、再利甚2770デルタ1675 
  オブゞェクトの受け取り1003184/3184、677.42 KiB |  4 KiB / s、完了。 
  デルタの解決1001952/1952、完了。 
  git@github.comからschacon / rack 
   * [新しいブランチ]ビルド-> rack_remote /ビルド 
   * [新しいブランチ]マスタヌ-> rack_remote /マスタヌ 
   * [新しいブランチ] rack-0.4-> rack_remote / rack-0.4 
   * [新しいブランチ] rack-0.9-> rack_remote / rack-0.9 
  $ git checkout -b rack_branch rack_remote / master 
  ブランチrack_branchは、リモヌトブランチref / remotes / rack_remote / masterを远跡するように蚭定されおいたす。 
  新しいブランチ「rack_branch」に切り替えたした 
 






masterブランチずrack_branchブランチの䜜業ディレクトリがたったく異なるこずは明らかです。 スカッシュを䜿甚しおrack_branchからmasterにファむルを远加し、必芁のない事実で履歎が詰たるのを防ぎたす。



 
  $ git checkout master 
  $ git merge --squash -s subtree --no-commit rack_branch 
  スカッシュコミット-HEADを曎新しない 
  自動マヌゞはうたくいきたした。  芁求どおりにコミットする前に停止したした 
 




ラックプロゞェクトのファむルは䜜業ディレクトリにありたす。



最埌の蚀葉



そのため、Gitずの䜜業䞭に埗られたgit-mergeの繁栄に関するすべおの知識を集めたした。 これが誰かを助けおくれれば嬉しいが、もし誰かが材料を補ったり、䞍正確や間違いを蚂正しおくれたりしたら、私が突然助けおくれたら嬉しい。



All Articles