From: Bhavik Bavishi Date: Sun, 09 Nov 2025 10:09:49 GMT Subject: Re: [Bug report] git cherry-pick silently ignores error whereas git apply fails for hunk apply Message-ID: In-Reply-To: Thanks for the explanation this helps. On Sat, Nov 8, 2025 at 4:28 PM Chris Torek wrote: > > 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.