]> git.ipfire.org Git - thirdparty/git.git/commitdiff
builtin/refs: add '--no-reflog' flag to drop reflogs
authorKarthik Nayak <karthik.188@gmail.com>
Fri, 21 Feb 2025 10:04:23 +0000 (11:04 +0100)
committerJunio C Hamano <gitster@pobox.com>
Fri, 21 Feb 2025 17:55:02 +0000 (09:55 -0800)
The "git refs migrate" subcommand converts the backend used for ref
storage. It always migrates reflog data as well as refs. Introduce an
option to exclude reflogs from migration, allowing them to be discarded
when they are unnecessary.

This is particularly useful in server-side repositories, where reflogs
are typically not expected. However, some repositories may still have
them due to historical reasons, such as bugs, misconfigurations, or
administrative decisions to enable reflogs for debugging. In such
repositories, it would be optimal to drop reflogs during the migration.

To address this, introduce the '--no-reflog' flag, which prevents reflog
migration. When this flag is used, reflogs from the original reference
backend are migrated. Since only the new reference backend remains in
the repository, all previous reflogs are permanently discarded.

Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-refs.txt
builtin/refs.c
refs.c
refs.h
t/t1460-refs-migrate.sh

index 9829984b0a4c4f54ec7f9b6c6c7072f62b1d198d..733ada7d51715d42a9ab48c3119d2756f2b26d01 100644 (file)
@@ -8,9 +8,9 @@ git-refs - Low-level access to refs
 
 SYNOPSIS
 --------
-[verse]
-'git refs migrate' --ref-format=<format> [--dry-run]
-'git refs verify' [--strict] [--verbose]
+[synopsis]
+git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]
+git refs verify [--strict] [--verbose]
 
 DESCRIPTION
 -----------
@@ -43,6 +43,11 @@ include::ref-storage-format.txt[]
        can be used to double check that the migration works as expected before
        performing the actual migration.
 
+--reflog::
+--no-reflog::
+       Choose between migrating the reflog data to the new backend,
+       and discarding them.  The default is "--reflog", to migrate.
+
 The following options are specific to 'git refs verify':
 
 --strict::
index a29f19583474518ee0942ea53c39cbdf9661c5e2..c459507d514b37322e965207893a3335b886f824 100644 (file)
@@ -30,6 +30,9 @@ static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,
                OPT_BIT(0, "dry-run", &flags,
                        N_("perform a non-destructive dry-run"),
                        REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN),
+               OPT_BIT(0, "no-reflog", &flags,
+                       N_("drop reflogs entirely during the migration"),
+                       REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG),
                OPT_END(),
        };
        struct strbuf errbuf = STRBUF_INIT;
diff --git a/refs.c b/refs.c
index f4094a326a9f88f979654b668cc9c3d27d83cb5d..5e8f5c06fa68d16c93ee11edd9742995eea994b6 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -3035,9 +3035,11 @@ int repo_migrate_ref_storage_format(struct repository *repo,
        if (ret < 0)
                goto done;
 
-       ret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);
-       if (ret < 0)
-               goto done;
+       if (!(flags & REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG)) {
+               ret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);
+               if (ret < 0)
+                       goto done;
+       }
 
        ret = ref_transaction_commit(transaction, errbuf);
        if (ret < 0)
diff --git a/refs.h b/refs.h
index a0cdd99250e8286b55808b697b0a94afac5d8319..ccee8fc6705e6e93a1c6234e7395180f8dfd815b 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -1157,8 +1157,11 @@ int is_pseudo_ref(const char *refname);
  *   - REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN: perform a dry-run migration
  *     without touching the main repository. The result will be written into a
  *     temporary ref storage directory.
+ *
+ *   - REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG: skip migration of reflogs.
  */
-#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN (1 << 0)
+#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN      (1 << 0)
+#define REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG (1 << 1)
 
 /*
  * Migrate the ref storage format used by the repository to the
index a6d9b35a46eb59350aa0d59d982a2fbfaecf1448..2ab97e1b7dfa7e9a00004db08d0bcd511b890054 100755 (executable)
@@ -9,14 +9,21 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 
 # Migrate the provided repository from one format to the other and
 # verify that the references and logs are migrated over correctly.
-# Usage: test_migration <repo> <format> <skip_reflog_verify>
+# Usage: test_migration <repo> <format> [<skip_reflog_verify> [<options...>]]
 #   <repo> is the relative path to the repo to be migrated.
 #   <format> is the ref format to be migrated to.
-#   <skip_reflog_verify> (true or false) whether to skip reflog verification.
+#   <skip_reflog_verify> (default: false) whether to skip reflog verification.
+#   <options...> are other options be passed directly to 'git refs migrate'.
 test_migration () {
        repo=$1 &&
        format=$2 &&
-       skip_reflog_verify=${3:-false} &&
+       shift 2 &&
+       skip_reflog_verify=false &&
+       if test $# -ge 1
+       then
+               skip_reflog_verify=$1
+               shift
+       fi &&
        git -C "$repo" for-each-ref --include-root-refs \
                --format='%(refname) %(objectname) %(symref)' >expect &&
        if ! $skip_reflog_verify
@@ -25,7 +32,7 @@ test_migration () {
           git -C "$repo" reflog list >expect_log_list
        fi &&
 
-       git -C "$repo" refs migrate --ref-format="$2" &&
+       git -C "$repo" refs migrate --ref-format="$format" "$@" &&
 
        git -C "$repo" for-each-ref --include-root-refs \
                --format='%(refname) %(objectname) %(symref)' >actual &&
@@ -241,6 +248,19 @@ do
                                test_cmp expect.reflog actual.reflog
                        )
                '
+
+               test_expect_success "$from_format -> $to_format: skip reflog with --skip-reflog" '
+                       test_when_finished "rm -rf repo" &&
+                       git init --ref-format=$from_format repo &&
+                       test_commit -C repo initial &&
+                       # we see that the repository contains reflogs.
+                       git -C repo reflog --all >reflogs &&
+                       test_line_count = 2 reflogs &&
+                       test_migration repo "$to_format" true --no-reflog &&
+                       # there should be no reflogs post migration.
+                       git -C repo reflog --all >reflogs &&
+                       test_must_be_empty reflogs
+               '
        done
 done