ignore-joins ignore prior --rejoin commits
onto= try connecting new tree to an existing one
rejoin merge the new branch back into HEAD
- options for 'merge' and 'pull'
+ options for 'add', 'merge', and 'pull'
squash merge subtree changes as a single commit
"
eval $(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)
+PATH=$(git --exec-path):$PATH
. git-sh-setup
require_work_tree
if [ -z "$prefix" ]; then
die "You must provide the --prefix option."
fi
-dir="$prefix"
+dir="$(dirname "$prefix/.")"
if [ "$command" != "pull" ]; then
revs=$(git rev-parse $default --revs-only "$@") || exit $?
find_latest_squash()
{
- debug "Looking for latest squash..."
+ debug "Looking for latest squash ($dir)..."
dir="$1"
- git log --grep="^git-subtree-dir: $dir\$" \
+ sq=
+ main=
+ sub=
+ git log --grep="^git-subtree-dir: $dir/*\$" \
--pretty=format:'START %H%n%s%n%n%b%nEND%n' HEAD |
while read a b junk; do
+ debug "$a $b $junk"
+ debug "{{$sq/$main/$sub}}"
case "$a" in
START) sq="$b" ;;
git-subtree-mainline:) main="$b" ;;
debug "Looking for prior splits..."
dir="$1"
revs="$2"
- git log --grep="^git-subtree-dir: $dir\$" \
- --pretty=format:'%s%n%n%b%nEND%n' $revs |
+ main=
+ sub=
+ git log --grep="^git-subtree-dir: $dir/*\$" \
+ --pretty=format:'START %H%n%s%n%n%b%nEND%n' $revs |
while read a b junk; do
case "$a" in
- START) main="$b" ;;
+ START) sq="$b" ;;
git-subtree-mainline:) main="$b" ;;
git-subtree-split:) sub="$b" ;;
END)
+ debug " Main is: '$main'"
+ if [ -z "$main" -a -n "$sub" ]; then
+ # squash commits refer to a subtree
+ debug " Squash: $sq from $sub"
+ cache_set "$sq" "$sub"
+ fi
if [ -n "$main" -a -n "$sub" ]; then
debug " Prior: $main -> $sub"
cache_set $main $sub
dir="$1"
oldsub="$2"
newsub="$3"
- oldsub_short=$(git rev-parse --short "$oldsub")
newsub_short=$(git rev-parse --short "$newsub")
- cat <<-EOF
- Squashed '$dir/' changes from $oldsub_short..$newsub_short
-
- EOF
- git log --pretty=tformat:'%h %s' "$oldsub..$newsub"
- git log --pretty=tformat:'REVERT: %h %s' "$newsub..$oldsub"
+ if [ -n "$oldsub" ]; then
+ oldsub_short=$(git rev-parse --short "$oldsub")
+ echo "Squashed '$dir/' changes from $oldsub_short..$newsub_short"
+ echo
+ git log --pretty=tformat:'%h %s' "$oldsub..$newsub"
+ git log --pretty=tformat:'REVERT: %h %s' "$newsub..$oldsub"
+ else
+ echo "Squashed '$dir/' content from commit $newsub_short"
+ fi
- cat <<-EOF
-
- git-subtree-dir: $dir
- git-subtree-split: $newsub
- EOF
+ echo
+ echo "git-subtree-dir: $dir"
+ echo "git-subtree-split: $newsub"
}
toptree_for_commit()
git ls-tree "$commit" -- "$dir" |
while read mode type tree name; do
assert [ "$name" = "$dir" ]
+ assert [ "$type" = "tree" ]
echo $tree
break
done
oldsub="$2"
newsub="$3"
tree=$(toptree_for_commit $newsub) || exit $?
- squash_msg "$dir" "$oldsub" "$newsub" |
- git commit-tree "$tree" -p "$old" || exit $?
+ if [ -n "$old" ]; then
+ squash_msg "$dir" "$oldsub" "$newsub" |
+ git commit-tree "$tree" -p "$old" || exit $?
+ else
+ squash_msg "$dir" "" "$newsub" |
+ git commit-tree "$tree" || exit $?
+ fi
}
copy_or_skip()
debug "Adding $dir as '$rev'..."
git read-tree --prefix="$dir" $rev || exit $?
- git checkout "$dir" || exit $?
+ git checkout -- "$dir" || exit $?
tree=$(git write-tree) || exit $?
headrev=$(git rev-parse HEAD) || exit $?
else
headp=
fi
- commit=$(add_msg "$dir" "$headrev" "$rev" |
- git commit-tree $tree $headp -p "$rev") || exit $?
+
+ if [ -n "$squash" ]; then
+ rev=$(new_squash_commit "" "" "$rev") || exit $?
+ commit=$(echo "Merge commit '$rev' as '$dir'" |
+ git commit-tree $tree $headp -p "$rev") || exit $?
+ else
+ commit=$(add_msg "$dir" "$headrev" "$rev" |
+ git commit-tree $tree $headp -p "$rev") || exit $?
+ fi
git reset "$commit" || exit $?
+
+ say "Added dir '$dir'"
}
cmd_split()
set $first_split
old=$1
sub=$2
+ if [ "$sub" = "$rev" ]; then
+ say "Subtree is already at commit $rev."
+ exit 0
+ fi
new=$(new_squash_commit "$old" "$sub" "$rev") || exit $?
debug "New squash commit: $new"
rev="$new"