Merge branch 'kb/full-history-compute-treesame-carefully-2'
Major update to the revision traversal logic to improve culling of irrelevant parents while traversing a mergy history. * kb/full-history-compute-treesame-carefully-2: revision.c: make default history consider bottom commits revision.c: don't show all merges for --parents revision.c: discount side branches when computing TREESAME revision.c: add BOTTOM flag for commits simplify-merges: drop merge from irrelevant side branch simplify-merges: never remove all TREESAME parents t6012: update test for tweaked full-history traversal revision.c: Make --full-history consider more merges Documentation: avoid "uninteresting" rev-list-options.txt: correct TREESAME for P t6111: add parents to tests t6111: allow checking the parents as well t6111: new TREESAME test set t6019: test file dropped in -s ours merge decorate.c: compact table when growing
This commit is contained in:
@ -14,21 +14,24 @@ unnote () {
|
||||
|
||||
test_expect_success setup '
|
||||
echo "Hi there" >file &&
|
||||
git add file &&
|
||||
test_tick && git commit -m "Initial file" &&
|
||||
echo "initial" >lost &&
|
||||
git add file lost &&
|
||||
test_tick && git commit -m "Initial file and lost" &&
|
||||
note A &&
|
||||
|
||||
git branch other-branch &&
|
||||
|
||||
echo "Hello" >file &&
|
||||
git add file &&
|
||||
test_tick && git commit -m "Modified file" &&
|
||||
echo "second" >lost &&
|
||||
git add file lost &&
|
||||
test_tick && git commit -m "Modified file and lost" &&
|
||||
note B &&
|
||||
|
||||
git checkout other-branch &&
|
||||
|
||||
echo "Hello" >file &&
|
||||
git add file &&
|
||||
>lost &&
|
||||
git add file lost &&
|
||||
test_tick && git commit -m "Modified the file identically" &&
|
||||
note C &&
|
||||
|
||||
@ -37,7 +40,9 @@ test_expect_success setup '
|
||||
test_tick && git commit -m "Add another file" &&
|
||||
note D &&
|
||||
|
||||
test_tick && git merge -m "merge" master &&
|
||||
test_tick &&
|
||||
test_must_fail git merge -m "merge" master &&
|
||||
>lost && git commit -a -m "merge" &&
|
||||
note E &&
|
||||
|
||||
echo "Yet another" >elif &&
|
||||
@ -105,9 +110,21 @@ check_result 'L K J I H G F E D C B A' --full-history
|
||||
check_result 'K I H E C B A' --full-history -- file
|
||||
check_result 'K I H E C B A' --full-history --topo-order -- file
|
||||
check_result 'K I H E C B A' --full-history --date-order -- file
|
||||
check_outcome failure 'I E C B A' --simplify-merges -- file
|
||||
check_result 'I E C B A' --simplify-merges -- file
|
||||
check_result 'I B A' -- file
|
||||
check_result 'I B A' --topo-order -- file
|
||||
check_result 'H' --first-parent -- another-file
|
||||
|
||||
check_result 'E C B A' --full-history E -- lost
|
||||
test_expect_success 'full history simplification without parent' '
|
||||
printf "%s\n" E C B A >expect &&
|
||||
git log --pretty="$FMT" --full-history E -- lost |
|
||||
unnote >actual &&
|
||||
sed -e "s/^.* \([^ ]*\) .*/\1/" >check <actual &&
|
||||
test_cmp expect check || {
|
||||
cat actual
|
||||
false
|
||||
}
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -16,6 +16,10 @@ test_description='--ancestry-path'
|
||||
#
|
||||
# F...I == F G H I
|
||||
# --ancestry-path F...I == F H I
|
||||
#
|
||||
# G..M -- G.t == [nothing - was dropped in "-s ours" merge L]
|
||||
# --ancestry-path G..M -- G.t == L
|
||||
# --ancestry-path --simplify-merges G^..M -- G.t == G L
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
@ -89,6 +93,29 @@ test_expect_success 'rev-list --ancestry-path F...I' '
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
# G.t is dropped in an "-s ours" merge
|
||||
test_expect_success 'rev-list G..M -- G.t' '
|
||||
>expect &&
|
||||
git rev-list --format=%s G..M -- G.t |
|
||||
sed -e "/^commit /d" >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'rev-list --ancestry-path G..M -- G.t' '
|
||||
echo L >expect &&
|
||||
git rev-list --ancestry-path --format=%s G..M -- G.t |
|
||||
sed -e "/^commit /d" >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'rev-list --ancestry-path --simplify-merges G^..M -- G.t' '
|
||||
for c in G L; do echo $c; done >expect &&
|
||||
git rev-list --ancestry-path --simplify-merges --format=%s G^..M -- G.t |
|
||||
sed -e "/^commit /d" |
|
||||
sort >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
# b---bc
|
||||
# / \ /
|
||||
# a X
|
||||
|
196
t/t6111-rev-list-treesame.sh
Executable file
196
t/t6111-rev-list-treesame.sh
Executable file
@ -0,0 +1,196 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# ,---E--. *H----------. * marks !TREESAME parent paths
|
||||
# / \ / \*
|
||||
# *A--*B---D--*F-*G---------K-*L-*M
|
||||
# \ /* \ /
|
||||
# `-C-' `-*I-*J
|
||||
#
|
||||
# A creates "file", B and F change it.
|
||||
# Odd merge G takes the old version from B.
|
||||
# I changes it, but J reverts it, so K is TREESAME to both parents.
|
||||
# H and L both change "file", and M merges those changes.
|
||||
|
||||
test_description='TREESAME and limiting'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
note () {
|
||||
git tag "$1"
|
||||
}
|
||||
|
||||
unnote () {
|
||||
git name-rev --tags --stdin | sed -e "s|$_x40 (tags/\([^)]*\))\([ ]\)|\1\2|g"
|
||||
}
|
||||
|
||||
test_expect_success setup '
|
||||
test_commit "Initial file" file "Hi there" A &&
|
||||
git branch other-branch &&
|
||||
|
||||
test_commit "file=Hello" file "Hello" B &&
|
||||
git branch third-branch &&
|
||||
|
||||
git checkout other-branch &&
|
||||
test_commit "Added other" other "Hello" C &&
|
||||
|
||||
git checkout master &&
|
||||
test_merge D other-branch &&
|
||||
|
||||
git checkout third-branch &&
|
||||
test_commit "Third file" third "Nothing" E &&
|
||||
|
||||
git checkout master &&
|
||||
test_commit "file=Blah" file "Blah" F &&
|
||||
|
||||
test_tick && git merge --no-commit third-branch &&
|
||||
git checkout third-branch file &&
|
||||
git commit &&
|
||||
note G &&
|
||||
git branch fiddler-branch &&
|
||||
|
||||
git checkout -b part2-branch &&
|
||||
test_commit "file=Part 2" file "Part 2" H &&
|
||||
|
||||
git checkout fiddler-branch &&
|
||||
test_commit "Bad commit" file "Silly" I &&
|
||||
|
||||
test_tick && git revert I && note J &&
|
||||
|
||||
git checkout master &&
|
||||
test_tick && git merge --no-ff fiddler-branch &&
|
||||
note K
|
||||
|
||||
test_commit "file=Part 1" file "Part 1" L &&
|
||||
|
||||
test_tick && test_must_fail git merge part2-branch &&
|
||||
test_commit M file "Parts 1+2"
|
||||
'
|
||||
|
||||
check_outcome () {
|
||||
outcome=$1
|
||||
shift
|
||||
|
||||
case "$1" in
|
||||
*"("*)
|
||||
FMT="%P %H | %s"
|
||||
munge_actual="
|
||||
s/^\([^ ]*\) \([^ ]*\) .*/(\1)\2/
|
||||
s/ //g
|
||||
s/()//
|
||||
"
|
||||
;;
|
||||
*)
|
||||
FMT="%H | %s"
|
||||
munge_actual="s/^\([^ ]*\) .*/\1/"
|
||||
;;
|
||||
esac &&
|
||||
printf "%s\n" $1 >expect &&
|
||||
shift
|
||||
|
||||
param="$*" &&
|
||||
test_expect_$outcome "log $param" '
|
||||
git log --format="$FMT" $param |
|
||||
unnote >actual &&
|
||||
sed -e "$munge_actual" <actual >check &&
|
||||
test_cmp expect check || {
|
||||
cat actual
|
||||
false
|
||||
}
|
||||
'
|
||||
}
|
||||
|
||||
check_result () {
|
||||
check_outcome success "$@"
|
||||
}
|
||||
|
||||
# Odd merge G drops a change in F. Important that G is listed in all
|
||||
# except the most basic list. Achieving this means normal merge D will also be
|
||||
# shown in normal full-history, as we can't distinguish unless we do a
|
||||
# simplification pass. After simplification, D is dropped but G remains.
|
||||
# Also, merge simplification of G should not drop the parent B that the default
|
||||
# simple history follows.
|
||||
check_result 'M L K J I H G F E D C B A'
|
||||
check_result '(LH)M (K)L (GJ)K (I)J (G)I (G)H (FE)G (D)F (B)E (BC)D (A)C (A)B A'
|
||||
check_result 'M H L K J I G E F D C B A' --topo-order
|
||||
check_result 'M L H B A' -- file
|
||||
check_result '(LH)M (B)L (B)H (A)B A' --parents -- file
|
||||
check_result 'M L J I H G F D B A' --full-history -- file
|
||||
check_result '(LH)M (K)L (GJ)K (I)J (G)I (G)H (FB)G (D)F (BA)D (A)B A' --full-history --parents -- file
|
||||
check_result '(LH)M (G)H (J)L (I)J (G)I (FB)G (B)F (A)B A' --simplify-merges -- file
|
||||
check_result 'M L K G F D B A' --first-parent
|
||||
check_result 'M L G F B A' --first-parent -- file
|
||||
|
||||
# Check that odd merge G remains shown when F is the bottom.
|
||||
check_result 'M L K J I H G E' F..M
|
||||
check_result 'M H L K J I G E' F..M --topo-order
|
||||
check_result 'M L H' F..M -- file
|
||||
check_result '(LH)M (B)L (B)H' --parents F..M -- file
|
||||
check_result 'M L J I H G' F..M --full-history -- file
|
||||
check_result '(LH)M (K)L (GJ)K (I)J (G)I (G)H (FB)G' F..M --full-history --parents -- file
|
||||
check_result '(LH)M (G)H (J)L (I)J (G)I (FB)G' F..M --simplify-merges -- file
|
||||
check_result 'M L K J I H G' F..M --ancestry-path
|
||||
check_result 'M L J I H G' F..M --ancestry-path -- file
|
||||
check_result '(LH)M (K)L (GJ)K (I)J (G)I (G)H (FE)G' F..M --ancestry-path --parents -- file
|
||||
check_result '(LH)M (G)H (J)L (I)J (G)I (FE)G' F..M --ancestry-path --simplify-merges -- file
|
||||
check_result 'M L K G' F..M --first-parent
|
||||
check_result 'M L G' F..M --first-parent -- file
|
||||
|
||||
# Note that G is pruned when E is the bottom, even if it's the same commit list
|
||||
# If we want history since E, then we're quite happy to ignore G that took E.
|
||||
check_result 'M L K J I H G' E..M --ancestry-path
|
||||
check_result 'M L J I H' E..M --ancestry-path -- file
|
||||
check_result '(LH)M (K)L (EJ)K (I)J (E)I (E)H' E..M --ancestry-path --parents -- file
|
||||
check_result '(LH)M (E)H (J)L (I)J (E)I' E..M --ancestry-path --simplify-merges -- file
|
||||
|
||||
# Should still be able to ignore I-J branch in simple log, despite limiting
|
||||
# to G.
|
||||
check_result 'M L K J I H' G..M
|
||||
check_result 'M H L K J I' G..M --topo-order
|
||||
check_result 'M L H' G..M -- file
|
||||
check_result '(LH)M (G)L (G)H' G..M --parents -- file
|
||||
check_result 'M L J I H' G..M --full-history -- file
|
||||
check_result 'M L K J I H' G..M --full-history --parents -- file
|
||||
check_result 'M H L J I' G..M --simplify-merges -- file
|
||||
check_result 'M L K J I H' G..M --ancestry-path
|
||||
check_result 'M L J I H' G..M --ancestry-path -- file
|
||||
check_result 'M L K J I H' G..M --ancestry-path --parents -- file
|
||||
check_result 'M H L J I' G..M --ancestry-path --simplify-merges -- file
|
||||
|
||||
# B..F should be able to simplify the merge D from irrelevant side branch C.
|
||||
# Default log should also be free to follow B-D, and ignore C.
|
||||
# But --full-history shouldn't drop D on its own - without simplification,
|
||||
# we can't decide if the merge from INTERESTING commit C was sensible.
|
||||
check_result 'F D C' B..F
|
||||
check_result 'F' B..F -- file
|
||||
check_result '(B)F' B..F --parents -- file
|
||||
check_result 'F D' B..F --full-history -- file
|
||||
check_result '(D)F (BA)D' B..F --full-history --parents -- file
|
||||
check_result '(B)F' B..F --simplify-merges -- file
|
||||
check_result 'F D' B..F --ancestry-path
|
||||
check_result 'F' B..F --ancestry-path -- file
|
||||
check_result 'F' B..F --ancestry-path --parents -- file
|
||||
check_result 'F' B..F --ancestry-path --simplify-merges -- file
|
||||
check_result 'F D' B..F --first-parent
|
||||
check_result 'F' B..F --first-parent -- file
|
||||
|
||||
# E...F should be equivalent to E F ^B, and be able to drop D as above.
|
||||
check_result 'F' E F ^B -- file # includes D
|
||||
check_result 'F' E...F -- file # includes D
|
||||
|
||||
# Any sort of full history of C..F should show D, as it's the connection to C,
|
||||
# and it differs from it.
|
||||
check_result 'F D B' C..F
|
||||
check_result 'F B' C..F -- file
|
||||
check_result '(B)F (A)B' C..F --parents -- file
|
||||
check_result 'F D B' C..F --full-history -- file
|
||||
check_result '(D)F (BC)D (A)B' C..F --full-history --parents -- file
|
||||
check_result '(D)F (BC)D (A)B' C..F --simplify-merges -- file
|
||||
check_result 'F D' C..F --ancestry-path
|
||||
check_result 'F D' C..F --ancestry-path -- file
|
||||
check_result 'F D' C..F --ancestry-path --parents -- file
|
||||
check_result 'F D' C..F --ancestry-path --simplify-merges -- file
|
||||
check_result 'F D B' C..F --first-parent
|
||||
check_result 'F B' C..F --first-parent -- file
|
||||
|
||||
|
||||
test_done
|
Reference in New Issue
Block a user