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

Re: [BUG] submodule merge tries to read B's commit from A

From
Philippe Blain <levraiphilippeblain@gmail.com>
Date
Sep 30, 2026, 18:31 UTC
Message-ID
<764b8c2e-cf09-4531-94f2-268f97a889d7@gmail.com>
In-Reply-To
<CAP4DsUexEmm1qo6jH+Qzy+n3dQs_OCJ8yg=ReF+aVrcTrC7NeQ@mail.gmail.com>
Hi Guillaume,
Le 2026-09-23 à 16 h 20, Guillaume CHAUVEL a écrit :
Show 5 quoted lines
> I ran into two problems while merging a superproject with submodules.
> 
> One problem, involving the repository used for commit-graph lookups, was
> reported in this thread:
> https://lore.kernel.org/git/d3241733-d015-4646-88e0-06e56a04e77b@nutanix.com/T/#m174067937aaf76e9fa844386961b3e9e66c1e4d9

FYI, the above bug was fixed in 700f7b74de (commit-reach: parse commits in the given repository, 2026-09-16), which is currently in 'next' but not yet in master.

Show 9 quoted lines
> The other problem is that during a merge, Git sometimes tries to read
> from submodule A a commit that exists only in submodule B. I reproduced
> this with Git v2.56.0-rc2, built from source in an Ubuntu 26.04
> container and an Alpine container. The reproducer below triggered the
> issue in all 50 Ubuntu runs and in 43 out of 50 Alpine runs.
> 
> The merge should report a submodule conflict, not look for B's commit
> in A or report A as corrupt. The script checks the OID's presence in
> both submodules and prints the "BUG" line when it finds this case.

Thanks for the reproducer, I confirm I see the same behaviour with v2.56.0-rc2, on RHEL 9. With v2.48.1, the merge results in a conflict, instead of aborting, although I get a spurious "hash mismatch" message, and the reason for the conflict ("commits not present") is wrong:

git version 2.48.1 git merge exit status: 1 error: hash mismatch 2ca9f0f330e976b992fc18633d1d267b8aad596e Failed to merge submodule A (commits not present) CONFLICT (submodule): Merge conflict in A Failed to merge submodule B CONFLICT (submodule): Merge conflict in B Automatic merge failed; fix conflicts and then commit the result.

With 2.33.0, which I chose randomly, we get the correct behaviour:

git version 2.33.0 git merge exit status: 1 Failed to merge submodule A CONFLICT (submodule): Merge conflict in A Failed to merge submodule B CONFLICT (submodule): Merge conflict in B Automatic merge failed; fix conflicts and then commit the result.

I turned your reproducer into a bisection script (~/bisect-merge.sh) by tweaking the final 'if':

```
if [[ $merge_output =~ Could\ not\ read\ ([0-9a-f]{40}|[0-9a-f]{64}) ]]; then
    foreign_oid=${BASH_REMATCH[1]}
    if ! (cd A && git cat-file -e "$foreign_oid" 2>/dev/null) &&
         (cd B && git cat-file -e "$foreign_oid" 2>/dev/null); then
        printf 'BUG: OID %s belongs to B instead of A\n' "$foreign_oid"
        exit 1
    fi
elif [[ $merge_output =~ hash\ mismatch ]];then
        [ ${1:-""} = MISMATCH ] && exit 1 || exit 0
else
    exit 0
fi
```
and invoking it in my ~/bisect-git.sh script:

``` #!/bin/bash

make clean > /dev/null
# build but keep the output on one line
if	make -j |& { while read line; do  printf "\033[K%s\r" "${line}" ; done; 
                     printf "\033[KFinished building $(cat GIT-VERSION-FILE)\n" ; }
then
	# run project specific test and report its status
	export PATH="$PWD/bin-wrappers/:$PATH"
	~/bisect-merge.sh "$@"
	status=$?
else
	# tell the caller this is untestable
	status=125
fi

# return control echo exit $status ```

Bisecting the merge failure with:
	git bisect start v2.56.0-rc2 v2.48.1 && git bisect run ~/bisect-git.sh

finds bb5da75d61 (commit: use commit graph in lookup_commit_reference_gently(), 2026-02-16), i.e. v2.54.0-rc0~136^2, which is the same commit from which the commit-graph bug mentioned above originates. I CC'ed Patrick, its author.

Bisecting the "hash mismatch" behaviour with:
	git bisect start v2.48.1 v2.33.0 && git bisect run ~/bisect-git.sh MISMATCH

finds 6f1e9394e2 (object: fix leaking packfiles when closing object store, 2024-08-08), i.e. v2.47.0-rc0~123^2, which is also authored by Patrick.

I did not yet dig further, but I have a few additional observations:
- in contrast to the commit-graph bug, disabling the use of commit-graphs via
  'git config --global core.commitGraph false' early in the script, by moving the 'tmpdir'
  definition to the top and setting GIT_CONFIG_GLOBAL=$tmpdir/.gitconfig, does not change
  the behaviour, neither in the "repository corrupt" case, nor in the "hash mismatch" case.
- On Ubuntu 22.02 under WSL, the reproducer does not trigger the bug on v2.56.0-rc2 (on a dozen runs),
  but it does trigger it on v2.55.0. Funnily on that system with v2.56.0-rc2 I get the correct behaviour !
  (no "hash mismatch" either).
- On a Ubuntu 22.04 Docker container, I get the same behaviour as on RHEL 9.
Show 5 quoted lines
> An AI analysis identified a likely cause: a delta-base cache entry may
> remain after its pack is closed. If a pack from another submodule reuses
> the same packed_git address and base offset, Git may return stale cached
> data.
> 
Previous: Guillaume CHAUVELNext: Patrick Steinhardt
Message 2 of 4 in “[BUG] submodule merge tries to read B's commit from A”
  1. Guillaume CHAUVELSep 23, 2026
  2. Philippe BlainSep 30, 2026
  3. Patrick SteinhardtOct 1, 2026
  4. Patrick SteinhardtOct 2, 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.