From 01e9d129396e98b611bff2ae82bb3d610b28c588 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Thu, 15 Aug 2024 13:31:00 -0400 Subject: [PATCH 1/8] pack-bitmap: initialize `bitmap_writer_init()` with packing_data In order to determine its object order, the pack-bitmap machinery keeps a 'struct packing_data' corresponding to the pack or pseudo-pack (when writing a MIDX bitmap) being written. The to_pack field is provided to the bitmap machinery by callers of bitmap_writer_build() and assigned to the bitmap_writer struct at that point. But a subsequent commit will want to have access to that data earlier on during commit selection. Prepare for that by adding a 'to_pack' argument to 'bitmap_writer_init()', and initializing the field during that function. Subsequent commits will clean up other functions which take now-redundant arguments (like nr_objects, which is equivalent to pdata->objects_nr, or pdata itself). Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- builtin/pack-objects.c | 2 +- midx-write.c | 2 +- pack-bitmap-write.c | 4 +++- pack-bitmap.h | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index f395488971..0ad533c045 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1342,7 +1342,7 @@ static void write_pack_file(void) if (write_bitmap_index) { bitmap_writer_init(&bitmap_writer, - the_repository); + the_repository, &to_pack); bitmap_writer_set_checksum(&bitmap_writer, hash); bitmap_writer_build_type_index(&bitmap_writer, &to_pack, written_list, nr_written); diff --git a/midx-write.c b/midx-write.c index a77ee73c68..62f507eb72 100644 --- a/midx-write.c +++ b/midx-write.c @@ -825,7 +825,7 @@ static int write_midx_bitmap(const char *midx_name, for (i = 0; i < pdata->nr_objects; i++) index[i] = &pdata->objects[i].idx; - bitmap_writer_init(&writer, the_repository); + bitmap_writer_init(&writer, the_repository, pdata); bitmap_writer_show_progress(&writer, flags & MIDX_PROGRESS); bitmap_writer_build_type_index(&writer, pdata, index, pdata->nr_objects); diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c index bf96c80898..4a7d2d1370 100644 --- a/pack-bitmap-write.c +++ b/pack-bitmap-write.c @@ -41,13 +41,15 @@ static inline int bitmap_writer_nr_selected_commits(struct bitmap_writer *writer return writer->selected_nr - writer->pseudo_merges_nr; } -void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r) +void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r, + struct packing_data *pdata) { memset(writer, 0, sizeof(struct bitmap_writer)); if (writer->bitmaps) BUG("bitmap writer already initialized"); writer->bitmaps = kh_init_oid_map(); writer->pseudo_merge_commits = kh_init_oid_map(); + writer->to_pack = pdata; string_list_init_dup(&writer->pseudo_merge_groups); diff --git a/pack-bitmap.h b/pack-bitmap.h index 1171e6d989..ab20d6a0b6 100644 --- a/pack-bitmap.h +++ b/pack-bitmap.h @@ -123,7 +123,8 @@ struct bitmap_writer { unsigned char pack_checksum[GIT_MAX_RAWSZ]; }; -void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r); +void bitmap_writer_init(struct bitmap_writer *writer, struct repository *r, + struct packing_data *pdata); void bitmap_writer_show_progress(struct bitmap_writer *writer, int show); void bitmap_writer_set_checksum(struct bitmap_writer *writer, const unsigned char *sha1); From 125ee4ae80e3661c3208fc1c8db0c619e5f625d2 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Thu, 15 Aug 2024 13:31:03 -0400 Subject: [PATCH 2/8] pack-bitmap: drop redundant args from `bitmap_writer_build_type_index()` The previous commit ensures that the bitmap_writer's "to_pack" field is initialized early on, so the "to_pack" and "index_nr" arguments to `bitmap_writer_build_type_index()` are redundant. Drop them and adjust the callers accordingly. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- builtin/pack-objects.c | 2 +- midx-write.c | 3 +-- pack-bitmap-write.c | 12 +++++------- pack-bitmap.h | 4 +--- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 0ad533c045..c08a62718d 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1345,7 +1345,7 @@ static void write_pack_file(void) the_repository, &to_pack); bitmap_writer_set_checksum(&bitmap_writer, hash); bitmap_writer_build_type_index(&bitmap_writer, - &to_pack, written_list, nr_written); + written_list); } if (cruft) diff --git a/midx-write.c b/midx-write.c index 62f507eb72..b3015af07f 100644 --- a/midx-write.c +++ b/midx-write.c @@ -827,8 +827,7 @@ static int write_midx_bitmap(const char *midx_name, bitmap_writer_init(&writer, the_repository, pdata); bitmap_writer_show_progress(&writer, flags & MIDX_PROGRESS); - bitmap_writer_build_type_index(&writer, pdata, index, - pdata->nr_objects); + bitmap_writer_build_type_index(&writer, index); /* * bitmap_writer_finish expects objects in lex order, but pack_order diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c index 4a7d2d1370..34cdf5f150 100644 --- a/pack-bitmap-write.c +++ b/pack-bitmap-write.c @@ -101,9 +101,7 @@ void bitmap_writer_show_progress(struct bitmap_writer *writer, int show) * Build the initial type index for the packfile or multi-pack-index */ void bitmap_writer_build_type_index(struct bitmap_writer *writer, - struct packing_data *to_pack, - struct pack_idx_entry **index, - uint32_t index_nr) + struct pack_idx_entry **index) { uint32_t i; @@ -111,13 +109,13 @@ void bitmap_writer_build_type_index(struct bitmap_writer *writer, writer->trees = ewah_new(); writer->blobs = ewah_new(); writer->tags = ewah_new(); - ALLOC_ARRAY(to_pack->in_pack_pos, to_pack->nr_objects); + ALLOC_ARRAY(writer->to_pack->in_pack_pos, writer->to_pack->nr_objects); - for (i = 0; i < index_nr; ++i) { + for (i = 0; i < writer->to_pack->nr_objects; ++i) { struct object_entry *entry = (struct object_entry *)index[i]; enum object_type real_type; - oe_set_in_pack_pos(to_pack, entry, i); + oe_set_in_pack_pos(writer->to_pack, entry, i); switch (oe_type(entry)) { case OBJ_COMMIT: @@ -128,7 +126,7 @@ void bitmap_writer_build_type_index(struct bitmap_writer *writer, break; default: - real_type = oid_object_info(to_pack->repo, + real_type = oid_object_info(writer->to_pack->repo, &entry->idx.oid, NULL); break; } diff --git a/pack-bitmap.h b/pack-bitmap.h index ab20d6a0b6..d2529abadc 100644 --- a/pack-bitmap.h +++ b/pack-bitmap.h @@ -129,9 +129,7 @@ void bitmap_writer_show_progress(struct bitmap_writer *writer, int show); void bitmap_writer_set_checksum(struct bitmap_writer *writer, const unsigned char *sha1); void bitmap_writer_build_type_index(struct bitmap_writer *writer, - struct packing_data *to_pack, - struct pack_idx_entry **index, - uint32_t index_nr); + struct pack_idx_entry **index); int bitmap_writer_has_bitmapped_object_id(struct bitmap_writer *writer, const struct object_id *oid); void bitmap_writer_push_commit(struct bitmap_writer *writer, From f00dda48490c1d5d515cc97b5b3197c0ed1c7ed9 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Thu, 15 Aug 2024 13:31:06 -0400 Subject: [PATCH 3/8] pack-bitmap: drop redundant args from `bitmap_writer_build()` In a similar fashion as the previous commit, drop a redundant argument from the `bitmap_writer_build()` function. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- builtin/pack-objects.c | 2 +- midx-write.c | 2 +- pack-bitmap-write.c | 9 +++------ pack-bitmap.h | 3 +-- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index c08a62718d..97090433a1 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1367,7 +1367,7 @@ static void write_pack_file(void) bitmap_writer_select_commits(&bitmap_writer, indexed_commits, indexed_commits_nr); - if (bitmap_writer_build(&bitmap_writer, &to_pack) < 0) + if (bitmap_writer_build(&bitmap_writer) < 0) die(_("failed to write bitmap index")); bitmap_writer_finish(&bitmap_writer, written_list, nr_written, diff --git a/midx-write.c b/midx-write.c index b3015af07f..1ccdf0df30 100644 --- a/midx-write.c +++ b/midx-write.c @@ -846,7 +846,7 @@ static int write_midx_bitmap(const char *midx_name, index[pack_order[i]] = &pdata->objects[i].idx; bitmap_writer_select_commits(&writer, commits, commits_nr); - ret = bitmap_writer_build(&writer, pdata); + ret = bitmap_writer_build(&writer); if (ret < 0) goto cleanup; diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c index 34cdf5f150..8d7437955d 100644 --- a/pack-bitmap-write.c +++ b/pack-bitmap-write.c @@ -569,8 +569,7 @@ static void store_selected(struct bitmap_writer *writer, kh_value(writer->bitmaps, hash_pos) = stored; } -int bitmap_writer_build(struct bitmap_writer *writer, - struct packing_data *to_pack) +int bitmap_writer_build(struct bitmap_writer *writer) { struct bitmap_builder bb; size_t i; @@ -581,17 +580,15 @@ int bitmap_writer_build(struct bitmap_writer *writer, uint32_t *mapping; int closed = 1; /* until proven otherwise */ - writer->to_pack = to_pack; - if (writer->show_progress) writer->progress = start_progress("Building bitmaps", writer->selected_nr); trace2_region_enter("pack-bitmap-write", "building_bitmaps_total", the_repository); - old_bitmap = prepare_bitmap_git(to_pack->repo); + old_bitmap = prepare_bitmap_git(writer->to_pack->repo); if (old_bitmap) - mapping = create_bitmap_mapping(old_bitmap, to_pack); + mapping = create_bitmap_mapping(old_bitmap, writer->to_pack); else mapping = NULL; diff --git a/pack-bitmap.h b/pack-bitmap.h index d2529abadc..0c5b83e954 100644 --- a/pack-bitmap.h +++ b/pack-bitmap.h @@ -146,8 +146,7 @@ struct ewah_bitmap *pseudo_merge_bitmap_for_commit(struct bitmap_index *bitmap_g void bitmap_writer_select_commits(struct bitmap_writer *writer, struct commit **indexed_commits, unsigned int indexed_commits_nr); -int bitmap_writer_build(struct bitmap_writer *writer, - struct packing_data *to_pack); +int bitmap_writer_build(struct bitmap_writer *writer); void bitmap_writer_finish(struct bitmap_writer *writer, struct pack_idx_entry **index, uint32_t index_nr, From 11a08e8332762ad0a56c7a92701d85d0d04f94a7 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Thu, 15 Aug 2024 13:31:08 -0400 Subject: [PATCH 4/8] pack-bitmap: drop redundant args from `bitmap_writer_finish()` In a similar fashion as the previous commit, drop a redundant argument from the `bitmap_writer_finish()` function. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- builtin/pack-objects.c | 2 +- midx-write.c | 3 +-- pack-bitmap-write.c | 8 ++++---- pack-bitmap.h | 1 - 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 97090433a1..e23c4950ed 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1370,7 +1370,7 @@ static void write_pack_file(void) if (bitmap_writer_build(&bitmap_writer) < 0) die(_("failed to write bitmap index")); bitmap_writer_finish(&bitmap_writer, - written_list, nr_written, + written_list, tmpname.buf, write_bitmap_options); bitmap_writer_free(&bitmap_writer); write_bitmap_index = 0; diff --git a/midx-write.c b/midx-write.c index 1ccdf0df30..d2d13447af 100644 --- a/midx-write.c +++ b/midx-write.c @@ -851,8 +851,7 @@ static int write_midx_bitmap(const char *midx_name, goto cleanup; bitmap_writer_set_checksum(&writer, midx_hash); - bitmap_writer_finish(&writer, index, pdata->nr_objects, bitmap_name, - options); + bitmap_writer_finish(&writer, index, bitmap_name, options); cleanup: free(index); diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c index 8d7437955d..346fb29513 100644 --- a/pack-bitmap-write.c +++ b/pack-bitmap-write.c @@ -998,7 +998,6 @@ void bitmap_writer_set_checksum(struct bitmap_writer *writer, void bitmap_writer_finish(struct bitmap_writer *writer, struct pack_idx_entry **index, - uint32_t index_nr, const char *filename, uint16_t options) { @@ -1031,12 +1030,13 @@ void bitmap_writer_finish(struct bitmap_writer *writer, dump_bitmap(f, writer->tags); if (options & BITMAP_OPT_LOOKUP_TABLE) - CALLOC_ARRAY(offsets, index_nr); + CALLOC_ARRAY(offsets, writer->to_pack->nr_objects); for (i = 0; i < bitmap_writer_nr_selected_commits(writer); i++) { struct bitmapped_commit *stored = &writer->selected[i]; int commit_pos = oid_pos(&stored->commit->object.oid, index, - index_nr, oid_access); + writer->to_pack->nr_objects, + oid_access); if (commit_pos < 0) BUG(_("trying to write commit not in index")); @@ -1052,7 +1052,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer, write_lookup_table(writer, f, offsets); if (options & BITMAP_OPT_HASH_CACHE) - write_hash_cache(f, index, index_nr); + write_hash_cache(f, index, writer->to_pack->nr_objects); finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, CSUM_HASH_IN_STREAM | CSUM_FSYNC | CSUM_CLOSE); diff --git a/pack-bitmap.h b/pack-bitmap.h index 0c5b83e954..ff0fd815b8 100644 --- a/pack-bitmap.h +++ b/pack-bitmap.h @@ -149,7 +149,6 @@ void bitmap_writer_select_commits(struct bitmap_writer *writer, int bitmap_writer_build(struct bitmap_writer *writer); void bitmap_writer_finish(struct bitmap_writer *writer, struct pack_idx_entry **index, - uint32_t index_nr, const char *filename, uint16_t options); void bitmap_writer_free(struct bitmap_writer *writer); From 187504f9b2b2af89c77247100b246a704c68c884 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Thu, 15 Aug 2024 13:31:12 -0400 Subject: [PATCH 5/8] pack-bitmap-write.c: select pseudo-merges even for small bitmaps Ordinarily, the pack-bitmap machinery will select some subset of reachable commits to receive bitmaps. But when there are fewer than 100 commits indexed in the first place, they will all receive bitmaps as a special case. When this happens, pseudo-merges are not generated, making it impossible to test pseudo-merge corner cases with fewer than 100 commits. Select pseudo-merges even for bitmaps with fewer than 100 commits to make such testing easier. In practice, this should not make a difference to non-testing bitmaps, as they are unlikely to be used when a repository has so few commits to begin with. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- pack-bitmap-write.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c index 346fb29513..923f793cec 100644 --- a/pack-bitmap-write.c +++ b/pack-bitmap-write.c @@ -694,6 +694,10 @@ void bitmap_writer_select_commits(struct bitmap_writer *writer, if (indexed_commits_nr < 100) { for (i = 0; i < indexed_commits_nr; ++i) bitmap_writer_push_commit(writer, indexed_commits[i], 0); + + select_pseudo_merges(writer, indexed_commits, + indexed_commits_nr); + return; } From 42f80e361c59b7afc0258e44299fa0263c4cfbaf Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Thu, 15 Aug 2024 13:31:14 -0400 Subject: [PATCH 6/8] t/t5333-pseudo-merge-bitmaps.sh: demonstrate empty pseudo-merge groups Demonstrate that it is possible to generate empty pseudo-merge commits in certain cases. In the below instance, we generate one non-empty pseudo-merge (containing commit "base"), and one empty pseudo-merge group (corresponding to the unstable commits within that group). (In my testing, the pseudo-merge machinery seems to handle empty groups just fine, but generating them is pointless as they carry no information.) This commit (introducing a deliberate "test_expect_failure") is split out from the actual fix (which will appear in the following commit) to demonstrate that the failure is correctly induced. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- t/t5333-pseudo-merge-bitmaps.sh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/t/t5333-pseudo-merge-bitmaps.sh b/t/t5333-pseudo-merge-bitmaps.sh index f052f395a7..0288691340 100755 --- a/t/t5333-pseudo-merge-bitmaps.sh +++ b/t/t5333-pseudo-merge-bitmaps.sh @@ -390,4 +390,24 @@ test_expect_success 'pseudo-merge reuse' ' ) ' +test_expect_failure 'empty pseudo-merge group' ' + git init pseudo-merge-empty-group && + ( + cd pseudo-merge-empty-group && + + # Ensure that a pseudo-merge group with no unstable + # commits does not generate an empty pseudo-merge + # bitmap. + git config bitmapPseudoMerge.empty.pattern refs/ && + + test_commit base && + git repack -adb && + + test-tool bitmap dump-pseudo-merges >merges && + test_line_count = 1 merges && + + test 0 -eq "$(grep -c commits=0 Date: Thu, 15 Aug 2024 13:31:17 -0400 Subject: [PATCH 7/8] pseudo-merge.c: do not generate empty pseudo-merge commits The previous commit demonstrated it is possible to generate empty pseudo-merge commits, which is not useful as such pseudo-merges carry no information. Ensure that we only generate non-empty groups by not pushing a new commit onto the bitmap_writer when that commit has no parents. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- pseudo-merge.c | 11 +++++++---- t/t5333-pseudo-merge-bitmaps.sh | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/pseudo-merge.c b/pseudo-merge.c index f0fde13c47..6422be979c 100644 --- a/pseudo-merge.c +++ b/pseudo-merge.c @@ -357,8 +357,10 @@ static void select_pseudo_merges_1(struct bitmap_writer *writer, p = commit_list_append(c, p); } while (j % group->stable_size); - bitmap_writer_push_commit(writer, merge, 1); - writer->pseudo_merges_nr++; + if (merge->parents) { + bitmap_writer_push_commit(writer, merge, 1); + writer->pseudo_merges_nr++; + } } /* make up to group->max_merges pseudo merges for unstable commits */ @@ -398,8 +400,9 @@ static void select_pseudo_merges_1(struct bitmap_writer *writer, p = commit_list_append(c, p); } - bitmap_writer_push_commit(writer, merge, 1); - writer->pseudo_merges_nr++; + if (merge->parents) { + bitmap_writer_push_commit(writer, merge, 1); + writer->pseudo_merges_nr++; } if (end >= matches->unstable_nr) break; } diff --git a/t/t5333-pseudo-merge-bitmaps.sh b/t/t5333-pseudo-merge-bitmaps.sh index 0288691340..aa1a7d26f1 100755 --- a/t/t5333-pseudo-merge-bitmaps.sh +++ b/t/t5333-pseudo-merge-bitmaps.sh @@ -390,7 +390,7 @@ test_expect_success 'pseudo-merge reuse' ' ) ' -test_expect_failure 'empty pseudo-merge group' ' +test_expect_success 'empty pseudo-merge group' ' git init pseudo-merge-empty-group && ( cd pseudo-merge-empty-group && From a72dfab8b8bcccee06d7bf53e5c0323e82a1765a Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Thu, 15 Aug 2024 13:31:20 -0400 Subject: [PATCH 8/8] pseudo-merge.c: ensure pseudo-merge groups are closed When generating pseudo-merge bitmaps, it's possible that concurrent reference updates may reveal some pseudo-merge candidates which reach objects that are not contained in the bitmap's pack or pseudo-pack order (in the case of MIDX bitmaps). The latter case is relatively easy to demonstrate: if we generate a MIDX bitmap with only half of the repository packed, then the unpacked contents are not part of the MIDX's object order. If we happen to select one or more commit(s) from the unpacked portion of the repository for inclusion in a pseudo-merge, we'll get the following message when trying to generate its bitmap: $ git multi-pack-index write --bitmap [...] Selecting pseudo-merge commits: 100% (1/1), done. warning: Failed to write bitmap index. Packfile doesn't have full closure (object ... is missing) Building bitmaps: 50% (1/2), done. error: could not write multi-pack bitmap , and the attempted bitmap write will fail, leaving the repository without a current bitmap. Rectify this by ensuring that the commits which are pseudo-merge candidates can only be so if they appear somewhere in the packing order. This is sufficient, since we know that the original packing order is closed under reachability, so if a commit appears in that list as a potential pseudo-merge candidate, we know that everything reachable from it also appears in the list (and thus the candidate is a good one). Noticed-by: Jeff King Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- pseudo-merge.c | 2 ++ t/t5333-pseudo-merge-bitmaps.sh | 36 +++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/pseudo-merge.c b/pseudo-merge.c index 6422be979c..7ec9d4c51c 100644 --- a/pseudo-merge.c +++ b/pseudo-merge.c @@ -217,6 +217,8 @@ static int find_pseudo_merge_group_for_ref(const char *refname, c = lookup_commit(the_repository, oid); if (!c) return 0; + if (!packlist_find(writer->to_pack, oid)) + return 0; has_bitmap = bitmap_writer_has_bitmapped_object_id(writer, oid); diff --git a/t/t5333-pseudo-merge-bitmaps.sh b/t/t5333-pseudo-merge-bitmaps.sh index aa1a7d26f1..1dd6284756 100755 --- a/t/t5333-pseudo-merge-bitmaps.sh +++ b/t/t5333-pseudo-merge-bitmaps.sh @@ -410,4 +410,40 @@ test_expect_success 'empty pseudo-merge group' ' ) ' +test_expect_success 'pseudo-merge closure' ' + git init pseudo-merge-closure && + ( + cd pseudo-merge-closure && + + test_commit A && + git repack -d && + + test_commit B && + + # Note that the contents of A is packed, but B is not. A + # (and the objects reachable from it) are thus visible + # to the MIDX, but the same is not true for B and its + # objects. + # + # Ensure that we do not attempt to create a pseudo-merge + # for B, depsite it matching the below pseudo-merge + # group pattern, as doing so would result in a failure + # to write a non-closed bitmap. + git config bitmapPseudoMerge.test.pattern refs/ && + git config bitmapPseudoMerge.test.threshold now && + + git multi-pack-index write --bitmap && + + test-tool bitmap dump-pseudo-merges >pseudo-merges && + test_line_count = 1 pseudo-merges && + + git rev-parse A >expect && + + test-tool bitmap list-commits >actual && + test_cmp expect actual && + test-tool bitmap dump-pseudo-merge-commits 0 >actual && + test_cmp expect actual + ) +' + test_done