]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'ds/commit-graph-merging-fix'
authorJunio C Hamano <gitster@pobox.com>
Mon, 2 Nov 2020 21:17:39 +0000 (13:17 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 2 Nov 2020 21:17:39 +0000 (13:17 -0800)
When "git commit-graph" detects the same commit recorded more than
once while it is merging the layers, it used to die.  The code now
ignores all but one of them and continues.

* ds/commit-graph-merging-fix:
  commit-graph: don't write commit-graph when disabled
  commit-graph: ignore duplicates when merging layers

Documentation/git-commit-graph.txt
commit-graph.c
t/t5324-split-commit-graph.sh

index de6b6de230223c2e3fd37b55827ba85265c3f052..e1f48c95b3ca37e67af88e634a44db88dd1ca6a9 100644 (file)
@@ -39,7 +39,9 @@ COMMANDS
 --------
 'write'::
 
-Write a commit-graph file based on the commits found in packfiles.
+Write a commit-graph file based on the commits found in packfiles. If
+the config option `core.commitGraph` is disabled, then this command will
+output a warning, then return success without writing a commit-graph file.
 +
 With the `--stdin-packs` option, generate the new commit graph by
 walking objects only in the specified pack-indexes. (Cannot be combined
index cb042bdba8c83288cfc1e42853447d5bc06f47fe..6f62a0731383293eb7e617f0ecda932d421757fd 100644 (file)
@@ -2008,7 +2008,7 @@ static int commit_compare(const void *_a, const void *_b)
 
 static void sort_and_scan_merged_commits(struct write_commit_graph_context *ctx)
 {
-       uint32_t i;
+       uint32_t i, dedup_i = 0;
 
        if (ctx->report_progress)
                ctx->progress = start_delayed_progress(
@@ -2023,17 +2023,27 @@ static void sort_and_scan_merged_commits(struct write_commit_graph_context *ctx)
 
                if (i && oideq(&ctx->commits.list[i - 1]->object.oid,
                          &ctx->commits.list[i]->object.oid)) {
-                       die(_("unexpected duplicate commit id %s"),
-                           oid_to_hex(&ctx->commits.list[i]->object.oid));
+                       /*
+                        * Silently ignore duplicates. These were likely
+                        * created due to a commit appearing in multiple
+                        * layers of the chain, which is unexpected but
+                        * not invalid. We should make sure there is a
+                        * unique copy in the new layer.
+                        */
                } else {
                        unsigned int num_parents;
 
+                       ctx->commits.list[dedup_i] = ctx->commits.list[i];
+                       dedup_i++;
+
                        num_parents = commit_list_count(ctx->commits.list[i]->parents);
                        if (num_parents > 2)
                                ctx->num_extra_edges += num_parents - 1;
                }
        }
 
+       ctx->commits.nr = dedup_i;
+
        stop_progress(&ctx->progress);
 }
 
@@ -2150,6 +2160,11 @@ int write_commit_graph(struct object_directory *odb,
        int replace = 0;
        struct bloom_filter_settings bloom_settings = DEFAULT_BLOOM_FILTER_SETTINGS;
 
+       prepare_repo_settings(the_repository);
+       if (!the_repository->settings.core_commit_graph) {
+               warning(_("attempting to write a commit-graph, but 'core.commitGraph' is disabled"));
+               return 0;
+       }
        if (!commit_graph_compatible(the_repository))
                return 0;
 
index c334ee9155b12c91b41ac86722e8f666e7b62d0e..4d3842b83b9456362a08842ebc10614d02f0943d 100755 (executable)
@@ -440,4 +440,17 @@ test_expect_success '--split=replace with partial Bloom data' '
        verify_chain_files_exist $graphdir
 '
 
+test_expect_success 'prevent regression for duplicate commits across layers' '
+       git init dup &&
+       git -C dup commit --allow-empty -m one &&
+       git -C dup -c core.commitGraph=false commit-graph write --split=no-merge --reachable 2>err &&
+       test_i18ngrep "attempting to write a commit-graph" err &&
+       git -C dup commit-graph write --split=no-merge --reachable &&
+       git -C dup commit --allow-empty -m two &&
+       git -C dup commit-graph write --split=no-merge --reachable &&
+       git -C dup commit --allow-empty -m three &&
+       git -C dup commit-graph write --split --reachable &&
+       git -C dup commit-graph verify
+'
+
 test_done