From: Colin Stagner Date: Sun, 15 Feb 2026 20:17:44 GMT Subject: [PATCH 2/3] contrib/subtree: functionalize split traversal Message-ID: <20260215201748.889866-3-ask+git@howdoi.land> In-Reply-To: <20260215201748.889866-1-ask+git@howdoi.land> `git subtree split` requires an ancestor-first history traversal. Refactor the existing rev-list traversal into its own function, `find_commits_to_split`. Pass unrevs via stdin to avoid limits on the maximum length of command-line arguments. Also remove an unnecessary `eval`. Signed-off-by: Colin Stagner --- contrib/subtree/git-subtree.sh | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh index 1cdf39a481..7a62ef7504 100755 --- a/contrib/subtree/git-subtree.sh +++ b/contrib/subtree/git-subtree.sh @@ -516,6 +516,31 @@ find_existing_splits () { done || exit $? } +# Usage: find_commits_to_split REV UNREVS [ARGS...] +# +# List each commit to split, with its parents. +# +# Specify the starting REV for the split, which is usually +# a branch tip. Populate UNREVS with the last --rejoin for +# this prefix, if any. Typically, `subtree split` ignores +# history prior to the last --rejoin... unless and if it +# becomes necessary to consider it. `find_existing_splits` is +# a convenient source of UNREVS. +# +# Remaining arguments are passed to rev-list. +# +# Outputs commits in ancestor-first order, one per line, with +# parent information. Outputs all parents before any child. +find_commits_to_split() { + assert test $# -ge 2 + rev="$1" + unrevs="$2" + shift 2 + + echo "$unrevs" | + git rev-list --topo-order --reverse --parents --stdin "$rev" "$@" +} + # Usage: copy_commit REV TREE FLAGS_STR copy_commit () { assert test $# = 3 @@ -1003,12 +1028,11 @@ cmd_split () { # We can't restrict rev-list to only $dir here, because some of our # parents have the $dir contents the root, and those won't match. # (and rev-list --follow doesn't seem to solve this) - grl='git rev-list --topo-order --reverse --parents $rev $unrevs' - revmax=$(eval "$grl" | wc -l) + revmax="$(find_commits_to_split "$rev" "$unrevs" --count)" revcount=0 createcount=0 extracount=0 - eval "$grl" | + find_commits_to_split "$rev" "$unrevs" | while read rev parents do if should_ignore_subtree_split_commit "$rev" -- 2.43.0