はじめに
ふと、コミットの時系列の順番とバックマージした結果が自分の想定と違う動きをしたので、改めて個人的に試してみた。
参考までに残します。
実験1
手順
1.feature/testAで、priority-test.txtが存在しない状態
2.feature/testAから、feature/testA-addを作成
3.feature/testA-addで、priority-test.txtを作成
4.feature/testAで、priority-test.txtを作成
5.feature/testAで、priority-test.txtを削除
6.feature/testA-add に feature/testAをバックマージ
コマンド
git switch develop
git branch feature/testA
git switch feature/testA
ls priority-test.txt
git branch feature/testA-add
git switch feature/testA-add
echo 'priority-test' > priority-test.txt
git add priority-test.txt
git commit -m 'testA-add add priority-test'
git switch feature/testA
echo 'priority-test' > priority-test.txt
git add priority-test.txt
git commit -m 'testA add priority-test'
rm -rf ./priority-test.txt
git add priority-test.txt
git commit -m 'testA delete priority-test'
ls ./priority-test.txt
git switch feature/testA-add
git merge feature/testA
ls ./priority-test.txt
結果
priority-test.txtが残る。
git log
$ git log --graph --oneline
* b5248d9 (HEAD -> feature/testA-add) Merge branch 'feature/testA' into feature/testA-add
|\
| * 8b02ae2 (feature/testA) testA delete priority-test
| * 1ae7174 testA add priority-test
* | 1339596 testA-add add priority-test
|/
* a705d0e (origin/develop, develop) Merge pull request #10 from tarosuke777/feature/test1
疑問に思ったこと
時系列的には、priority-test.txt の削除が最後なので残らない OR コンフリクトするのかな?って気がしたが、バックマージしてみたらコンフリクトもせずに残った。
GEMINIに聞いてみた。
Gitのデフォルトのmerge戦略では、あるブランチで作成されたファイルが、別のブランチで削除された場合、マージ後の状態はそのファイルが存在する方(この場合はfeature/testA-add)の状態が優先される傾向があります。これは、意図しないファイルの削除を防ぐための安全な設計と言えます。
ほー、なるほど、そうなんだ・?
じゃあ、同一ファイル内だとが気になってきた。
実験2
1.developブランチで以下のようファイルを作る
$ cat priority-test2.txt
test1
test3
2.feature/testA2で、priority-test2.txtの中身が以下の状態
cat priority-test2.txt
test1
test3
3.feature/testA2から、feature/testA2-addを作成
3.feature/testA2-addで、priority-test2.txtの2行目に「test2」を追加
cat priority-test2.txt
test1
test2
test3
4.feature/testA2で、priority-test2.txtの2行目に「test2」を追加
cat priority-test2.txt
test1
test2
test3
5.feature/testA2で、priority-test2.txtの2行目の「test2」を削除
cat priority-test2.txt
test1
test3
6.feature/testA2-add に feature/testA2をバックマージ
コマンド
git switch develop
git branch feature/testA2
git switch feature/testA2
cat priority-test2.txt
git branch feature/testA2-add
git switch feature/testA2-add
vi priority-test2.txt
※ 2行目に「test2」を追加
git add priority-test2.txt
git commit -m 'testA2-add add line priority-test2'
git switch feature/testA2
vi priority-test2.txt
※ 2行目に「test2」を追加
git add priority-test2.txt
git commit -m 'testA2-add add line priority-test2'
vi priority-test2.txt
※ 2行目の「test2」を削除
git add priority-test2.txt
git commit -m 'testA2-add delete line priority-test2'
cat ./priority-test2.txt
git switch feature/testA2-add
git merge feature/testA2
cat ./priority-test2.txt
結果
2行目のtest2は残る。
git log
$ git log --graph --oneline
* a4475ba (HEAD -> feature/testA2-add) Merge branch 'feature/testA2' into feature/testA2-add
|\
| * c1aa6ef (feature/testA2) testA2-add delete line priority-test2
| * f45e867 testA2-add add line priority-test2
* | 7d35e61 testA2-add add line priority-test2
|/
* 698f5de (origin/develop, develop) init priority test
疑問に思ったこと
時系列的には、priority-test2.txt の2行目の削除が最後なので残らない OR コンフリクトするのかな?って気がしたが、バックマージしてみたらコンフリクトもせずに残った。
GEMINIに聞いてみた
Gitは、feature/testA2-addの「test2を追加する」という意図と、feature/testA2の「最終的にtest2を削除する」という意図を完全に理解することはできません。そのため、それぞれのブランチの最終的な状態を考慮し、結果としてfeature/testA2-addの変更(test2が存在する)を優先するような形でマージが行われたと考えられます。
~ 中略 ~
この例からも、Gitのマージ処理は単なる時系列的な操作の反映ではなく、各ブランチの変更内容を統合しようとする複雑な処理であることが理解できます。
なるほど、なるほど。単純な時系列な操作をもとにマージではないということかな?
個人的結論
単純な時系列な操作をもとにマージではないということかな?