sandalone
sandalone

Reputation: 41749

Does Git merge complete files or changed portions of it?

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

Answers (2)

jub0bs
jub0bs

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.

Example of a conflict-free 3-way merge

For instance, in the following situation,

enter image description here

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

enter image description here

Example of a conflict during a 3-way merge

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.

enter image description here

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.

enter image description here

Upvotes: 7

lef
lef

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

Related Questions