subtree split includes unrelated commits

From: Daniel Pauli <hidden>
Date: 2021-06-18 08:54:30

Hi there

First time I post to the mailing list here, I hope I get it right...

I came across an issue where pushing a subtree resulted in unexpected 
commits in the remote repository: These commits included files that are 
not part of the subtree's directory. There's a related question on 
stackoverflow: 
https://stackoverflow.com/questions/61150709/git-subtree-push-seems-to-push-commits-that-dont-apply-to-the-subtree

In my case, the excess commits were introduced by a merge commit of a 
branch that forked off the main branch *before* the subtree was added. 
This merge commit was the result of updating my fork from the upstream 
repository (which is not aware of the subtree, it just lives in my fork 
so far).

I found the issue to be related with the following change in git-subtree.sh:
Revision: 933cfeb90b5d03b4096db6d60494a6eedea25d03
Author: Dave Ware [off-list ref]
Date: 15.01.2016 01:41:43
Message:
contrib/subtree: fix "subtree split" skipped-merge bug

'git subtree split' can incorrectly skip a merge even when both parents
act on the subtree, provided the merge results in a tree identical to
one of the parents. Fix by copying the merge if at least one parent is
non-identical, and the non-identical parent is not an ancestor of the
identical parent.

Also, add a test case which checks that a descendant remains a
descendent on the subtree in this case.

Signed-off-by: Dave Ware <redacted>
Reviewed-by: David A. Greene <redacted>
Signed-off-by: Junio C Hamano <redacted>
----
Modified: contrib/subtree/git-subtree.sh
Modified: contrib/subtree/t/t7900-subtree.sh
    copycommit=
    if [ -n "$identical" ] && [ -n "$nonidentical" ]; then
        extras=$(git rev-list --count $identical..$nonidentical)
        if [ "$extras" -ne 0 ]; then
            # we need to preserve history along the other branch
 copycommit=1 // <---------------------
        fi
    fi
    if [ -n "$identical" ] && [ -z "$copycommit" ]; then
        echo $identical
    else
        copy_commit $rev $tree "$p" || exit $?
    fi
As a workaround, removing the copycommit=1 line here results in a split 
as I would expect for my case.

I attached a sample repository and log that reproduces the issue:
- From the main branch, do a "git subtree split --prefix my_subtree -b 
splitted -d". This is how the branches listed below were created.
- branch "splitted_bad" shows the unexpected merge commit f7fd955 that 
includes files that are not part of the subtree (9eeff05)
- branch "splitted_good" shows the result as I would expect it, without 
merge commit f7fd955. It was done by commenting out the copycommit=1

Now I wonder, is this expected behavior, or could it be a regression? I 
do not really understand the inner workings of git-subtree.sh, but I 
feel that where it included "too few" commits before the mentioned 
patch, it might now include "too many".

Regards
Daniel

Attachments

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help