Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git ignores deleted file on merge

Tags:

git

I have two repositories. From time to time, I want to merge the content of other into main. However the merge ignores deleted files. Let me explain it through an example:

mkdir -p test/main test/other

cd test/other/
git init
touch one two three
git add .
git commit -m "Add one, two and three."

cd ../main/
git init
touch four
git add .
git commit -m "Add four."

Add other to main as remote.

git remote add other ../other/
git fetch other

Merge its content.

git merge --squash other/master
git commit -m "Merge other."

It adds the files correctly. Now, remove a file in other.

cd ../other/
git rm two
git commit -m "Remove two."

Merge changes into main.

cd ../main/
git fetch other
git merge --squash other/master

After the merge git status says:

# On branch master
nothing to commit (working directory clean)

I would expect the merge to delete two, as it was deleted in other. What am I doing wrong?

like image 623
Gergo Erdosi Avatar asked Jan 15 '13 17:01

Gergo Erdosi


People also ask

Does git ignore delete files?

If you want to ignore a file that you've committed in the past, you'll need to delete the file from your repository and then add a .gitignore rule for it. Using the --cached option with git rm means that the file will be deleted from your repository, but will remain in your working directory as an ignored file.

Does git merge delete files?

If a file is modified in one branch and moved in another branch, Git has no way to propagate the changes from the original file to the moved copy of the file. If a file is deleted in one branch and isn't modified in the other, the file is deleted during the merge.


1 Answers

The issue here is your use of squash commits.

When you do a merge --squash, you abandon all of the history of a branch. You haven't really "merged the branch" - you've just applied a condensed representation of its history. So if you do a later merge --squash, git will reapply all the commits in the branch's history (since the two branches have no common ancestor).

When you perform the first merge --squash, you create a commit on main which contains "Create one, two, and three". So the history of main is first "create four", then "create one, two, and three".

When you do the second merge --squash, you add a commit which consists of (in effect) "Create one, two, and three" plus "Remove two". The net of those two commits together (squashed!) is "Create one and three". So git auto-merges the "Create one and three" commit with your current repo state - leaving you with four files present. The content merge succeeds automatically because the files "one" and "three" are identical on both sides.

You should use "real" merges or cherry-picking instead of squashing if you want to keep a repo up-to-date with a remote. A merge --squash is not the same thing as "play through all the new commits in a remote repository and integrate them here".

like image 116
Borealid Avatar answered Sep 20 '22 14:09

Borealid