LoginSignup
1
0

More than 5 years have passed since last update.

【Git】計画なしに他のブランチをマージし、削除/移動したら起こりえる問題

Posted at

他の人のブランチで作成されたものを自分のブランチにマージしてから、マージされたものを削除や移動しmasterにマージした後、他の人のブランチをmasterにマージする場合、どうなるのか検証してみました。

検証用GitHubリポジトリ

予測

他の人のブランチにはまだ削除/移動前の姿があるから、そのままmasterにマージされ、
結果的には移動されたものはコピーした扱いになる。(結論から言いますと、これは不正解です。)

検証

検証用のブランチですること

  • dev/newfile
    新しいディレクトリとその配下にファイルを作成する。

  • dev/movefile
    dev/newfileをマージし、マージされたものを一部は削除、残りはディレクトリごと移動する。

検証詳細

準備

  1. masterからdev/newfileブランチを切る
    1. ディレクトリnew作成
    2. newの配下にいくつかのファイルを作成
    3. コミット
  2. masterからdev/movefileブランチを切る
    1. dev/newfileブランチをマージする
    2. マージされたnewディレクトリ配下のファイル一部を削除
    3. newディレクトリ名をmovetoに変更
    4. コミット
  3. masterdev/movefileをマージ

ここまでのGit履歴グラフ
git_graph.png

結果

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 {自分のブランチ}

もっと簡単でスマートな方法がありましたら教えてください!🙇‍♂️

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0