Reputation: 41749
The docs say that Git merge integrate file changes. I am not sure if it means it replaces the complete changed file or only changed portions of it.
Let me illustrate my concern. There are guys A and B working on the same project but on different branches.
Project--- Branch ---Master
---B's branch
The "b branch" is branched at 10th version of Master branch.
Master v1--2--...--10--11--
--v1--v2--
If we both changed the file MyFile.java
in v11/v2 and I want to merge it on Master v12, will the Git completely move the file from B's v2 or it will only merge added lines (let's say that there are no conflicts or changed methods from Master v10)?
For example, MyFile v11 looks like
1:
2: void someMethod() {}
3:
4: void anotherMethod() {}
5:
and B's MyFile v2 looks like
1:
2: void someMethod() {}
3:
4: void myCoolMethod() {}
5:
6: void anotherMethod() {}
If the MyFile was empty, but existed, when the branching occurred, will merge only squeeze method myCoolMethod
into the code or will copy the whole content of MyFile from branch B into the MyFile on branch A?
Upvotes: 1
Views: 223
Reputation: 66244
There is no copying of files involved. It's more subtle that that; roughly speaking, a merge involves comparing files (or rather, blobs) line by line.
In the simple merge example outlined in your question, Git would apply 3-way merging. Basically, this merging strategy uses, not just the two commits you want to merge, but also takes cues from their most recent common ancestor.
The information contained in the common ancestor allows Git to figure out how to merge things on its own in many situations where a more simplistic merging strategy, such as a 2-way merging (which doesn't use the common ancestor at all), would cause a merge conflict and ask you, the user, to intervene.
For instance, in the following situation,
if you told Git to merge commits B
and C
, the 3-way merging strategy, by looking at the contents of the file as recorded in the common ancestor (A
), would realize that all you did was add the baz
line in between the foo
and bar
lines in the version recorded in C
. Therefore, the merge would simply result in
However, in some cases, the common ancestor still doesn't provide enough information to allow Git to figure things out on its own. That is the case in the example described in your question.
Even though Git would attempt to perform a 3-way merge in your example, a merge conflict would still arise, because the blob holding the contents of MyFile.java
in the common ancestor is completely empty; therefore, it can't provide any cues as to where lines were added or deleted in descendants (B
and C
) of the common ancestor (A
).
Git, on its own, has no way of figuring out whether the version to keep is that which contains foo\nbar
or that which contains foo\nbaz\nbar
(\n
stands for a newline character, here). Therefore, Git will stop in its tracks (issue a merge conflict) and ask for your help.
Upvotes: 7
Reputation: 1234
Changes get merged only in changed lines. A's version can be replaced by B's version only if there's conflict and it is resolved manually by accepting entire file version.
One of A or B, will be the first who will appear in history as the first one who changed the file. Let's say Mr. A. His changes will be merged into previous version from master. Mr. B won't be able to merge without pulling A's changes after merge. So Mr. B's changes will be merged during pulling into what was the version after A has merged. In case that A and B edited same lines in the file, conflicts arise.
Upvotes: -1