Marcel Marino
Marcel Marino

Reputation: 1002

GIT Merging Existing File as "New"

I've got two branches, master and DevMaster.

Let's say we have a file in master with a reference of: src/AppFiles/Submissions/CompleteSubmission.java

That same file exists in DevMaster.

When doing a merge from master into DevMaster, it's detecting the file above as a new file, even though it exists identically to the file in master. This makes no sense to me or my team at all.

Edit: Also, I do the merge on that branch, and STILL everything is being detected as new, even after I just merged it.

Upvotes: 0

Views: 387

Answers (3)

torek
torek

Reputation: 488519

All merges work from a merge base. The merge base is the "best" common ancestor commit of the two1 commits being merged. The easiest way to understand this is, I think, visually. Draw out the two tip commits, along with the branch names that identify them (or use git log --decorate --oneline --graph branch1 branch2 to get Git to do this vertically):

     J  <-- branch1



     L  <-- branch2

Follow J (which stands in for some big ugly commit hash) back to its parent I, and do the same with L to its parent K:

  I--J  <-- branch1



  K--L  <-- branch2

Repeat until you find a commit that's on both branches:

  I--J  <-- branch1
 /
H
 \
  K--L  <-- branch2

The commit you have found is the merge base. (Not all merge bases will show up as neatly and simply as this! Most graphs are horribly tangled.)

You can have Git identify the merge base for you:

git merge-base --all branch1 branch2

will tell you what the merge base is, as long as you run it before running git merge. (Afterward, one of the two branch names points to the new merge commit and the merge base is just the other branch/commit.) Use the raw commit hashes after the merge, if you want to see what the merge base was.

Once you have the merge base itself, the merge process becomes comprehensible. Git runs two git diff commands: one compares the merge base commit to the tip of branch1, and the other compares the (same) merge base commit to the tip of branch2. These differences guide Git in terms of combining each set of changes to each file.

If the merge base commit does not have some file that exists in both branch tips, then that file has an add/add conflict: it's completely new in both branches and Git has no idea how to combine the two files, unless they exactly match.

The result of a default automatic merge (one with no options and no stopping to edit the result) is completely determined by the three input commits. You cannot just compare the two branch-tip commits to each other! You must compare each branch-tip commit to the (common) merge base.


1In the case of an octopus merge—a merge of more than two commits—the merge base is computed a bit differently.

Upvotes: 1

Marcel Marino
Marcel Marino

Reputation: 1002

So there was some funny business going on with the remote version of the branch. I did the merge locally through suggestions from @Angelo Mendes and @Marek R (why don't tags work on this page?) and the merge on my local only detected a single file change, which is what we expected. To fix this, I pulled all the files from my remote branch into my local, deleted the remote, and then pushed the local to the remote. Now new PR's don't readd all of the already existing files.

Upvotes: 0

sarang
sarang

Reputation: 114

@marcel first check whether the file is pushed to remote. Verify it on bitbucket browser client.

Upvotes: -1

Related Questions