1#!/bin/sh 2 3test_description='split commit graph' 4. ./test-lib.sh 5 6GIT_TEST_COMMIT_GRAPH=0 7GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0 8 9test_expect_success 'setup repo' ' 10 git init && 11 git config core.commitGraph true && 12 git config gc.writeCommitGraph false && 13 infodir=".git/objects/info" && 14 graphdir="$infodir/commit-graphs" && 15 test_oid_cache <<-EOM 16 shallow sha1:2132 17 shallow sha256:2436 18 19 base sha1:1408 20 base sha256:1528 21 22 oid_version sha1:1 23 oid_version sha256:2 24 EOM 25' 26 27graph_read_expect() { 28 NUM_BASE=0 29 if test ! -z $2 30 then 31 NUM_BASE=$2 32 fi 33 cat >expect <<- EOF 34 header: 43475048 1 $(test_oid oid_version) 4 $NUM_BASE 35 num_commits: $1 36 chunks: oid_fanout oid_lookup commit_metadata generation_data 37 EOF 38 test-tool read-graph >output && 39 test_cmp expect output 40} 41 42test_expect_success POSIXPERM 'tweak umask for modebit tests' ' 43 umask 022 44' 45 46test_expect_success 'create commits and write commit-graph' ' 47 for i in $(test_seq 3) 48 do 49 test_commit $i && 50 git branch commits/$i || return 1 51 done && 52 git commit-graph write --reachable && 53 test_path_is_file $infodir/commit-graph && 54 graph_read_expect 3 55' 56 57graph_git_two_modes() { 58 git ${2:+ -C "$2"} -c core.commitGraph=true $1 >output && 59 git ${2:+ -C "$2"} -c core.commitGraph=false $1 >expect && 60 test_cmp expect output 61} 62 63graph_git_behavior() { 64 MSG=$1 65 BRANCH=$2 66 COMPARE=$3 67 DIR=$4 68 test_expect_success "check normal git operations: $MSG" ' 69 graph_git_two_modes "log --oneline $BRANCH" "$DIR" && 70 graph_git_two_modes "log --topo-order $BRANCH" "$DIR" && 71 graph_git_two_modes "log --graph $COMPARE..$BRANCH" "$DIR" && 72 graph_git_two_modes "branch -vv" "$DIR" && 73 graph_git_two_modes "merge-base -a $BRANCH $COMPARE" "$DIR" 74 ' 75} 76 77graph_git_behavior 'graph exists' commits/3 commits/1 78 79verify_chain_files_exist() { 80 for hash in $(cat $1/commit-graph-chain) 81 do 82 test_path_is_file $1/graph-$hash.graph || return 1 83 done 84} 85 86test_expect_success 'add more commits, and write a new base graph' ' 87 git reset --hard commits/1 && 88 for i in $(test_seq 4 5) 89 do 90 test_commit $i && 91 git branch commits/$i || return 1 92 done && 93 git reset --hard commits/2 && 94 for i in $(test_seq 6 10) 95 do 96 test_commit $i && 97 git branch commits/$i || return 1 98 done && 99 git reset --hard commits/2 && 100 git merge commits/4 && 101 git branch merge/1 && 102 git reset --hard commits/4 && 103 git merge commits/6 && 104 git branch merge/2 && 105 git commit-graph write --reachable && 106 graph_read_expect 12 107' 108 109test_expect_success 'fork and fail to base a chain on a commit-graph file' ' 110 test_when_finished rm -rf fork && 111 git clone . fork && 112 ( 113 cd fork && 114 rm .git/objects/info/commit-graph && 115 echo "$(pwd)/../.git/objects" >.git/objects/info/alternates && 116 test_commit new-commit && 117 git commit-graph write --reachable --split && 118 test_path_is_file $graphdir/commit-graph-chain && 119 test_line_count = 1 $graphdir/commit-graph-chain && 120 verify_chain_files_exist $graphdir 121 ) 122' 123 124test_expect_success 'add three more commits, write a tip graph' ' 125 git reset --hard commits/3 && 126 git merge merge/1 && 127 git merge commits/5 && 128 git merge merge/2 && 129 git branch merge/3 && 130 git commit-graph write --reachable --split && 131 test_path_is_missing $infodir/commit-graph && 132 test_path_is_file $graphdir/commit-graph-chain && 133 ls $graphdir/graph-*.graph >graph-files && 134 test_line_count = 2 graph-files && 135 verify_chain_files_exist $graphdir 136' 137 138graph_git_behavior 'split commit-graph: merge 3 vs 2' merge/3 merge/2 139 140test_expect_success 'add one commit, write a tip graph' ' 141 test_commit 11 && 142 git branch commits/11 && 143 git commit-graph write --reachable --split && 144 test_path_is_missing $infodir/commit-graph && 145 test_path_is_file $graphdir/commit-graph-chain && 146 ls $graphdir/graph-*.graph >graph-files && 147 test_line_count = 3 graph-files && 148 verify_chain_files_exist $graphdir 149' 150 151graph_git_behavior 'three-layer commit-graph: commit 11 vs 6' commits/11 commits/6 152 153test_expect_success 'add one commit, write a merged graph' ' 154 test_commit 12 && 155 git branch commits/12 && 156 git commit-graph write --reachable --split && 157 test_path_is_file $graphdir/commit-graph-chain && 158 test_line_count = 2 $graphdir/commit-graph-chain && 159 ls $graphdir/graph-*.graph >graph-files && 160 test_line_count = 2 graph-files && 161 verify_chain_files_exist $graphdir 162' 163 164graph_git_behavior 'merged commit-graph: commit 12 vs 6' commits/12 commits/6 165 166test_expect_success 'create fork and chain across alternate' ' 167 git clone . fork && 168 ( 169 cd fork && 170 git config core.commitGraph true && 171 rm -rf $graphdir && 172 echo "$(pwd)/../.git/objects" >.git/objects/info/alternates && 173 test_commit 13 && 174 git branch commits/13 && 175 git commit-graph write --reachable --split && 176 test_path_is_file $graphdir/commit-graph-chain && 177 test_line_count = 3 $graphdir/commit-graph-chain && 178 ls $graphdir/graph-*.graph >graph-files && 179 test_line_count = 1 graph-files && 180 git -c core.commitGraph=true rev-list HEAD >expect && 181 git -c core.commitGraph=false rev-list HEAD >actual && 182 test_cmp expect actual && 183 test_commit 14 && 184 git commit-graph write --reachable --split --object-dir=.git/objects/ && 185 test_line_count = 3 $graphdir/commit-graph-chain && 186 ls $graphdir/graph-*.graph >graph-files && 187 test_line_count = 1 graph-files 188 ) 189' 190 191if test -d fork 192then 193 graph_git_behavior 'alternate: commit 13 vs 6' commits/13 origin/commits/6 "fork" 194fi 195 196test_expect_success 'test merge stragety constants' ' 197 git clone . merge-2 && 198 ( 199 cd merge-2 && 200 git config core.commitGraph true && 201 test_line_count = 2 $graphdir/commit-graph-chain && 202 test_commit 14 && 203 git commit-graph write --reachable --split --size-multiple=2 && 204 test_line_count = 3 $graphdir/commit-graph-chain 205 206 ) && 207 git clone . merge-10 && 208 ( 209 cd merge-10 && 210 git config core.commitGraph true && 211 test_line_count = 2 $graphdir/commit-graph-chain && 212 test_commit 14 && 213 git commit-graph write --reachable --split --size-multiple=10 && 214 test_line_count = 1 $graphdir/commit-graph-chain && 215 ls $graphdir/graph-*.graph >graph-files && 216 test_line_count = 1 graph-files 217 ) && 218 git clone . merge-10-expire && 219 ( 220 cd merge-10-expire && 221 git config core.commitGraph true && 222 test_line_count = 2 $graphdir/commit-graph-chain && 223 test_commit 15 && 224 touch $graphdir/to-delete.graph $graphdir/to-keep.graph && 225 test-tool chmtime =1546362000 $graphdir/to-delete.graph && 226 test-tool chmtime =1546362001 $graphdir/to-keep.graph && 227 git commit-graph write --reachable --split --size-multiple=10 \ 228 --expire-time="2019-01-01 12:00 -05:00" && 229 test_line_count = 1 $graphdir/commit-graph-chain && 230 test_path_is_missing $graphdir/to-delete.graph && 231 test_path_is_file $graphdir/to-keep.graph && 232 ls $graphdir/graph-*.graph >graph-files && 233 test_line_count = 3 graph-files 234 ) && 235 git clone --no-hardlinks . max-commits && 236 ( 237 cd max-commits && 238 git config core.commitGraph true && 239 test_line_count = 2 $graphdir/commit-graph-chain && 240 test_commit 16 && 241 test_commit 17 && 242 git commit-graph write --reachable --split --max-commits=1 && 243 test_line_count = 1 $graphdir/commit-graph-chain && 244 ls $graphdir/graph-*.graph >graph-files && 245 test_line_count = 1 graph-files 246 ) 247' 248 249test_expect_success 'remove commit-graph-chain file after flattening' ' 250 git clone . flatten && 251 ( 252 cd flatten && 253 test_line_count = 2 $graphdir/commit-graph-chain && 254 git commit-graph write --reachable && 255 test_path_is_missing $graphdir/commit-graph-chain && 256 ls $graphdir >graph-files && 257 test_line_count = 0 graph-files 258 ) 259' 260 261corrupt_file() { 262 file=$1 263 pos=$2 264 data="${3:-\0}" 265 chmod a+w "$file" && 266 printf "$data" | dd of="$file" bs=1 seek="$pos" conv=notrunc 267} 268 269test_expect_success 'verify hashes along chain, even in shallow' ' 270 git clone --no-hardlinks . verify && 271 ( 272 cd verify && 273 git commit-graph verify && 274 base_file=$graphdir/graph-$(head -n 1 $graphdir/commit-graph-chain).graph && 275 corrupt_file "$base_file" $(test_oid shallow) "\01" && 276 test_must_fail git commit-graph verify --shallow 2>test_err && 277 grep -v "^+" test_err >err && 278 test_i18ngrep "incorrect checksum" err 279 ) 280' 281 282test_expect_success 'verify --shallow does not check base contents' ' 283 git clone --no-hardlinks . verify-shallow && 284 ( 285 cd verify-shallow && 286 git commit-graph verify && 287 base_file=$graphdir/graph-$(head -n 1 $graphdir/commit-graph-chain).graph && 288 corrupt_file "$base_file" 1000 "\01" && 289 git commit-graph verify --shallow && 290 test_must_fail git commit-graph verify 2>test_err && 291 grep -v "^+" test_err >err && 292 test_i18ngrep "incorrect checksum" err 293 ) 294' 295 296test_expect_success 'warn on base graph chunk incorrect' ' 297 git clone --no-hardlinks . base-chunk && 298 ( 299 cd base-chunk && 300 git commit-graph verify && 301 base_file=$graphdir/graph-$(tail -n 1 $graphdir/commit-graph-chain).graph && 302 corrupt_file "$base_file" $(test_oid base) "\01" && 303 git commit-graph verify --shallow 2>test_err && 304 grep -v "^+" test_err >err && 305 test_i18ngrep "commit-graph chain does not match" err 306 ) 307' 308 309test_expect_success 'verify after commit-graph-chain corruption' ' 310 git clone --no-hardlinks . verify-chain && 311 ( 312 cd verify-chain && 313 corrupt_file "$graphdir/commit-graph-chain" 60 "G" && 314 git commit-graph verify 2>test_err && 315 grep -v "^+" test_err >err && 316 test_i18ngrep "invalid commit-graph chain" err && 317 corrupt_file "$graphdir/commit-graph-chain" 60 "A" && 318 git commit-graph verify 2>test_err && 319 grep -v "^+" test_err >err && 320 test_i18ngrep "unable to find all commit-graph files" err 321 ) 322' 323 324test_expect_success 'verify across alternates' ' 325 git clone --no-hardlinks . verify-alt && 326 ( 327 cd verify-alt && 328 rm -rf $graphdir && 329 altdir="$(pwd)/../.git/objects" && 330 echo "$altdir" >.git/objects/info/alternates && 331 git commit-graph verify --object-dir="$altdir/" && 332 test_commit extra && 333 git commit-graph write --reachable --split && 334 tip_file=$graphdir/graph-$(tail -n 1 $graphdir/commit-graph-chain).graph && 335 corrupt_file "$tip_file" 100 "\01" && 336 test_must_fail git commit-graph verify --shallow 2>test_err && 337 grep -v "^+" test_err >err && 338 test_i18ngrep "commit-graph has incorrect fanout value" err 339 ) 340' 341 342test_expect_success 'add octopus merge' ' 343 git reset --hard commits/10 && 344 git merge commits/3 commits/4 && 345 git branch merge/octopus && 346 git commit-graph write --reachable --split && 347 git commit-graph verify --progress 2>err && 348 test_line_count = 3 err && 349 test_i18ngrep ! warning err && 350 test_line_count = 3 $graphdir/commit-graph-chain 351' 352 353graph_git_behavior 'graph exists' merge/octopus commits/12 354 355test_expect_success 'split across alternate where alternate is not split' ' 356 git commit-graph write --reachable && 357 test_path_is_file .git/objects/info/commit-graph && 358 cp .git/objects/info/commit-graph . && 359 git clone --no-hardlinks . alt-split && 360 ( 361 cd alt-split && 362 rm -f .git/objects/info/commit-graph && 363 echo "$(pwd)"/../.git/objects >.git/objects/info/alternates && 364 test_commit 18 && 365 git commit-graph write --reachable --split && 366 test_line_count = 1 $graphdir/commit-graph-chain 367 ) && 368 test_cmp commit-graph .git/objects/info/commit-graph 369' 370 371test_expect_success '--split=no-merge always writes an incremental' ' 372 test_when_finished rm -rf a b && 373 rm -rf $graphdir $infodir/commit-graph && 374 git reset --hard commits/2 && 375 git rev-list HEAD~1 >a && 376 git rev-list HEAD >b && 377 git commit-graph write --split --stdin-commits <a && 378 git commit-graph write --split=no-merge --stdin-commits <b && 379 test_line_count = 2 $graphdir/commit-graph-chain 380' 381 382test_expect_success '--split=replace replaces the chain' ' 383 rm -rf $graphdir $infodir/commit-graph && 384 git reset --hard commits/3 && 385 git rev-list -1 HEAD~2 >a && 386 git rev-list -1 HEAD~1 >b && 387 git rev-list -1 HEAD >c && 388 git commit-graph write --split=no-merge --stdin-commits <a && 389 git commit-graph write --split=no-merge --stdin-commits <b && 390 git commit-graph write --split=no-merge --stdin-commits <c && 391 test_line_count = 3 $graphdir/commit-graph-chain && 392 git commit-graph write --stdin-commits --split=replace <b && 393 test_path_is_missing $infodir/commit-graph && 394 test_path_is_file $graphdir/commit-graph-chain && 395 ls $graphdir/graph-*.graph >graph-files && 396 test_line_count = 1 graph-files && 397 verify_chain_files_exist $graphdir && 398 graph_read_expect 2 399' 400 401test_expect_success ULIMIT_FILE_DESCRIPTORS 'handles file descriptor exhaustion' ' 402 git init ulimit && 403 ( 404 cd ulimit && 405 for i in $(test_seq 64) 406 do 407 test_commit $i && 408 run_with_limited_open_files test_might_fail git commit-graph write \ 409 --split=no-merge --reachable || return 1 410 done 411 ) 412' 413 414while read mode modebits 415do 416 test_expect_success POSIXPERM "split commit-graph respects core.sharedrepository $mode" ' 417 rm -rf $graphdir $infodir/commit-graph && 418 git reset --hard commits/1 && 419 test_config core.sharedrepository "$mode" && 420 git commit-graph write --split --reachable && 421 ls $graphdir/graph-*.graph >graph-files && 422 test_line_count = 1 graph-files && 423 echo "$modebits" >expect && 424 test_modebits $graphdir/graph-*.graph >actual && 425 test_cmp expect actual && 426 test_modebits $graphdir/commit-graph-chain >actual && 427 test_cmp expect actual 428 ' 429done <<\EOF 4300666 -r--r--r-- 4310600 -r-------- 432EOF 433 434test_expect_success '--split=replace with partial Bloom data' ' 435 rm -rf $graphdir $infodir/commit-graph && 436 git reset --hard commits/3 && 437 git rev-list -1 HEAD~2 >a && 438 git rev-list -1 HEAD~1 >b && 439 git commit-graph write --split=no-merge --stdin-commits --changed-paths <a && 440 git commit-graph write --split=no-merge --stdin-commits <b && 441 git commit-graph write --split=replace --stdin-commits --changed-paths <c && 442 ls $graphdir/graph-*.graph >graph-files && 443 test_line_count = 1 graph-files && 444 verify_chain_files_exist $graphdir 445' 446 447test_expect_success 'prevent regression for duplicate commits across layers' ' 448 git init dup && 449 git -C dup commit --allow-empty -m one && 450 git -C dup -c core.commitGraph=false commit-graph write --split=no-merge --reachable 2>err && 451 test_i18ngrep "attempting to write a commit-graph" err && 452 git -C dup commit-graph write --split=no-merge --reachable && 453 git -C dup commit --allow-empty -m two && 454 git -C dup commit-graph write --split=no-merge --reachable && 455 git -C dup commit --allow-empty -m three && 456 git -C dup commit-graph write --split --reachable && 457 git -C dup commit-graph verify 458' 459 460NUM_FIRST_LAYER_COMMITS=64 461NUM_SECOND_LAYER_COMMITS=16 462NUM_THIRD_LAYER_COMMITS=7 463NUM_FOURTH_LAYER_COMMITS=8 464NUM_FIFTH_LAYER_COMMITS=16 465SECOND_LAYER_SEQUENCE_START=$(($NUM_FIRST_LAYER_COMMITS + 1)) 466SECOND_LAYER_SEQUENCE_END=$(($SECOND_LAYER_SEQUENCE_START + $NUM_SECOND_LAYER_COMMITS - 1)) 467THIRD_LAYER_SEQUENCE_START=$(($SECOND_LAYER_SEQUENCE_END + 1)) 468THIRD_LAYER_SEQUENCE_END=$(($THIRD_LAYER_SEQUENCE_START + $NUM_THIRD_LAYER_COMMITS - 1)) 469FOURTH_LAYER_SEQUENCE_START=$(($THIRD_LAYER_SEQUENCE_END + 1)) 470FOURTH_LAYER_SEQUENCE_END=$(($FOURTH_LAYER_SEQUENCE_START + $NUM_FOURTH_LAYER_COMMITS - 1)) 471FIFTH_LAYER_SEQUENCE_START=$(($FOURTH_LAYER_SEQUENCE_END + 1)) 472FIFTH_LAYER_SEQUENCE_END=$(($FIFTH_LAYER_SEQUENCE_START + $NUM_FIFTH_LAYER_COMMITS - 1)) 473 474# Current split graph chain: 475# 476# 16 commits (No GDAT) 477# ------------------------ 478# 64 commits (GDAT) 479# 480test_expect_success 'setup repo for mixed generation commit-graph-chain' ' 481 graphdir=".git/objects/info/commit-graphs" && 482 test_oid_cache <<-EOF && 483 oid_version sha1:1 484 oid_version sha256:2 485 EOF 486 git init mixed && 487 ( 488 cd mixed && 489 git config core.commitGraph true && 490 git config gc.writeCommitGraph false && 491 for i in $(test_seq $NUM_FIRST_LAYER_COMMITS) 492 do 493 test_commit $i && 494 git branch commits/$i || return 1 495 done && 496 git -c commitGraph.generationVersion=2 commit-graph write --reachable --split && 497 graph_read_expect $NUM_FIRST_LAYER_COMMITS && 498 test_line_count = 1 $graphdir/commit-graph-chain && 499 for i in $(test_seq $SECOND_LAYER_SEQUENCE_START $SECOND_LAYER_SEQUENCE_END) 500 do 501 test_commit $i && 502 git branch commits/$i || return 1 503 done && 504 git -c commitGraph.generationVersion=1 commit-graph write --reachable --split=no-merge && 505 test_line_count = 2 $graphdir/commit-graph-chain && 506 test-tool read-graph >output && 507 cat >expect <<-EOF && 508 header: 43475048 1 $(test_oid oid_version) 4 1 509 num_commits: $NUM_SECOND_LAYER_COMMITS 510 chunks: oid_fanout oid_lookup commit_metadata 511 EOF 512 test_cmp expect output && 513 git commit-graph verify && 514 cat $graphdir/commit-graph-chain 515 ) 516' 517 518# The new layer will be added without generation data chunk as it was not 519# present on the layer underneath it. 520# 521# 7 commits (No GDAT) 522# ------------------------ 523# 16 commits (No GDAT) 524# ------------------------ 525# 64 commits (GDAT) 526# 527test_expect_success 'do not write generation data chunk if not present on existing tip' ' 528 git clone mixed mixed-no-gdat && 529 ( 530 cd mixed-no-gdat && 531 for i in $(test_seq $THIRD_LAYER_SEQUENCE_START $THIRD_LAYER_SEQUENCE_END) 532 do 533 test_commit $i && 534 git branch commits/$i || return 1 535 done && 536 git commit-graph write --reachable --split=no-merge && 537 test_line_count = 3 $graphdir/commit-graph-chain && 538 test-tool read-graph >output && 539 cat >expect <<-EOF && 540 header: 43475048 1 $(test_oid oid_version) 4 2 541 num_commits: $NUM_THIRD_LAYER_COMMITS 542 chunks: oid_fanout oid_lookup commit_metadata 543 EOF 544 test_cmp expect output && 545 git commit-graph verify 546 ) 547' 548 549# Number of commits in each layer of the split-commit graph before merge: 550# 551# 8 commits (No GDAT) 552# ------------------------ 553# 7 commits (No GDAT) 554# ------------------------ 555# 16 commits (No GDAT) 556# ------------------------ 557# 64 commits (GDAT) 558# 559# The top two layers are merged and do not have generation data chunk as layer below them does 560# not have generation data chunk. 561# 562# 15 commits (No GDAT) 563# ------------------------ 564# 16 commits (No GDAT) 565# ------------------------ 566# 64 commits (GDAT) 567# 568test_expect_success 'do not write generation data chunk if the topmost remaining layer does not have generation data chunk' ' 569 git clone mixed-no-gdat mixed-merge-no-gdat && 570 ( 571 cd mixed-merge-no-gdat && 572 for i in $(test_seq $FOURTH_LAYER_SEQUENCE_START $FOURTH_LAYER_SEQUENCE_END) 573 do 574 test_commit $i && 575 git branch commits/$i || return 1 576 done && 577 git commit-graph write --reachable --split --size-multiple 1 && 578 test_line_count = 3 $graphdir/commit-graph-chain && 579 test-tool read-graph >output && 580 cat >expect <<-EOF && 581 header: 43475048 1 $(test_oid oid_version) 4 2 582 num_commits: $(($NUM_THIRD_LAYER_COMMITS + $NUM_FOURTH_LAYER_COMMITS)) 583 chunks: oid_fanout oid_lookup commit_metadata 584 EOF 585 test_cmp expect output && 586 git commit-graph verify 587 ) 588' 589 590# Number of commits in each layer of the split-commit graph before merge: 591# 592# 16 commits (No GDAT) 593# ------------------------ 594# 15 commits (No GDAT) 595# ------------------------ 596# 16 commits (No GDAT) 597# ------------------------ 598# 64 commits (GDAT) 599# 600# The top three layers are merged and has generation data chunk as the topmost remaining layer 601# has generation data chunk. 602# 603# 47 commits (GDAT) 604# ------------------------ 605# 64 commits (GDAT) 606# 607test_expect_success 'write generation data chunk if topmost remaining layer has generation data chunk' ' 608 git clone mixed-merge-no-gdat mixed-merge-gdat && 609 ( 610 cd mixed-merge-gdat && 611 for i in $(test_seq $FIFTH_LAYER_SEQUENCE_START $FIFTH_LAYER_SEQUENCE_END) 612 do 613 test_commit $i && 614 git branch commits/$i || return 1 615 done && 616 git commit-graph write --reachable --split --size-multiple 1 && 617 test_line_count = 2 $graphdir/commit-graph-chain && 618 test-tool read-graph >output && 619 cat >expect <<-EOF && 620 header: 43475048 1 $(test_oid oid_version) 5 1 621 num_commits: $(($NUM_SECOND_LAYER_COMMITS + $NUM_THIRD_LAYER_COMMITS + $NUM_FOURTH_LAYER_COMMITS + $NUM_FIFTH_LAYER_COMMITS)) 622 chunks: oid_fanout oid_lookup commit_metadata generation_data 623 EOF 624 test_cmp expect output 625 ) 626' 627 628test_expect_success 'write generation data chunk when commit-graph chain is replaced' ' 629 git clone mixed mixed-replace && 630 ( 631 cd mixed-replace && 632 git commit-graph write --reachable --split=replace && 633 test_path_is_file $graphdir/commit-graph-chain && 634 test_line_count = 1 $graphdir/commit-graph-chain && 635 verify_chain_files_exist $graphdir && 636 graph_read_expect $(($NUM_FIRST_LAYER_COMMITS + $NUM_SECOND_LAYER_COMMITS)) && 637 git commit-graph verify 638 ) 639' 640 641test_done 642