From: Chris Torek Date: Sat, 08 Nov 2025 10:57:47 GMT Subject: Re: [Bug report] git cherry-pick silently ignores error whereas git apply fails for hunk apply Message-ID: In-Reply-To: On Fri, Nov 7, 2025 at 12:35 AM Bhavik Bavishi wrote: ["git apply" fails, "git apply --3way" and "git cherry-pick" succeed, and:] > I've compare the file content of `mango/utils/apple_utils.cc` for `git > apply --3way` and `git cherry-pick` is same This is all entirely normal. You're seeing the difference between a "patch" and an actual "three way merge". The cherry-pick command does a three-way merge using the complete information available to it. The apply command applies a simple patch, or, with "--3way", searches the patch for auxiliary information that may or may not provide the extra detail needed for doing a three-way merge. To understand this, we need to illustrate the difference between these two ideas. Let's start with patches. A "patch" says "we expect the file looks something like this, and we would like to make certain changes in these areas". If the file *does* look "like this" in the indicated areas, it's easy to apply the patch: --- lines 15 through 19 of file.txt used to be like this +++ lines 15 through 20 of file.txt should now look like this we expect the file to look like this + and we should add a line and then the text goes on as before If file `file.txt` has the desired lines at lines 15--19, and we add the indicated text in the middle, we've "patched" the file to match the new desired result. But what if the file, at lines 15 through 19, reads: we expect the file to look like this and we should add a line and then the text Well, it sure looks like that patch was already applied. We can *guess* that it was in fact already applied, or we can search for lines before or after lines 15 through 19 that read the expected way. Patches can add, remove, or (depending on the kind of patch) change lines (or characters within lines, or whatever: the more general form is "symbol by symbol, add/subtract/replace"). A *merge*, by contrast, takes two separate sets of patches: * First, there's a "common base version": a version both you and they, whoever they were, had that's absolutely 100%] identical in all respects. * Second, there's an "ours" version. By comparing the "base" version to the "ours" version, we find out what *we* changed. * Last, there's a "theirs" version. By comparing the "base" version to the "theirs" version, we find out what *they* changed. This time, if we already have the change at lines 15--19 / 15--20, we'll see that they and we have the *same* change. We can silenly discard their duplicate change! We don't have to guess whether we have their change, or whether the lines moved around somewhat in the file. This same method handles removals (and if they're in the difference format, "changes", which are just "remove and add" combined into one block). The way "git apply --3way" works is that it looks for a text line in the patch of the form "index .." before the diff listing (which has only add and remove, in Git's case). The first hash ID in this pair of hash IDs is the Git-specific unique identifier for the original version of the file. Git then looks in your own Git repository to see if you have that version of the file. If so, that's the "common base version". If Git can find the base version this way, Git can then apply the patch diff to the *base* version, which produces the "theirs" version, guaranteed, because the change *must* apply to the base. That ID is *unique*, across the entire universe of every file in existence anywhere, in any Git repository.[footnote] If you have that ID, you have *that version* of *that file*. Now that Git has the base version and the "theirs" version, Git can do its own three-way merge: diff the base vs your version to see what you changed, and diff the base vs their version to see what they changed. This can still have conflicts, but now at least they will always be in the right places. Chris [footnote] This is clearly nonsense, due to the pigeonhole principle. And yet, Git depends on it successfully (modulo carefully engineered hash collisions, currently possible for SHA-1 but not for SHA-256). With some clever mathematics we can show that the chance of failure of any given Git repository is quite small -- far smaller than the chance that your computer will just randomly explode into flames while you're using it, for instance.