git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] am: record blobs of cleanly applied patches when using --3way

From
Junio C Hamano <gitster@pobox.com>
Date
Aug 25, 2026, 17:14 UTC
Message-ID
<xmqqmruam8at.fsf@gitster.g>
In-Reply-To
<20260825085516.66088-1-nikita@island.io>
Nikita Leshenko <nikita@island.io> writes:
Show 46 quoted lines
> Make "git am --3way" succeed in an edge case where it currently fails.
>
> First, some background about the case:
>
> Say we have a patch with two commits, A and B, and both of them change the
> same file.  We apply them to a different repo on a different version of the
> file using --3way.
>
> If both patches apply cleanly, we are done.
>
> If A does not apply cleanly, git am falls back to 3-way merge.  To merge,
> Git uses the preimage hash from the patch:
>
>     A: index 83b2a16..cccad2b 100644
>     B: index cccad2b..0ce2f98 100644
>
> git am looks up 83b2a16, applies A to it, and merges that result with the
> current version of the file.  As an important side effect, applying A to
> 83b2a16 also stores A's postimage, cccad2b, in the repository.  This means
> that if B also doesn't apply cleanly, cccad2b (which is now B's preimage)
> exists in the repository so we can merge against it as well.
>
> Let's assume instead that A applies cleanly and B fails.  Because git am
> didn't have to 3-way merge A, nothing created cccad2b this time.  What we
> have after applying A is our file plus A's change, which is a different
> hash.  When B doesn't apply cleanly, git am fails because it doesn't know
> what cccad2b is:
>
>     Applying: A
>     Applying: B
>     error: sha1 information is lacking or useless (file).
>     error: could not build fake ancestor
>
> However, technically we have the information to build the fake ancestor!  We
> have 83b2a16 in the repository, and we have A, so if we apply A we'll get
> that hash.
>
> So do exactly that: if the user requested --3way, apply the patch on the
> fake ancestor even after a patch applies cleanly, in order to produce
> intermediate hashes for later commits.  If the preimage is missing, or the
> patch does not apply, nothing is recorded and git am behaves as it does
> today.
>
> This does not change the behavior of how patches apply, but when the user
> requested --3way it does cost one extra "git apply --build-fake-ancestor"
> process and one extra apply per clean patch.

If you have a 50-patch series that cleanly applies, we would incur overhead to spawn 49 extra "git apply --build-fake-ancestor" subprocesses, to write and unlink 49 temporary index files, and to perform 49 in-core patch applications, generating unneeded loose objects in the object database, and loading and unloading the index file one extra time per step. That is simply unacceptable.

Can't you do the equivalent lazily inside fall_back_threeway() instead? A rough outline may go like so:

 * Imagine that, after applying patches 1..(N-1) successfully, you
   are applying patch N.
   - First try direct application of the patch, and it fails.
   - You call fall_back_threeway().
   - build_fake_ancestor() is called for patch N; if the preimage
     blob exists, you are done, but the case you want to address is
     what to do when the preimage is missing.  And in that case (and
     in that case only), can't you reconstruct the image chain
     lazily?
     Instead of returning error("could not build fake ancestor"):
     - You inspect patches in .git/rebase-apply/ for 1..(N-1)
       patches (i.e., those you have applied already) to find the
       relevant blob objects involved in reconstructing the
       preimage blob necessary to apply patch N.  Some of the
       blobs may already exist in the object database (83b2a16
       in your example).
     - Apply these previous patches in-core to arrive at the
       preimage recorded in these earlier patches (applying patch 1
       to 83b2a16 would now give you cccad2b), until you see the
       preimage blob recorded in patch N.  Write out that blob
       object (and not the blobs that the chain may have
       produced as a result of intermediate patches).
   - If the lazy reconstruction yielded the necessary blobs, try the
     build_fake_ancestor() call again, which should succeed.  If
     not, you can return error("could not build fake ancestor").
   - And after patch N succeeds with 3-way fallback this way, you
     would also have the postimage blob recorded in the patch in
     your object database, which may help when you apply patch
     (N+1).

When the patches cleanly apply, or if 3-way finds necessary blobs already, there is no additional overhead with the above approach.

Hmm?
Previous: Nikita LeshenkoNext: Nikita Leshenko
Message 2 of 3 in “am: record blobs of cleanly applied patches when using --3way”
  1. am: record blobs of cleanly applied patches when using --3wayNikita Leshenko, Aug 25, 2026
  2. Junio C HamanoAug 25, 2026
  3. Nikita LeshenkoAug 25, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.