mirror of
https://github.com/git/git.git
synced 2026-03-05 06:57:37 +01:00
Merge branch 'rs/subtree-fixes'
Various subtree fixes. * rs/subtree-fixes: subtree: performance improvement for finding unexpected parent commits subtree: improve decision on merges kept in split subtree: use commits before rejoins for splits subtree: make --ignore-joins pay attention to adds subtree: refactor split of a commit into standalone method
This commit is contained in:
@@ -231,12 +231,14 @@ cache_miss () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
check_parents () {
|
check_parents () {
|
||||||
missed=$(cache_miss "$@")
|
missed=$(cache_miss "$1")
|
||||||
|
local indent=$(($2 + 1))
|
||||||
for miss in $missed
|
for miss in $missed
|
||||||
do
|
do
|
||||||
if ! test -r "$cachedir/notree/$miss"
|
if ! test -r "$cachedir/notree/$miss"
|
||||||
then
|
then
|
||||||
debug " incorrect order: $miss"
|
debug " incorrect order: $miss"
|
||||||
|
process_split_commit "$miss" "" "$indent"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
@@ -340,7 +342,12 @@ find_existing_splits () {
|
|||||||
revs="$2"
|
revs="$2"
|
||||||
main=
|
main=
|
||||||
sub=
|
sub=
|
||||||
git log --grep="^git-subtree-dir: $dir/*\$" \
|
local grep_format="^git-subtree-dir: $dir/*\$"
|
||||||
|
if test -n "$ignore_joins"
|
||||||
|
then
|
||||||
|
grep_format="^Add '$dir/' from commit '"
|
||||||
|
fi
|
||||||
|
git log --grep="$grep_format" \
|
||||||
--no-show-signature --pretty=format:'START %H%n%s%n%n%b%nEND%n' $revs |
|
--no-show-signature --pretty=format:'START %H%n%s%n%n%b%nEND%n' $revs |
|
||||||
while read a b junk
|
while read a b junk
|
||||||
do
|
do
|
||||||
@@ -534,6 +541,7 @@ copy_or_skip () {
|
|||||||
nonidentical=
|
nonidentical=
|
||||||
p=
|
p=
|
||||||
gotparents=
|
gotparents=
|
||||||
|
copycommit=
|
||||||
for parent in $newparents
|
for parent in $newparents
|
||||||
do
|
do
|
||||||
ptree=$(toptree_for_commit $parent) || exit $?
|
ptree=$(toptree_for_commit $parent) || exit $?
|
||||||
@@ -541,7 +549,24 @@ copy_or_skip () {
|
|||||||
if test "$ptree" = "$tree"
|
if test "$ptree" = "$tree"
|
||||||
then
|
then
|
||||||
# an identical parent could be used in place of this rev.
|
# an identical parent could be used in place of this rev.
|
||||||
identical="$parent"
|
if test -n "$identical"
|
||||||
|
then
|
||||||
|
# if a previous identical parent was found, check whether
|
||||||
|
# one is already an ancestor of the other
|
||||||
|
mergebase=$(git merge-base $identical $parent)
|
||||||
|
if test "$identical" = "$mergebase"
|
||||||
|
then
|
||||||
|
# current identical commit is an ancestor of parent
|
||||||
|
identical="$parent"
|
||||||
|
elif test "$parent" != "$mergebase"
|
||||||
|
then
|
||||||
|
# no common history; commit must be copied
|
||||||
|
copycommit=1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# first identical parent detected
|
||||||
|
identical="$parent"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
nonidentical="$parent"
|
nonidentical="$parent"
|
||||||
fi
|
fi
|
||||||
@@ -564,7 +589,6 @@ copy_or_skip () {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
copycommit=
|
|
||||||
if test -n "$identical" && test -n "$nonidentical"
|
if test -n "$identical" && test -n "$nonidentical"
|
||||||
then
|
then
|
||||||
extras=$(git rev-list --count $identical..$nonidentical)
|
extras=$(git rev-list --count $identical..$nonidentical)
|
||||||
@@ -598,6 +622,58 @@ ensure_valid_ref_format () {
|
|||||||
die "'$1' does not look like a ref"
|
die "'$1' does not look like a ref"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
process_split_commit () {
|
||||||
|
local rev="$1"
|
||||||
|
local parents="$2"
|
||||||
|
local indent=$3
|
||||||
|
|
||||||
|
if test $indent -eq 0
|
||||||
|
then
|
||||||
|
revcount=$(($revcount + 1))
|
||||||
|
else
|
||||||
|
# processing commit without normal parent information;
|
||||||
|
# fetch from repo
|
||||||
|
parents=$(git rev-parse "$rev^@")
|
||||||
|
extracount=$(($extracount + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
progress "$revcount/$revmax ($createcount) [$extracount]"
|
||||||
|
|
||||||
|
debug "Processing commit: $rev"
|
||||||
|
exists=$(cache_get "$rev")
|
||||||
|
if test -n "$exists"
|
||||||
|
then
|
||||||
|
debug " prior: $exists"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
createcount=$(($createcount + 1))
|
||||||
|
debug " parents: $parents"
|
||||||
|
check_parents "$parents" "$indent"
|
||||||
|
newparents=$(cache_get $parents)
|
||||||
|
debug " newparents: $newparents"
|
||||||
|
|
||||||
|
tree=$(subtree_for_commit "$rev" "$dir")
|
||||||
|
debug " tree is: $tree"
|
||||||
|
|
||||||
|
# ugly. is there no better way to tell if this is a subtree
|
||||||
|
# vs. a mainline commit? Does it matter?
|
||||||
|
if test -z "$tree"
|
||||||
|
then
|
||||||
|
set_notree "$rev"
|
||||||
|
if test -n "$newparents"
|
||||||
|
then
|
||||||
|
cache_set "$rev" "$rev"
|
||||||
|
fi
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
newrev=$(copy_or_skip "$rev" "$tree" "$newparents") || exit $?
|
||||||
|
debug " newrev is: $newrev"
|
||||||
|
cache_set "$rev" "$newrev"
|
||||||
|
cache_set latest_new "$newrev"
|
||||||
|
cache_set latest_old "$rev"
|
||||||
|
}
|
||||||
|
|
||||||
cmd_add () {
|
cmd_add () {
|
||||||
if test -e "$dir"
|
if test -e "$dir"
|
||||||
then
|
then
|
||||||
@@ -689,12 +765,7 @@ cmd_split () {
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test -n "$ignore_joins"
|
unrevs="$(find_existing_splits "$dir" "$revs")"
|
||||||
then
|
|
||||||
unrevs=
|
|
||||||
else
|
|
||||||
unrevs="$(find_existing_splits "$dir" "$revs")"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# We can't restrict rev-list to only $dir here, because some of our
|
# 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.
|
# parents have the $dir contents the root, and those won't match.
|
||||||
@@ -703,45 +774,11 @@ cmd_split () {
|
|||||||
revmax=$(eval "$grl" | wc -l)
|
revmax=$(eval "$grl" | wc -l)
|
||||||
revcount=0
|
revcount=0
|
||||||
createcount=0
|
createcount=0
|
||||||
|
extracount=0
|
||||||
eval "$grl" |
|
eval "$grl" |
|
||||||
while read rev parents
|
while read rev parents
|
||||||
do
|
do
|
||||||
revcount=$(($revcount + 1))
|
process_split_commit "$rev" "$parents" 0
|
||||||
progress "$revcount/$revmax ($createcount)"
|
|
||||||
debug "Processing commit: $rev"
|
|
||||||
exists=$(cache_get "$rev")
|
|
||||||
if test -n "$exists"
|
|
||||||
then
|
|
||||||
debug " prior: $exists"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
createcount=$(($createcount + 1))
|
|
||||||
debug " parents: $parents"
|
|
||||||
newparents=$(cache_get $parents)
|
|
||||||
debug " newparents: $newparents"
|
|
||||||
|
|
||||||
tree=$(subtree_for_commit "$rev" "$dir")
|
|
||||||
debug " tree is: $tree"
|
|
||||||
|
|
||||||
check_parents $parents
|
|
||||||
|
|
||||||
# ugly. is there no better way to tell if this is a subtree
|
|
||||||
# vs. a mainline commit? Does it matter?
|
|
||||||
if test -z "$tree"
|
|
||||||
then
|
|
||||||
set_notree "$rev"
|
|
||||||
if test -n "$newparents"
|
|
||||||
then
|
|
||||||
cache_set "$rev" "$rev"
|
|
||||||
fi
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
newrev=$(copy_or_skip "$rev" "$tree" "$newparents") || exit $?
|
|
||||||
debug " newrev is: $newrev"
|
|
||||||
cache_set "$rev" "$newrev"
|
|
||||||
cache_set latest_new "$newrev"
|
|
||||||
cache_set latest_old "$rev"
|
|
||||||
done || exit $?
|
done || exit $?
|
||||||
|
|
||||||
latest_new=$(cache_get latest_new)
|
latest_new=$(cache_get latest_new)
|
||||||
|
|||||||
Reference in New Issue
Block a user