Skip to content

Instantly share code, notes, and snippets.

@x-yuri

x-yuri/a.md Secret

Last active July 2, 2022 13:32
Show Gist options
  • Save x-yuri/57d08f6afb10a89856d6e6a62abe30d4 to your computer and use it in GitHub Desktop.
Save x-yuri/57d08f6afb10a89856d6e6a62abe30d4 to your computer and use it in GitHub Desktop.

A three-way merge introduces that "little more" information than the plain "series of instructions":

The way I understand it, if git has enough information, it can perform a 3-way merge. It's not like a 3-way merge introduces anything.

it tells you what the original version of the file was as well. If your repository has the original version, your Git software, working in your repository, can compare what you did to a file, to what the patch says to do to the file.

Technically, this is probably correct, but it seemingly implies that git uses information in the patch to find the commit (let's say commit A) that matches the original version of the file (which is the version of the file before the patch was applied). And now it has 2 patches: 1) from A to HEAD, 2) the patch you supply. Having these 2 patches it is able to perform a 3-way merge, that can be applied e.g. in cases where a normal patch wouldn't.

For example, let's say you have a repository with 2 unrelated branches:

(branch a) A
(branch b) B---C

At every revision you have only file f:

A:

11
2
3

B:

1
2
3

C:

1
2
33

You use format-patch to create a patch from B to C (imagine a proper diff here with an index line):

 1
 2
-3
+33

and want to apply it to A. patch or git am would fail because in f you have 11 and in patch 1. But git am -3 will succeed.

A script that reproduces the case can be found here.

Now, what is the original version you're referring to? Undoubtedly, that's the version in B. But you probably suggest that using the blob hash in the patch git finds the revision in branch a where f also contains the original version. But there's no such commit in a.

Also, it's not clear what makes git decide that it doesn't matter that the first line in A and in the diff differ (why the patch doesn't apply in the traditional way, but applies with a 3-way merge). Because there's no original version in branch a.

--

A patch is little more (see below) than a series of instructions: "add this here", "remove that there", "change this third thing to a fourth".

"A git patch is...", to make it more clear, then? Because it has an index line.

That's why Git tells you:

The copy of the patch that failed is found in: c:/.../project2/.git/rebase-apply/patch

The reason git can't apply the patch is not because a patch is a little more. The reasons are: 1) the original version is not in the repository, 2) the current version contradicts the patch and the user doesn't try to do a 3-way merge (doesn't pass -3).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment