他の人のブランチで作成されたものを自分のブランチにマージしてから、マージされたものを削除や移動しmaster
にマージした後、他の人のブランチをmaster
にマージする場合、どうなるのか検証してみました。
予測
他の人のブランチにはまだ削除/移動前の姿があるから、そのままmaster
にマージされ、
結果的には移動されたものはコピーした扱いになる。(結論から言いますと、これは不正解です。)
検証
検証用のブランチですること
-
dev/newfile
新しいディレクトリとその配下にファイルを作成する。 -
dev/movefile
dev/newfileをマージし、マージされたものを一部は削除、残りはディレクトリごと移動する。
検証詳細
準備
-
master
からdev/newfile
ブランチを切る
2. ディレクトリnew
作成
3.new
の配下にいくつかのファイルを作成
4. コミット -
master
からdev/movefile
ブランチを切る
6.dev/newfile
ブランチをマージする
7. マージされたnew
ディレクトリ配下のファイル一部を削除
8.new
ディレクトリ名をmoveto
に変更
9. コミット -
master
にdev/movefile
をマージ
結果
dev/newfile
ブランチをmaster
へのマージリクエストを作成する。
あれ、差分がない!?
じゃあ、なにか修正してマージしたら差分がでるのでは?と考え、確認してみました。
dev/newfile
の一部を修正した後、master
へマージする。
コンフリクトが起きました。
CONFLICT (modify/delete): new/new_c.txt deleted in master and modified in HEAD. Version HEAD of new/new_c.txt left in tree.
CONFLICT (modify/delete): new/new_b.txt deleted in master and modified in HEAD. Version HEAD of new/new_b.txt left in tree.
Automatic merge failed; fix conflicts and then commit the result.
$ git status
On branch dev/newfile
Your branch is up to date with 'origin/dev/newfile'.
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Changes to be committed:
new file: moveto/move_to.txt
renamed: new/new_a.txt -> moveto/new/new_a.txt
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
deleted by them: new/new_b.txt
deleted by them: new/new_c.txt
ローカルで手動マージするとdev/newfile
で最後の修正分は
dev/movefile
で削除されたファイル : 新しいファイルとして作成されます。
dev/movefile
で移動されたファイル : 移動されたまま修正分が適応されます。
Changes to be committed:
modified: moveto/new/new_a.txt
new file: new/new_b.txt
new file: new/new_c.txt
まとめ
dev/newfile
にはファイルが残っていてもdev/moveto
ブランチでのコミットが最新なので、マージしようとしてもmaster
にマージ済みより過去分になるので、差分がでず削除/移動済み扱いになりました。
移動されたものに対してはdev/newfile
で移動前のファイルを修正しても、移動後のファイルにマージはされます。
予測での「結果的には移動されたものはコピーした扱いになる」は完全に間違えたものでした。
他のブランチのファイルやディレクトリを別名でコピーして自分のブランチで使いたい場合、こういう問題にならないために下記のようにするといいかなと思います。
# ファイルが1つの場合
git show {コピー元ブランチ名}:{パス/ファイル名} > {コピー先パス/ファイル名}
# ディレクトリごとコピー
git checkout {コピー元ブランチ名}
cp {コピー元Dir} {コピー先Dir}
git checkout {自分のブランチ}
もっと簡単でスマートな方法がありましたら教えてください!🙇♂️