Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git merge not merging all files

Tags:

git

I am having a real tough time using git.

I have a branch A and a branch B. I want to merge branch A into branch B. I am currently on branch B and I used the following command:

git merge A.

Now when I run git status, I see that I am ahead by two commits and when I look at the files that were altered during the git merge I noticed only two files being altered. However, there are at least a dozen files that I know was changed in branch A that didn't get picked up during the git merge.

Why is git merge only merging those two files when there are clearly other files that need to get merged?

like image 289
Robin Avatar asked Feb 19 '18 17:02

Robin


People also ask

Can't merge branch already up to date?

The message “Already up-to-date” means that all the changes from the branch you're trying to merge have already been merged to the branch you're currently on. More specifically it means that the branch you're trying to merge is a parent of your current branch.

What is an alternative to merging in git?

While merging is definitely the easiest and most common way to integrate changes, it's not the only one: "Rebase" is an alternative means of integration.


1 Answers

Comparing the two branch tip commits is the wrong thing to do, because that's not what git merge does.

To see what files each of you changed, you must first find the commit that branches A and B most recently shared:

             o--o   <-- branch-B
            /
...--o--o--*
            \
             o--o--o   <-- branch-A

(where each round o represents a commit, in the chain of commits people have added over time).

The common commit, which I marked * here, is what Git calls the merge base of the two branches. Git will find this commit automatically, on its own, when you sit at the tip of one of the two branches (such as B) and run git merge A.

Git will then compare, not B vs A, nor A vs B, but rather:

git diff hash-of-* hash-of-tip-of-B    # what did *we* change?

and:

git diff hash-of-* hash-of-tip-of-A    # what did *they* change?

The goal of git merge is to locate and extract commit *, apply all the changes from both branches, and commit that as a new merge commit on the current branch (B), with two parent commits, to make it a merge commit so that Git knows what to use as the merge base the next time too.

If you want to see the hash ID of commit *, you can run git merge-base:

git merge-base --all A B

You can then run git diff, giving it that hash ID for the merge base, and the name A to select the tip of branch A to see what they changed. You can run a second, separate, git diff, giving it that same hash ID for the merge base, and the name B to select the tip of branch B to see what you changed (you might remember what you changed, but it's a good idea to see if Git agrees with your memory, because Git is going to use what it finds, not what you remember!).

There is a short-hand that will run git merge-base for you, that works only with git diff:

git diff A...B   # note the three dots

will compare the merge base of A and B against the commit identified by B, to find what you changed. A subsequent:

git diff B...A   # note the three dots again

will compare the merge base of B and A1 against the commit identified by A, to find what they changed.

(You can add options like --name-status or --name-only to the git diff to affect how git diff shows the changes it calculates / finds. Note that whenever there are renames involved, the merge uses the equivalent of git diff -M50 to find the renames. Modern Git, since 2.9, enables rename detection in git diff as well by default.)


1"Merge base" is a symmetric graph operation, so "merge base of A and B" is by definition equal to "merge base of B and A".

like image 74
torek Avatar answered Oct 23 '22 20:10

torek