diff options
Diffstat (limited to 't/t6010-merge-base.sh')
-rwxr-xr-x | t/t6010-merge-base.sh | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/t/t6010-merge-base.sh b/t/t6010-merge-base.sh new file mode 100755 index 0000000000..31db7b5f91 --- /dev/null +++ b/t/t6010-merge-base.sh @@ -0,0 +1,308 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='Merge base and parent list computation. +' + +. ./test-lib.sh + +M=1130000000 +Z=+0000 + +GIT_COMMITTER_EMAIL=git@comm.iter.xz +GIT_COMMITTER_NAME='C O Mmiter' +GIT_AUTHOR_NAME='A U Thor' +GIT_AUTHOR_EMAIL=git@au.thor.xz +export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL + +doit () { + OFFSET=$1 && + NAME=$2 && + shift 2 && + + PARENTS= && + for P + do + PARENTS="${PARENTS}-p $P " + done && + + GIT_COMMITTER_DATE="$(($M + $OFFSET)) $Z" && + GIT_AUTHOR_DATE=$GIT_COMMITTER_DATE && + export GIT_COMMITTER_DATE GIT_AUTHOR_DATE && + + commit=$(echo $NAME | git commit-tree $T $PARENTS) && + + echo $commit >.git/refs/tags/$NAME && + echo $commit +} + +test_expect_success 'setup' ' + T=$(git mktree </dev/null) +' + +test_expect_success 'set up G and H' ' + # E---D---C---B---A + # \"-_ \ \ + # \ `---------G \ + # \ \ + # F----------------H + E=$(doit 5 E) && + D=$(doit 4 D $E) && + F=$(doit 6 F $E) && + C=$(doit 3 C $D) && + B=$(doit 2 B $C) && + A=$(doit 1 A $B) && + G=$(doit 7 G $B $E) && + H=$(doit 8 H $A $F) +' + +test_expect_success 'merge-base G H' ' + git name-rev $B >expected && + + MB=$(git merge-base G H) && + git name-rev "$MB" >actual.single && + + MB=$(git merge-base --all G H) && + git name-rev "$MB" >actual.all && + + MB=$(git show-branch --merge-base G H) && + git name-rev "$MB" >actual.sb && + + test_cmp expected actual.single && + test_cmp expected actual.all && + test_cmp expected actual.sb +' + +test_expect_success 'merge-base/show-branch --independent' ' + git name-rev "$H" >expected1 && + git name-rev "$H" "$G" >expected2 && + + parents=$(git merge-base --independent H) && + git name-rev $parents >actual1.mb && + parents=$(git merge-base --independent A H G) && + git name-rev $parents >actual2.mb && + + parents=$(git show-branch --independent H) && + git name-rev $parents >actual1.sb && + parents=$(git show-branch --independent A H G) && + git name-rev $parents >actual2.sb && + + test_cmp expected1 actual1.mb && + test_cmp expected2 actual2.mb && + test_cmp expected1 actual1.sb && + test_cmp expected2 actual2.sb +' + +test_expect_success 'unsynchronized clocks' ' + # This test is to demonstrate that relying on timestamps in a distributed + # SCM to provide a _consistent_ partial ordering of commits leads to + # insanity. + # + # Relative + # Structure timestamps + # + # PL PR +4 +4 + # / \/ \ / \/ \ + # L2 C2 R2 +3 -1 +3 + # | | | | | | + # L1 C1 R1 +2 -2 +2 + # | | | | | | + # L0 C0 R0 +1 -3 +1 + # \ | / \ | / + # S 0 + # + # The left and right chains of commits can be of any length and complexity as + # long as all of the timestamps are greater than that of S. + + S=$(doit 0 S) && + + C0=$(doit -3 C0 $S) && + C1=$(doit -2 C1 $C0) && + C2=$(doit -1 C2 $C1) && + + L0=$(doit 1 L0 $S) && + L1=$(doit 2 L1 $L0) && + L2=$(doit 3 L2 $L1) && + + R0=$(doit 1 R0 $S) && + R1=$(doit 2 R1 $R0) && + R2=$(doit 3 R2 $R1) && + + PL=$(doit 4 PL $L2 $C2) && + PR=$(doit 4 PR $C2 $R2) && + + git name-rev $C2 >expected && + + MB=$(git merge-base PL PR) && + git name-rev "$MB" >actual.single && + + MB=$(git merge-base --all PL PR) && + git name-rev "$MB" >actual.all && + + test_cmp expected actual.single && + test_cmp expected actual.all +' + +test_expect_success '--independent with unsynchronized clocks' ' + IB=$(doit 0 IB) && + I1=$(doit -10 I1 $IB) && + I2=$(doit -9 I2 $I1) && + I3=$(doit -8 I3 $I2) && + I4=$(doit -7 I4 $I3) && + I5=$(doit -6 I5 $I4) && + I6=$(doit -5 I6 $I5) && + I7=$(doit -4 I7 $I6) && + I8=$(doit -3 I8 $I7) && + IH=$(doit -2 IH $I8) && + + echo $IH >expected && + git merge-base --independent IB IH >actual && + test_cmp expected actual +' + +test_expect_success 'merge-base for octopus-step (setup)' ' + # Another set to demonstrate base between one commit and a merge + # in the documentation. + # + # * C (MMC) * B (MMB) * A (MMA) + # * o * o * o + # * o * o * o + # * o * o * o + # * o | _______/ + # | |/ + # | * 1 (MM1) + # | _______/ + # |/ + # * root (MMR) + + test_commit MMR && + test_commit MM1 && + test_commit MM-o && + test_commit MM-p && + test_commit MM-q && + test_commit MMA && + git checkout MM1 && + test_commit MM-r && + test_commit MM-s && + test_commit MM-t && + test_commit MMB && + git checkout MMR && + test_commit MM-u && + test_commit MM-v && + test_commit MM-w && + test_commit MM-x && + test_commit MMC +' + +test_expect_success 'merge-base A B C' ' + git rev-parse --verify MM1 >expected && + git rev-parse --verify MMR >expected.sb && + + git merge-base --all MMA MMB MMC >actual && + git merge-base --all --octopus MMA MMB MMC >actual.common && + git show-branch --merge-base MMA MMB MMC >actual.sb && + + test_cmp expected actual && + test_cmp expected.sb actual.common && + test_cmp expected.sb actual.sb +' + +test_expect_success 'criss-cross merge-base for octopus-step' ' + git reset --hard MMR && + test_commit CC1 && + git reset --hard E && + test_commit CC2 && + test_tick && + # E is a root commit unrelated to MMR root on which CC1 is based + git merge -s ours --allow-unrelated-histories CC1 && + test_commit CC-o && + test_commit CCB && + git reset --hard CC1 && + # E is a root commit unrelated to MMR root on which CC1 is based + git merge -s ours --allow-unrelated-histories CC2 && + test_commit CCA && + + git rev-parse CC1 CC2 >expected && + git merge-base --all CCB CCA^^ CCA^^2 >actual && + + sort expected >expected.sorted && + sort actual >actual.sorted && + test_cmp expected.sorted actual.sorted +' + +test_expect_success 'using reflog to find the fork point' ' + git reset --hard && + git checkout -b base $E && + + ( + for count in 1 2 3 + do + git commit --allow-empty -m "Base commit #$count" && + git rev-parse HEAD >expect$count && + git checkout -B derived && + git commit --allow-empty -m "Derived #$count" && + git rev-parse HEAD >derived$count && + git checkout -B base $E || exit 1 + done + + for count in 1 2 3 + do + git merge-base --fork-point base $(cat derived$count) >actual && + test_cmp expect$count actual || exit 1 + done + + ) && + # check that we correctly default to HEAD + git checkout derived && + git merge-base --fork-point base >actual && + test_cmp expect3 actual +' + +test_expect_success '--fork-point works with empty reflog' ' + git -c core.logallrefupdates=false branch no-reflog base && + git merge-base --fork-point no-reflog derived && + test_cmp expect3 actual +' + +test_expect_success 'merge-base --octopus --all for complex tree' ' + # Best common ancestor for JE, JAA and JDD is JC + # JE + # / | + # / | + # / | + # JAA / | + # |\ / | + # | \ | JDD | + # | \ |/ | | + # | JC JD | + # | | /| | + # | |/ | | + # JA | | | + # |\ /| | | + # X JB | X X + # \ \ | / / + # \__\|/___/ + # J + test_commit J && + test_commit JB && + git reset --hard J && + test_commit JC && + git reset --hard J && + test_commit JTEMP1 && + test_merge JA JB && + test_merge JAA JC && + git reset --hard J && + test_commit JTEMP2 && + test_merge JD JB && + test_merge JDD JC && + git reset --hard J && + test_commit JTEMP3 && + test_merge JE JC && + git rev-parse JC >expected && + git merge-base --all --octopus JAA JDD JE >actual && + test_cmp expected actual +' + +test_done |