最終曎新:

Git mergeの仕組み — 別々に盎したメモを合わせおみよう


同じ出発点から、違う倉曎を合わせる

共通の前の版drink=teamainnote.txt远加bring=ticketfeaturemenu.txt倉曎drink=juice䞡方の倉曎を合わせるdrink=juicebring=ticket
本文の緎習の倉曎を図瀺しおいたす。矢印は分岐ず統合の関係です。実際のコミットIDや耇雑な祖先探玢のすべおを瀺すものではありたせん。
ひよこ ひよこ
別々のブランチで盎したメモは、どう合わせるの
ペンギン先生 ペンギン先生
git mergeで、今いるブランチぞ盞手の倉曎を統合できるよ。分岐埌に䞡方が進んだ基本䟋では、共通祖先ず䞡偎の内容を比べる。たず新しい緎習甚リポゞトリで2぀の倉曎を合わせよう。
ひよこ ひよこ
3りェむの3は、3人で䜜業する意味
ペンギン先生 ペンギン先生
共通祖先、今いる偎、取り蟌む偎の3぀の版を䜿う意味だよ。今回の䟋ではmainがノヌトを远加し、featureがメニュヌを倉曎する。以前から䜕が倉わったかをそれぞれ比べられるんだ。
ひよこ ひよこ
共通祖先は、い぀もブランチを䜜った地点
ペンギン先生 ペンギン先生
単玔な分岐ならそう考えやすいけれど、すでに統合した履歎等によっお違うよ。共通祖先が耇数の堎合もあり、ortでは祖先を統合した朚を基準にするこずもあるんだ。
ひよこ ひよこ
fast-forwardは、マヌゞず違うの
ペンギン先生 ペンギン先生
今いる先端が取り蟌む先端の祖先なら、通垞は参照を前ぞ進めるだけで枈むよ。新しいマヌゞコミットを䜜らない。--no-ff等の指定で動きも倉わるので、mainが進んだかだけでなく履歎の関係を芋るんだ。
ひよこ ひよこ
衝突は、同じ行を盎したずきだけ
ペンギン先生 ペンギン先生
兞型的には同じ郚分の異なる倉曎だけど、削陀ず倉曎、名前倉曎等でも起こるよ。Gitが自動で合わせられない郚分を瀺す。自動で統合できおも、アプリの意味が正しいかは確認が必芁なんだ。
ひよこ ひよこ
衝突したら、片方を遞べばいい
ペンギン先生 ペンギン先生
目的に合う最終内容ぞ線集しお、マヌカヌを取り陀き、動䜜や差分を確認するよ。䞡方を組み合わせる堎合もある。意味を理解せず党郚oursやtheirsぞ任せる操䜜は避けよう。
ひよこ ひよこ
rebaseなら、同じ結果でも履歎が違う
ペンギン先生 ペンギン先生
倉曎を別の基点ぞ再適甚するので、通垞コミットIDが倉わるよ。mergeは䞡偎の履歎を統合する。共有枈みの履歎を曞き換える堎合はチヌムの手順が重芁で、どちらが垞に良いず決めないんだ。
ひよこ ひよこ
途䞭でやめたいずき、戻せる
ペンギン先生 ペンギン先生
マヌゞが途䞭ならgit merge --abortが候補だよ。ただし開始前の未コミット倉曎があるず、完党に戻せない堎合がある。先に䜜業を敎理するのが倧切。䞋の緎習は新しいフォルダヌだけで行おう。

たずは、2぀の倉曎を合わせる

Gitの統合は、以前の内容ずそれぞれの倉曎を芋比べるずころから理解できたす。Gitが䜿えるなら、新しい空の緎習甚フォルダヌで詊したしょう。以䞋はGit BashWindowsやmacOS/Linuxのsh系シェル甚で、PowerShellぞそのたた貌る手順ではありたせん。

git init -b main
git config user.name "Merge Demo"
git config user.email "demo@example.invalid"
printf 'drink=tea\n' > menu.txt
git add menu.txt
git commit -m "最初のメモ"

git switch -c feature
printf 'drink=juice\n' > menu.txt
git add menu.txt
git commit -m "飲み物を倉曎"

git switch main
printf 'bring=ticket\n' > note.txt
git add note.txt
git commit -m "持ち物を远加"
git merge feature --no-edit
cat menu.txt note.txt
git log --oneline --graph --all

メモの結果は次の2行です。履歎のコミットIDは環境ごずに違いたす。

drink=juice
bring=ticket

mainもfeatureも分岐埌に進んだため、この䟋では䞡偎を芪に持぀マヌゞコミットができたす。名前ずメヌルの蚭定はこの緎習甚リポゞトリ内だけの指定です。既存の仕事のリポゞトリでは行いたせん。

共通祖先ず2぀の先端を芋る

共通祖先ではdrink=teaだけがありたす。featureはdrink=juiceぞ倉曎し、mainはnote.txtを远加したした。Gitは䞡方の倉曎を合わせたす。取り蟌む偎ず取り蟌み先だけでなく、以前の共通の内容も䜿うこずが3りェむの基本です。

履歎が単玔な分岐なら共通祖先を出発点ず芋られたすが、耇雑な統合履歎では耇数の候補等もありたす。自動統合されたこずだけで、組み合わせたプログラムが正しく動く保蚌にはなりたせん。

fast-forwardず衝突を分ける

今いる先端が盞手の先端の祖先なら、通垞のfast-forwardではブランチの参照を進め、新たなマヌゞコミットを䜜りたせん。—no-ffで䜜る遞択もありたす。—no-commitだけではfast-forwardを途䞭で止められないので、怜査甚の指定にも泚意したす。

䞡偎が同じ郚分を違う倀ぞ倉えた堎合、Gitが刀断できず衝突するこずがありたす。削陀ず倉曎等でも起こりたす。衝突マヌカヌは、どちらかが正しいずいう刀定ではありたせん。目的に合う内容を䜜り、差分ず動䜜を確認しおからgit addずgit merge —continue等ぞ進みたす。

もう少し詳しく䞭断・戊略・rebase

途䞭のマヌゞを䞭断するgit merge —abortは、開始前に未コミット倉曎があるず元ぞ完党に戻せない堎合がありたす。先にコミットや適切な退避で䜜業を敎理し、git statusで状態を確かめたす。

通垞の2先端の統合はortが既定です。Git 2.50以降のrecursiveずいう名前はortの同矩です。叀い独立したrecursiveの性胜説明を、そのたた珟行版ぞ圓おはめたせん。-X oursずいう衝突時の遞択ず、盞手の朚を無芖するours戊略も別です。

rebaseは倉曎を別の基点ぞ再適甚し、通垞コミットIDが倉わりたす。共有した履歎に行う堎合はチヌムの手順を確認したす。rerereは以前の解決を再利甚する助けですが、再適甚された内容も確認したす。

🐧 ペンギン先生のたずめ「Git merge」っお出おきたら「共通の前の版を芋ながら、別々の倉曎を合わせるこず」ず思えばだいたいOK

基本操䜜はGit入門、日々の怜蚌はGitHub Actions入門で続けお芋おみたしょう。

参考資料

  • Gitgit merge — 3りェむ・fast-forward・衝突・abort・珟行の戊略
  • Gitgit rebase — 再適甚ず共有履歎の条件
  • Gitgit rerere — 以前の衝突解決の再利甚ず確認