Basic "subtree merge --squash" support.
Instead of merging in the history of the entire subproject, just squash it all into one commit, but try to at least track which commits we used so that we can do future merges correctly. Bonus feature: we can actually switch branches of the subproject this way, just by "squash merging" back and forth from one tag to another.
This commit is contained in:
parent
7ee9eef340
commit
1cc2cfff91
@ -167,15 +167,46 @@ try_remove_previous()
|
||||
fi
|
||||
}
|
||||
|
||||
find_latest_squash()
|
||||
{
|
||||
debug "Looking for latest squash..."
|
||||
dir="$1"
|
||||
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
|
||||
case "$a" in
|
||||
START) sq="$b" ;;
|
||||
git-subtree-mainline:) main="$b" ;;
|
||||
git-subtree-split:) sub="$b" ;;
|
||||
END)
|
||||
if [ -n "$sub" ]; then
|
||||
if [ -n "$main" ]; then
|
||||
# a rejoin commit?
|
||||
# Pretend its sub was a squash.
|
||||
sq="$sub"
|
||||
fi
|
||||
debug "Squash found: $sq $sub"
|
||||
echo "$sq" "$sub"
|
||||
break
|
||||
fi
|
||||
sq=
|
||||
main=
|
||||
sub=
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
find_existing_splits()
|
||||
{
|
||||
debug "Looking for prior splits..."
|
||||
dir="$1"
|
||||
revs="$2"
|
||||
git log --grep="^git-subtree-dir: $dir\$" \
|
||||
--pretty=format:'%s%n%n%b%nEND' $revs |
|
||||
--pretty=format:'%s%n%n%b%nEND%n' $revs |
|
||||
while read a b junk; do
|
||||
case "$a" in
|
||||
START) main="$b" ;;
|
||||
git-subtree-mainline:) main="$b" ;;
|
||||
git-subtree-split:) sub="$b" ;;
|
||||
END)
|
||||
@ -244,6 +275,28 @@ rejoin_msg()
|
||||
EOF
|
||||
}
|
||||
|
||||
squash_msg()
|
||||
{
|
||||
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"
|
||||
|
||||
cat <<-EOF
|
||||
|
||||
git-subtree-dir: $dir
|
||||
git-subtree-split: $newsub
|
||||
EOF
|
||||
}
|
||||
|
||||
toptree_for_commit()
|
||||
{
|
||||
commit="$1"
|
||||
@ -278,6 +331,16 @@ tree_changed()
|
||||
fi
|
||||
}
|
||||
|
||||
new_squash_commit()
|
||||
{
|
||||
old="$1"
|
||||
oldsub="$2"
|
||||
newsub="$3"
|
||||
tree=$(toptree_for_commit $newsub) || exit $?
|
||||
squash_msg "$dir" "$oldsub" "$newsub" |
|
||||
git commit-tree "$tree" -p "$old" || exit $?
|
||||
}
|
||||
|
||||
copy_or_skip()
|
||||
{
|
||||
rev="$1"
|
||||
@ -452,6 +515,19 @@ cmd_merge()
|
||||
fi
|
||||
rev="$1"
|
||||
|
||||
if [ -n "$squash" ]; then
|
||||
first_split="$(find_latest_squash "$dir")"
|
||||
if [ -z "$first_split" ]; then
|
||||
die "Can't squash-merge: '$dir' was never added."
|
||||
fi
|
||||
set $first_split
|
||||
old=$1
|
||||
sub=$2
|
||||
new=$(new_squash_commit "$old" "$sub" "$rev") || exit $?
|
||||
debug "New squash commit: $new"
|
||||
rev="$new"
|
||||
fi
|
||||
|
||||
git merge -s subtree $rev
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user