{"thread":{"id":"62917","subject":"[PATCH] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","startedAt":"2025-02-07T11:57:43Z","lastAt":"2025-02-23T20:30:19Z","messageCount":26,"participants":["Karthik Nayak","Patrick Steinhardt","Justin Tobler","Junio C Hamano","Toon Claes"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"512094","messageId":"20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v1-1-7d40f3b4e30b@gmail.com","threadId":"62917","inReplyTo":null,"subject":"[PATCH] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-02-07T11:57:31Z","receivedAt":"2025-02-07T11:57:43Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"The 'git-refs(1)' migrate subcommand, which transfers repositories\nbetween reference backends, currently migrates reflogs by default as of\nIn 246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\nWhile this behavior is desirable for most client-side repositories,\nserver-side repositories typically don't use reflogs and the migration\nof these entries is unnecessary overhead.\n\nAdd a '--skip-reflog' flag to the migrate subcommand to make reflog\nmigration optional. This is particularly useful for server-side\nmigrations where reflogs are not needed, improving migration performance\nin these scenarios.\n\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n---\n builtin/refs.c          |  3 +++\n refs.c                  |  8 +++++---\n refs.h                  |  5 ++++-\n t/t1460-refs-migrate.sh | 17 +++++++++++++++--\n 4 files changed, 27 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/refs.c b/builtin/refs.c\nindex a29f19583474518ee0942ea53c39cbdf9661c5e2..30be0254c14dd3d07693d70c25dddc9990756e9c 100644\n--- a/builtin/refs.c\n+++ b/builtin/refs.c\n@@ -30,6 +30,9 @@ static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,\n \t\tOPT_BIT(0, \"dry-run\", &flags,\n \t\t\tN_(\"perform a non-destructive dry-run\"),\n \t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN),\n+\t\tOPT_BIT(0, \"skip-reflog\", &flags,\n+\t\t\tN_(\"skip migrating reflogs\"),\n+\t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG),\n \t\tOPT_END(),\n \t};\n \tstruct strbuf errbuf = STRBUF_INIT;\ndiff --git a/refs.c b/refs.c\nindex f4094a326a9f88f979654b668cc9c3d27d83cb5d..5e8f5c06fa68d16c93ee11edd9742995eea994b6 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -3035,9 +3035,11 @@ int repo_migrate_ref_storage_format(struct repository *repo,\n \tif (ret < 0)\n \t\tgoto done;\n \n-\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n-\tif (ret < 0)\n-\t\tgoto done;\n+\tif (!(flags & REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG)) {\n+\t\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n+\t\tif (ret < 0)\n+\t\t\tgoto done;\n+\t}\n \n \tret = ref_transaction_commit(transaction, errbuf);\n \tif (ret < 0)\ndiff --git a/refs.h b/refs.h\nindex a0cdd99250e8286b55808b697b0a94afac5d8319..ccee8fc6705e6e93a1c6234e7395180f8dfd815b 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -1157,8 +1157,11 @@ int is_pseudo_ref(const char *refname);\n  *   - REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN: perform a dry-run migration\n  *     without touching the main repository. The result will be written into a\n  *     temporary ref storage directory.\n+ *\n+ *   - REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG: skip migration of reflogs.\n  */\n-#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN (1 << 0)\n+#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN      (1 << 0)\n+#define REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG (1 << 1)\n \n /*\n  * Migrate the ref storage format used by the repository to the\ndiff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh\nindex a6d9b35a46eb59350aa0d59d982a2fbfaecf1448..9059d4c4121842a9d2e77dc4e54c537eeff8afab 100755\n--- a/t/t1460-refs-migrate.sh\n+++ b/t/t1460-refs-migrate.sh\n@@ -9,14 +9,16 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\n \n # Migrate the provided repository from one format to the other and\n # verify that the references and logs are migrated over correctly.\n-# Usage: test_migration <repo> <format> <skip_reflog_verify>\n+# Usage: test_migration <repo> <format> <skip_reflog_verify> <...options>\n #   <repo> is the relative path to the repo to be migrated.\n #   <format> is the ref format to be migrated to.\n #   <skip_reflog_verify> (true or false) whether to skip reflog verification.\n+#   <...options> are other options be passed directly to 'git refs migrate'.\n test_migration () {\n \trepo=$1 &&\n \tformat=$2 &&\n \tskip_reflog_verify=${3:-false} &&\n+\tshift $(( $# >= 3 ? 3 : 2 )) &&\n \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n \t\t--format='%(refname) %(objectname) %(symref)' >expect &&\n \tif ! $skip_reflog_verify\n@@ -25,7 +27,7 @@ test_migration () {\n \t   git -C \"$repo\" reflog list >expect_log_list\n \tfi &&\n \n-\tgit -C \"$repo\" refs migrate --ref-format=\"$2\" &&\n+\tgit -C \"$repo\" refs migrate --ref-format=\"$format\" $@ &&\n \n \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n \t\t--format='%(refname) %(objectname) %(symref)' >actual &&\n@@ -241,6 +243,17 @@ do\n \t\t\t\ttest_cmp expect.reflog actual.reflog\n \t\t\t)\n \t\t'\n+\n+\t\ttest_expect_success \"$from_format -> $to_format: skip reflog with --skip-reflog\" '\n+\t\t\ttest_when_finished \"rm -rf repo\" &&\n+\t\t\tgit init --ref-format=$from_format repo &&\n+\t\t\ttest_commit -C repo initial &&\n+\t\t\t# we see that the repository contains reflogs.\n+\t\t\ttest 2 = $(git -C repo reflog --all | wc -l) &&\n+\t\t\ttest_migration repo \"$to_format\" true --skip-reflog &&\n+\t\t\t# there should be no reflogs post migration.\n+\t\t\ttest 0 = $(git -C repo reflog --all | wc -l)\n+\t\t'\n \tdone\n done\n \n\n---\n\nbase-commit: bc204b742735ae06f65bb20291c95985c9633b7f\nchange-id: 20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-8066f6df50ac\n\nThanks\n- Karthik\n\n"},{"id":"512099","messageId":"Z6YlcpKp2U2V8Yd3@pks.im","threadId":"62917","inReplyTo":"20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v1-1-7d40f3b4e30b@gmail.com","subject":"Re: [PATCH] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-02-07T15:23:30Z","receivedAt":"2025-02-07T15:23:40Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Feb 07, 2025 at 12:57:31PM +0100, Karthik Nayak wrote:\n> The 'git-refs(1)' migrate subcommand, which transfers repositories\n> between reference backends, currently migrates reflogs by default as of\n> In 246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n\ns/In//\n\n> While this behavior is desirable for most client-side repositories,\n> server-side repositories typically don't use reflogs and the migration\n> of these entries is unnecessary overhead.\n\nNit: if the server-side repository doesn't _have_ reflogs, then there\ncannot be any overhead caused by their migration either, right? I still\nthink that the flag makes sense (well, I proposed it). But to me the\nargument is rather that we don't _expect_ there to be any reflogs, but\ndue to historic reasons there actually _might_ be some. This could for\nexample be caused by a bugs, misconfiguration, or an admin who has\nenabled reflogs on the server-side to debug something.\n\nSo even if there are some reflogs, we don't want to migrate them. Which\ncoincidentally helps us to improve performance, but the real value-add\nhere is that it makes the result match our expectations.\n\n> Add a '--skip-reflog' flag to the migrate subcommand to make reflog\n> migration optional. This is particularly useful for server-side\n> migrations where reflogs are not needed, improving migration performance\n> in these scenarios.\n\nThe second sentence of this paragraph feels duplicated with what you\nhave already been saying in the preceding paragraph.\n\n> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n> ---\n> ---\n\nAnother thing to teach b4: skip the comment in a single-patch patch\nseries in case you don't supply a cover letter :)\n\n> diff --git a/refs.c b/refs.c\n> index f4094a326a9f88f979654b668cc9c3d27d83cb5d..5e8f5c06fa68d16c93ee11edd9742995eea994b6 100644\n> --- a/refs.c\n> +++ b/refs.c\n> @@ -3035,9 +3035,11 @@ int repo_migrate_ref_storage_format(struct repository *repo,\n>  \tif (ret < 0)\n>  \t\tgoto done;\n>  \n> -\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n> -\tif (ret < 0)\n> -\t\tgoto done;\n> +\tif (!(flags & REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG)) {\n> +\t\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n> +\t\tif (ret < 0)\n> +\t\t\tgoto done;\n> +\t}\n>  \n>  \tret = ref_transaction_commit(transaction, errbuf);\n>  \tif (ret < 0)\n\nNice and simple, as expected.\n\n> diff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh\n> index a6d9b35a46eb59350aa0d59d982a2fbfaecf1448..9059d4c4121842a9d2e77dc4e54c537eeff8afab 100755\n> --- a/t/t1460-refs-migrate.sh\n> +++ b/t/t1460-refs-migrate.sh\n> @@ -9,14 +9,16 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\n>  \n>  # Migrate the provided repository from one format to the other and\n>  # verify that the references and logs are migrated over correctly.\n> -# Usage: test_migration <repo> <format> <skip_reflog_verify>\n> +# Usage: test_migration <repo> <format> <skip_reflog_verify> <...options>\n>  #   <repo> is the relative path to the repo to be migrated.\n>  #   <format> is the ref format to be migrated to.\n>  #   <skip_reflog_verify> (true or false) whether to skip reflog verification.\n> +#   <...options> are other options be passed directly to 'git refs migrate'.\n>  test_migration () {\n>  \trepo=$1 &&\n>  \tformat=$2 &&\n>  \tskip_reflog_verify=${3:-false} &&\n> +\tshift $(( $# >= 3 ? 3 : 2 )) &&\n\nI honestly have no idea whether this works with all supported shells. If\nit does it's a bit funky, but should work alright for our purpose. I was\nthinking a bit about how to improve this, but ultimately came to the\nconclusion that there isn't really a need to overengineer this simple\ntest function.\n\n> @@ -241,6 +243,17 @@ do\n>  \t\t\t\ttest_cmp expect.reflog actual.reflog\n>  \t\t\t)\n>  \t\t'\n> +\n> +\t\ttest_expect_success \"$from_format -> $to_format: skip reflog with --skip-reflog\" '\n> +\t\t\ttest_when_finished \"rm -rf repo\" &&\n> +\t\t\tgit init --ref-format=$from_format repo &&\n> +\t\t\ttest_commit -C repo initial &&\n> +\t\t\t# we see that the repository contains reflogs.\n> +\t\t\ttest 2 = $(git -C repo reflog --all | wc -l) &&\n\nNit: we don't want to have Git on the left-hand side of a pipe, as it\nmight make use lose its exit code. This could instead be:\n\n    git -C repo reflog --all >reflogs &&\n    test_line_count = 2 reflogs\n\n> +\t\t\ttest_migration repo \"$to_format\" true --skip-reflog &&\n> +\t\t\t# there should be no reflogs post migration.\n> +\t\t\ttest 0 = $(git -C repo reflog --all | wc -l)\n\nAnd here we could use `test_must_be_empty`.\n\nThanks!\n\nPatrick\n"},{"id":"512109","messageId":"llz32al6tgghs73odbryc2324vks2pf3uyawp5dls5wgop7or2@bumahbjibtgz","threadId":"62917","inReplyTo":"20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v1-1-7d40f3b4e30b@gmail.com","subject":"Re: [PATCH] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2025-02-07T17:45:07Z","receivedAt":"2025-02-07T17:48:08Z","isPatch":true,"sender":{"key":"jltobler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/53454972?v=4"},"body":"On 25/02/07 12:57PM, Karthik Nayak wrote:\n> The 'git-refs(1)' migrate subcommand, which transfers repositories\n> between reference backends, currently migrates reflogs by default as of\n> In 246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n\ns/In 246cebe320/246cebe320/\n\n> While this behavior is desirable for most client-side repositories,\n> server-side repositories typically don't use reflogs and the migration\n> of these entries is unnecessary overhead.\n> \n> Add a '--skip-reflog' flag to the migrate subcommand to make reflog\n> migration optional. This is particularly useful for server-side\n> migrations where reflogs are not needed, improving migration performance\n> in these scenarios.\n\nJust to clarify, does a repository already without reflogs see improved\nmigration performance with this `--skip-reflog` flag? Or is the improved\nperformance soley due to repositories with reflogs skipping that part of\nthe migration?\n\n> \n> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n> ---\n> ---\n>  builtin/refs.c          |  3 +++\n>  refs.c                  |  8 +++++---\n>  refs.h                  |  5 ++++-\n>  t/t1460-refs-migrate.sh | 17 +++++++++++++++--\n>  4 files changed, 27 insertions(+), 6 deletions(-)\n> \n> diff --git a/builtin/refs.c b/builtin/refs.c\n> index a29f19583474518ee0942ea53c39cbdf9661c5e2..30be0254c14dd3d07693d70c25dddc9990756e9c 100644\n> --- a/builtin/refs.c\n> +++ b/builtin/refs.c\n> @@ -30,6 +30,9 @@ static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,\n>  \t\tOPT_BIT(0, \"dry-run\", &flags,\n>  \t\t\tN_(\"perform a non-destructive dry-run\"),\n>  \t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN),\n> +\t\tOPT_BIT(0, \"skip-reflog\", &flags,\n> +\t\t\tN_(\"skip migrating reflogs\"),\n> +\t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG),\n>  \t\tOPT_END(),\n>  \t};\n>  \tstruct strbuf errbuf = STRBUF_INIT;\n> diff --git a/refs.c b/refs.c\n> index f4094a326a9f88f979654b668cc9c3d27d83cb5d..5e8f5c06fa68d16c93ee11edd9742995eea994b6 100644\n> --- a/refs.c\n> +++ b/refs.c\n> @@ -3035,9 +3035,11 @@ int repo_migrate_ref_storage_format(struct repository *repo,\n>  \tif (ret < 0)\n>  \t\tgoto done;\n>  \n> -\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n> -\tif (ret < 0)\n> -\t\tgoto done;\n> +\tif (!(flags & REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG)) {\n> +\t\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n> +\t\tif (ret < 0)\n> +\t\t\tgoto done;\n> +\t}\n\nWhen the `REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG` flag is set, we\nnow skip over all the logs to perform the reflog migration. Makes sense.\n\n-Justin\n\n>  \n>  \tret = ref_transaction_commit(transaction, errbuf);\n>  \tif (ret < 0)\n> diff --git a/refs.h b/refs.h\n> index a0cdd99250e8286b55808b697b0a94afac5d8319..ccee8fc6705e6e93a1c6234e7395180f8dfd815b 100644\n> --- a/refs.h\n> +++ b/refs.h\n> @@ -1157,8 +1157,11 @@ int is_pseudo_ref(const char *refname);\n>   *   - REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN: perform a dry-run migration\n>   *     without touching the main repository. The result will be written into a\n>   *     temporary ref storage directory.\n> + *\n> + *   - REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG: skip migration of reflogs.\n>   */\n> -#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN (1 << 0)\n> +#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN      (1 << 0)\n> +#define REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG (1 << 1)\n>  \n>  /*\n>   * Migrate the ref storage format used by the repository to the\n> diff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh\n> index a6d9b35a46eb59350aa0d59d982a2fbfaecf1448..9059d4c4121842a9d2e77dc4e54c537eeff8afab 100755\n> --- a/t/t1460-refs-migrate.sh\n> +++ b/t/t1460-refs-migrate.sh\n> @@ -9,14 +9,16 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\n>  \n>  # Migrate the provided repository from one format to the other and\n>  # verify that the references and logs are migrated over correctly.\n> -# Usage: test_migration <repo> <format> <skip_reflog_verify>\n> +# Usage: test_migration <repo> <format> <skip_reflog_verify> <...options>\n>  #   <repo> is the relative path to the repo to be migrated.\n>  #   <format> is the ref format to be migrated to.\n>  #   <skip_reflog_verify> (true or false) whether to skip reflog verification.\n> +#   <...options> are other options be passed directly to 'git refs migrate'.\n>  test_migration () {\n>  \trepo=$1 &&\n>  \tformat=$2 &&\n>  \tskip_reflog_verify=${3:-false} &&\n> +\tshift $(( $# >= 3 ? 3 : 2 )) &&\n>  \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n>  \t\t--format='%(refname) %(objectname) %(symref)' >expect &&\n>  \tif ! $skip_reflog_verify\n> @@ -25,7 +27,7 @@ test_migration () {\n>  \t   git -C \"$repo\" reflog list >expect_log_list\n>  \tfi &&\n>  \n> -\tgit -C \"$repo\" refs migrate --ref-format=\"$2\" &&\n> +\tgit -C \"$repo\" refs migrate --ref-format=\"$format\" $@ &&\n>  \n>  \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n>  \t\t--format='%(refname) %(objectname) %(symref)' >actual &&\n> @@ -241,6 +243,17 @@ do\n>  \t\t\t\ttest_cmp expect.reflog actual.reflog\n>  \t\t\t)\n>  \t\t'\n> +\n> +\t\ttest_expect_success \"$from_format -> $to_format: skip reflog with --skip-reflog\" '\n> +\t\t\ttest_when_finished \"rm -rf repo\" &&\n> +\t\t\tgit init --ref-format=$from_format repo &&\n> +\t\t\ttest_commit -C repo initial &&\n> +\t\t\t# we see that the repository contains reflogs.\n> +\t\t\ttest 2 = $(git -C repo reflog --all | wc -l) &&\n> +\t\t\ttest_migration repo \"$to_format\" true --skip-reflog &&\n> +\t\t\t# there should be no reflogs post migration.\n> +\t\t\ttest 0 = $(git -C repo reflog --all | wc -l)\n> +\t\t'\n>  \tdone\n>  done\n>  \n> \n> ---\n> \n> base-commit: bc204b742735ae06f65bb20291c95985c9633b7f\n> change-id: 20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-8066f6df50ac\n> \n> Thanks\n> - Karthik\n> \n> \n"},{"id":"512207","messageId":"CAOLa=ZTGTr_3Xe2mLZ9wYB6oo++TuLUN-OQ2Cpv9Fokgc77UcQ@mail.gmail.com","threadId":"62917","inReplyTo":"llz32al6tgghs73odbryc2324vks2pf3uyawp5dls5wgop7or2@bumahbjibtgz","subject":"Re: [PATCH] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-02-11T06:09:16Z","receivedAt":"2025-02-11T06:09:18Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Justin Tobler <jltobler@gmail.com> writes:\n\n> On 25/02/07 12:57PM, Karthik Nayak wrote:\n>> The 'git-refs(1)' migrate subcommand, which transfers repositories\n>> between reference backends, currently migrates reflogs by default as of\n>> In 246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n>\n> s/In 246cebe320/246cebe320/\n>\n\nThanks.\n\n>> While this behavior is desirable for most client-side repositories,\n>> server-side repositories typically don't use reflogs and the migration\n>> of these entries is unnecessary overhead.\n>>\n>> Add a '--skip-reflog' flag to the migrate subcommand to make reflog\n>> migration optional. This is particularly useful for server-side\n>> migrations where reflogs are not needed, improving migration performance\n>> in these scenarios.\n>\n> Just to clarify, does a repository already without reflogs see improved\n> migration performance with this `--skip-reflog` flag? Or is the improved\n> performance soley due to repositories with reflogs skipping that part of\n> the migration?\n>\n\nSince we iterate over all reflogs and add them, the perf gain would only\nbe for repositories which already have reflogs. Will modify accordingly.\n\n>>\n>> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n>> ---\n>> ---\n>>  builtin/refs.c          |  3 +++\n>>  refs.c                  |  8 +++++---\n>>  refs.h                  |  5 ++++-\n>>  t/t1460-refs-migrate.sh | 17 +++++++++++++++--\n>>  4 files changed, 27 insertions(+), 6 deletions(-)\n>>\n>> diff --git a/builtin/refs.c b/builtin/refs.c\n>> index a29f19583474518ee0942ea53c39cbdf9661c5e2..30be0254c14dd3d07693d70c25dddc9990756e9c 100644\n>> --- a/builtin/refs.c\n>> +++ b/builtin/refs.c\n>> @@ -30,6 +30,9 @@ static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,\n>>  \t\tOPT_BIT(0, \"dry-run\", &flags,\n>>  \t\t\tN_(\"perform a non-destructive dry-run\"),\n>>  \t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN),\n>> +\t\tOPT_BIT(0, \"skip-reflog\", &flags,\n>> +\t\t\tN_(\"skip migrating reflogs\"),\n>> +\t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG),\n>>  \t\tOPT_END(),\n>>  \t};\n>>  \tstruct strbuf errbuf = STRBUF_INIT;\n>> diff --git a/refs.c b/refs.c\n>> index f4094a326a9f88f979654b668cc9c3d27d83cb5d..5e8f5c06fa68d16c93ee11edd9742995eea994b6 100644\n>> --- a/refs.c\n>> +++ b/refs.c\n>> @@ -3035,9 +3035,11 @@ int repo_migrate_ref_storage_format(struct repository *repo,\n>>  \tif (ret < 0)\n>>  \t\tgoto done;\n>>\n>> -\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n>> -\tif (ret < 0)\n>> -\t\tgoto done;\n>> +\tif (!(flags & REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG)) {\n>> +\t\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n>> +\t\tif (ret < 0)\n>> +\t\t\tgoto done;\n>> +\t}\n>\n> When the `REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG` flag is set, we\n> now skip over all the logs to perform the reflog migration. Makes sense.\n>\n\nYup, thanks for the review.\n\n> -Justin\n>\n"},{"id":"512208","messageId":"CAOLa=ZQX1mZD+iegnezObmJrFy+Zer4CgHTrQz=-SbgHeTfN=g@mail.gmail.com","threadId":"62917","inReplyTo":"Z6YlcpKp2U2V8Yd3@pks.im","subject":"Re: [PATCH] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-02-11T06:18:54Z","receivedAt":"2025-02-11T06:18:56Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> On Fri, Feb 07, 2025 at 12:57:31PM +0100, Karthik Nayak wrote:\n>> The 'git-refs(1)' migrate subcommand, which transfers repositories\n>> between reference backends, currently migrates reflogs by default as of\n>> In 246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n>\n> s/In//\n>\n>> While this behavior is desirable for most client-side repositories,\n>> server-side repositories typically don't use reflogs and the migration\n>> of these entries is unnecessary overhead.\n>\n> Nit: if the server-side repository doesn't _have_ reflogs, then there\n> cannot be any overhead caused by their migration either, right? I still\n> think that the flag makes sense (well, I proposed it). But to me the\n> argument is rather that we don't _expect_ there to be any reflogs, but\n> due to historic reasons there actually _might_ be some. This could for\n> example be caused by a bugs, misconfiguration, or an admin who has\n> enabled reflogs on the server-side to debug something.\n>\n> So even if there are some reflogs, we don't want to migrate them. Which\n> coincidentally helps us to improve performance, but the real value-add\n> here is that it makes the result match our expectations.\n>\n\nFair enough, I agree that, finally, we mostly care about not having\nreflogs in the end. I'll modify accordingly.\n\n>> Add a '--skip-reflog' flag to the migrate subcommand to make reflog\n>> migration optional. This is particularly useful for server-side\n>> migrations where reflogs are not needed, improving migration performance\n>> in these scenarios.\n>\n> The second sentence of this paragraph feels duplicated with what you\n> have already been saying in the preceding paragraph.\n>\n\nWill cleanup.\n\n>> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n>> ---\n>> ---\n>\n> Another thing to teach b4: skip the comment in a single-patch patch\n> series in case you don't supply a cover letter :)\n>\n\nTrue. I think this is because of lack of conditionals in the templating.\n\n>> diff --git a/refs.c b/refs.c\n>> index f4094a326a9f88f979654b668cc9c3d27d83cb5d..5e8f5c06fa68d16c93ee11edd9742995eea994b6 100644\n>> --- a/refs.c\n>> +++ b/refs.c\n>> @@ -3035,9 +3035,11 @@ int repo_migrate_ref_storage_format(struct repository *repo,\n>>  \tif (ret < 0)\n>>  \t\tgoto done;\n>>\n>> -\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n>> -\tif (ret < 0)\n>> -\t\tgoto done;\n>> +\tif (!(flags & REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG)) {\n>> +\t\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n>> +\t\tif (ret < 0)\n>> +\t\t\tgoto done;\n>> +\t}\n>>\n>>  \tret = ref_transaction_commit(transaction, errbuf);\n>>  \tif (ret < 0)\n>\n> Nice and simple, as expected.\n>\n>> diff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh\n>> index a6d9b35a46eb59350aa0d59d982a2fbfaecf1448..9059d4c4121842a9d2e77dc4e54c537eeff8afab 100755\n>> --- a/t/t1460-refs-migrate.sh\n>> +++ b/t/t1460-refs-migrate.sh\n>> @@ -9,14 +9,16 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\n>>\n>>  # Migrate the provided repository from one format to the other and\n>>  # verify that the references and logs are migrated over correctly.\n>> -# Usage: test_migration <repo> <format> <skip_reflog_verify>\n>> +# Usage: test_migration <repo> <format> <skip_reflog_verify> <...options>\n>>  #   <repo> is the relative path to the repo to be migrated.\n>>  #   <format> is the ref format to be migrated to.\n>>  #   <skip_reflog_verify> (true or false) whether to skip reflog verification.\n>> +#   <...options> are other options be passed directly to 'git refs migrate'.\n>>  test_migration () {\n>>  \trepo=$1 &&\n>>  \tformat=$2 &&\n>>  \tskip_reflog_verify=${3:-false} &&\n>> +\tshift $(( $# >= 3 ? 3 : 2 )) &&\n>\n> I honestly have no idea whether this works with all supported shells. If\n> it does it's a bit funky, but should work alright for our purpose. I was\n> thinking a bit about how to improve this, but ultimately came to the\n> conclusion that there isn't really a need to overengineer this simple\n> test function.\n>\n\nI was skeptical too, while not a complete test, the CI seemed to not\ncomplain.\n\n>> @@ -241,6 +243,17 @@ do\n>>  \t\t\t\ttest_cmp expect.reflog actual.reflog\n>>  \t\t\t)\n>>  \t\t'\n>> +\n>> +\t\ttest_expect_success \"$from_format -> $to_format: skip reflog with --skip-reflog\" '\n>> +\t\t\ttest_when_finished \"rm -rf repo\" &&\n>> +\t\t\tgit init --ref-format=$from_format repo &&\n>> +\t\t\ttest_commit -C repo initial &&\n>> +\t\t\t# we see that the repository contains reflogs.\n>> +\t\t\ttest 2 = $(git -C repo reflog --all | wc -l) &&\n>\n> Nit: we don't want to have Git on the left-hand side of a pipe, as it\n> might make use lose its exit code. This could instead be:\n>\n>     git -C repo reflog --all >reflogs &&\n>     test_line_count = 2 reflogs\n>\n\nThis looks cleaner.\n\n>> +\t\t\ttest_migration repo \"$to_format\" true --skip-reflog &&\n>> +\t\t\t# there should be no reflogs post migration.\n>> +\t\t\ttest 0 = $(git -C repo reflog --all | wc -l)\n>\n> And here we could use `test_must_be_empty`.\n>\n\nWill amend, Thanks for the review.\n\n> Thanks!\n>\n> Patrick\n"},{"id":"512229","messageId":"20250211-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v2-1-991a2ec9a796@gmail.com","threadId":"62917","inReplyTo":"20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v1-1-7d40f3b4e30b@gmail.com","subject":"[PATCH v2] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-02-11T11:42:18Z","receivedAt":"2025-02-11T11:42:28Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"The 'git-refs(1)' migrate subcommand, which transfers repositories\nbetween reference backends, currently migrates reflogs by default as of\n246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n\nWhile this behavior is desirable for most client-side repositories,\nserver-side repositories are not expected to contain reflogs. However,\ndue to historical reasons, some may still have them. This could be\ncaused, for example, by bugs, misconfiguration, or an administrator\nenabling reflogs on the server for debugging purposes.\n\nTo address this, introduce the --skip-reflog flag, allowing users to\nbypass reflog migration. This ensures that the repository ends up in the\nexpected state after migration.\n\nHelped-by: Patrick Steinhardt <ps@pks.im>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\nChanges in v2:\n- Fix typo in commit mesasge and clarify the intent.\n- Modify the test to use `test_line_count` and `test_must_be_empty`.\n- Link to v1: https://lore.kernel.org/r/20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v1-1-7d40f3b4e30b@gmail.com\n---\nRange-diff versus v1:\n\n1:  ce14d3d07e ! 1:  6b83089348 builtin/refs: add '--skip-reflog' flag to bypass reflog migration\n    @@ Commit message\n     \n         The 'git-refs(1)' migrate subcommand, which transfers repositories\n         between reference backends, currently migrates reflogs by default as of\n    -    In 246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n    +    246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n    +\n         While this behavior is desirable for most client-side repositories,\n    -    server-side repositories typically don't use reflogs and the migration\n    -    of these entries is unnecessary overhead.\n    +    server-side repositories are not expected to contain reflogs. However,\n    +    due to historical reasons, some may still have them. This could be\n    +    caused, for example, by bugs, misconfiguration, or an administrator\n    +    enabling reflogs on the server for debugging purposes.\n     \n    -    Add a '--skip-reflog' flag to the migrate subcommand to make reflog\n    -    migration optional. This is particularly useful for server-side\n    -    migrations where reflogs are not needed, improving migration performance\n    -    in these scenarios.\n    +    To address this, introduce the --skip-reflog flag, allowing users to\n    +    bypass reflog migration. This ensures that the repository ends up in the\n    +    expected state after migration.\n     \n    +    Helped-by: Patrick Steinhardt <ps@pks.im>\n         Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n     \n      ## builtin/refs.c ##\n    @@ t/t1460-refs-migrate.sh: do\n     +\t\t\tgit init --ref-format=$from_format repo &&\n     +\t\t\ttest_commit -C repo initial &&\n     +\t\t\t# we see that the repository contains reflogs.\n    -+\t\t\ttest 2 = $(git -C repo reflog --all | wc -l) &&\n    ++\t\t\tgit -C repo reflog --all >reflogs &&\n    ++\t\t\ttest_line_count = 2 reflogs &&\n     +\t\t\ttest_migration repo \"$to_format\" true --skip-reflog &&\n     +\t\t\t# there should be no reflogs post migration.\n    -+\t\t\ttest 0 = $(git -C repo reflog --all | wc -l)\n    ++\t\t\tgit -C repo reflog --all >reflogs &&\n    ++\t\t\ttest_must_be_empty reflogs\n     +\t\t'\n      \tdone\n      done\n---\n builtin/refs.c          |  3 +++\n refs.c                  |  8 +++++---\n refs.h                  |  5 ++++-\n t/t1460-refs-migrate.sh | 19 +++++++++++++++++--\n 4 files changed, 29 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/refs.c b/builtin/refs.c\nindex a29f19583474518ee0942ea53c39cbdf9661c5e2..30be0254c14dd3d07693d70c25dddc9990756e9c 100644\n--- a/builtin/refs.c\n+++ b/builtin/refs.c\n@@ -30,6 +30,9 @@ static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,\n \t\tOPT_BIT(0, \"dry-run\", &flags,\n \t\t\tN_(\"perform a non-destructive dry-run\"),\n \t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN),\n+\t\tOPT_BIT(0, \"skip-reflog\", &flags,\n+\t\t\tN_(\"skip migrating reflogs\"),\n+\t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG),\n \t\tOPT_END(),\n \t};\n \tstruct strbuf errbuf = STRBUF_INIT;\ndiff --git a/refs.c b/refs.c\nindex f4094a326a9f88f979654b668cc9c3d27d83cb5d..5e8f5c06fa68d16c93ee11edd9742995eea994b6 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -3035,9 +3035,11 @@ int repo_migrate_ref_storage_format(struct repository *repo,\n \tif (ret < 0)\n \t\tgoto done;\n \n-\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n-\tif (ret < 0)\n-\t\tgoto done;\n+\tif (!(flags & REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG)) {\n+\t\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n+\t\tif (ret < 0)\n+\t\t\tgoto done;\n+\t}\n \n \tret = ref_transaction_commit(transaction, errbuf);\n \tif (ret < 0)\ndiff --git a/refs.h b/refs.h\nindex a0cdd99250e8286b55808b697b0a94afac5d8319..ccee8fc6705e6e93a1c6234e7395180f8dfd815b 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -1157,8 +1157,11 @@ int is_pseudo_ref(const char *refname);\n  *   - REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN: perform a dry-run migration\n  *     without touching the main repository. The result will be written into a\n  *     temporary ref storage directory.\n+ *\n+ *   - REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG: skip migration of reflogs.\n  */\n-#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN (1 << 0)\n+#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN      (1 << 0)\n+#define REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG (1 << 1)\n \n /*\n  * Migrate the ref storage format used by the repository to the\ndiff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh\nindex a6d9b35a46eb59350aa0d59d982a2fbfaecf1448..28c0024a4c8cb8282bf586840265edba442f5056 100755\n--- a/t/t1460-refs-migrate.sh\n+++ b/t/t1460-refs-migrate.sh\n@@ -9,14 +9,16 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\n \n # Migrate the provided repository from one format to the other and\n # verify that the references and logs are migrated over correctly.\n-# Usage: test_migration <repo> <format> <skip_reflog_verify>\n+# Usage: test_migration <repo> <format> <skip_reflog_verify> <...options>\n #   <repo> is the relative path to the repo to be migrated.\n #   <format> is the ref format to be migrated to.\n #   <skip_reflog_verify> (true or false) whether to skip reflog verification.\n+#   <...options> are other options be passed directly to 'git refs migrate'.\n test_migration () {\n \trepo=$1 &&\n \tformat=$2 &&\n \tskip_reflog_verify=${3:-false} &&\n+\tshift $(( $# >= 3 ? 3 : 2 )) &&\n \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n \t\t--format='%(refname) %(objectname) %(symref)' >expect &&\n \tif ! $skip_reflog_verify\n@@ -25,7 +27,7 @@ test_migration () {\n \t   git -C \"$repo\" reflog list >expect_log_list\n \tfi &&\n \n-\tgit -C \"$repo\" refs migrate --ref-format=\"$2\" &&\n+\tgit -C \"$repo\" refs migrate --ref-format=\"$format\" $@ &&\n \n \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n \t\t--format='%(refname) %(objectname) %(symref)' >actual &&\n@@ -241,6 +243,19 @@ do\n \t\t\t\ttest_cmp expect.reflog actual.reflog\n \t\t\t)\n \t\t'\n+\n+\t\ttest_expect_success \"$from_format -> $to_format: skip reflog with --skip-reflog\" '\n+\t\t\ttest_when_finished \"rm -rf repo\" &&\n+\t\t\tgit init --ref-format=$from_format repo &&\n+\t\t\ttest_commit -C repo initial &&\n+\t\t\t# we see that the repository contains reflogs.\n+\t\t\tgit -C repo reflog --all >reflogs &&\n+\t\t\ttest_line_count = 2 reflogs &&\n+\t\t\ttest_migration repo \"$to_format\" true --skip-reflog &&\n+\t\t\t# there should be no reflogs post migration.\n+\t\t\tgit -C repo reflog --all >reflogs &&\n+\t\t\ttest_must_be_empty reflogs\n+\t\t'\n \tdone\n done\n \n\n---\n\nbase-commit: bc204b742735ae06f65bb20291c95985c9633b7f\nchange-id: 20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-8066f6df50ac\n\nThanks\n- Karthik\n\n"},{"id":"512232","messageId":"Z6tA4zC4WhdAVbPD@pks.im","threadId":"62917","inReplyTo":"20250211-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v2-1-991a2ec9a796@gmail.com","subject":"Re: [PATCH v2] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-02-11T12:21:55Z","receivedAt":"2025-02-11T12:22:01Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Tue, Feb 11, 2025 at 12:42:18PM +0100, Karthik Nayak wrote:\n> The 'git-refs(1)' migrate subcommand, which transfers repositories\n> between reference backends, currently migrates reflogs by default as of\n> 246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n> \n> While this behavior is desirable for most client-side repositories,\n> server-side repositories are not expected to contain reflogs. However,\n> due to historical reasons, some may still have them. This could be\n> caused, for example, by bugs, misconfiguration, or an administrator\n> enabling reflogs on the server for debugging purposes.\n> \n> To address this, introduce the --skip-reflog flag, allowing users to\n> bypass reflog migration. This ensures that the repository ends up in the\n> expected state after migration.\n\nThanks, this version looks good to me.\n\nPatrick\n"},{"id":"512245","messageId":"xmqqcyfoz82h.fsf@gitster.g","threadId":"62917","inReplyTo":"20250211-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v2-1-991a2ec9a796@gmail.com","subject":"Re: [PATCH v2] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-02-11T17:48:22Z","receivedAt":"2025-02-11T17:48:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> The 'git-refs(1)' migrate subcommand, which transfers repositories\n> between reference backends, currently migrates reflogs by default as of\n> 246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n>\n> While this behavior is desirable for most client-side repositories,\n> server-side repositories are not expected to contain reflogs. However,\n> due to historical reasons, some may still have them. This could be\n> caused, for example, by bugs, misconfiguration, or an administrator\n> enabling reflogs on the server for debugging purposes.\n>\n> To address this, introduce the --skip-reflog flag, allowing users to\n> bypass reflog migration. This ensures that the repository ends up in the\n> expected state after migration.\n>\n> Helped-by: Patrick Steinhardt <ps@pks.im>\n> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n> ---\n> Changes in v2:\n> - Fix typo in commit mesasge and clarify the intent.\n> - Modify the test to use `test_line_count` and `test_must_be_empty`.\n> - Link to v1: https://lore.kernel.org/r/20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v1-1-7d40f3b4e30b@gmail.com\n> ---\n> Range-diff versus v1:\n>\n> 1:  ce14d3d07e ! 1:  6b83089348 builtin/refs: add '--skip-reflog' flag to bypass reflog migration\n>     @@ Commit message\n>      \n>          The 'git-refs(1)' migrate subcommand, which transfers repositories\n>          between reference backends, currently migrates reflogs by default as of\n> ...\n>      +\t\t'\n>       \tdone\n>       done\n> ---\n>  builtin/refs.c          |  3 +++\n>  refs.c                  |  8 +++++---\n>  refs.h                  |  5 ++++-\n>  t/t1460-refs-migrate.sh | 19 +++++++++++++++++--\n>  4 files changed, 29 insertions(+), 6 deletions(-)\n\nThis is tangent that is totally unrelated to the theme of this\npatch, but I find that the placement of range-diff makes it very\nhard to follow.\n\nAfter skimming the proposed log message, the next thing I would want\nto see is the list of paths that are modified, before deciding I\nwant to review the patch now.  Once I decide to read it _now_, the\nchanges from the previous iteration and range-diff becomes relevant.\n\nIs it just me who decides in what order to review the patches and\nthen reviews them in that order?\n\nAnyway.\n\n> diff --git a/builtin/refs.c b/builtin/refs.c\n> index a29f19583474518ee0942ea53c39cbdf9661c5e2..30be0254c14dd3d07693d70c25dddc9990756e9c 100644\n> --- a/builtin/refs.c\n> +++ b/builtin/refs.c\n> @@ -30,6 +30,9 @@ static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,\n>  \t\tOPT_BIT(0, \"dry-run\", &flags,\n>  \t\t\tN_(\"perform a non-destructive dry-run\"),\n>  \t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN),\n> +\t\tOPT_BIT(0, \"skip-reflog\", &flags,\n> +\t\t\tN_(\"skip migrating reflogs\"),\n> +\t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG),\n>  \t\tOPT_END(),\n>  \t};\n>  \tstruct strbuf errbuf = STRBUF_INIT;\n\nOK.\n\n> diff --git a/refs.c b/refs.c\n> index f4094a326a9f88f979654b668cc9c3d27d83cb5d..5e8f5c06fa68d16c93ee11edd9742995eea994b6 100644\n> --- a/refs.c\n> +++ b/refs.c\n> @@ -3035,9 +3035,11 @@ int repo_migrate_ref_storage_format(struct repository *repo,\n>  \tif (ret < 0)\n>  \t\tgoto done;\n>  \n> -\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n> -\tif (ret < 0)\n> -\t\tgoto done;\n> +\tif (!(flags & REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG)) {\n> +\t\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n> +\t\tif (ret < 0)\n> +\t\t\tgoto done;\n> +\t}\n>  \n>  \tret = ref_transaction_commit(transaction, errbuf);\n>  \tif (ret < 0)\n> diff --git a/refs.h b/refs.h\n> index a0cdd99250e8286b55808b697b0a94afac5d8319..ccee8fc6705e6e93a1c6234e7395180f8dfd815b 100644\n> --- a/refs.h\n> +++ b/refs.h\n> @@ -1157,8 +1157,11 @@ int is_pseudo_ref(const char *refname);\n>   *   - REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN: perform a dry-run migration\n>   *     without touching the main repository. The result will be written into a\n>   *     temporary ref storage directory.\n> + *\n> + *   - REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG: skip migration of reflogs.\n>   */\n> -#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN (1 << 0)\n> +#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN      (1 << 0)\n> +#define REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG (1 << 1)\n\nThese are quite a mouthful, but they are only used between the refs\nsubsystem and \"git refs\" command, so being overly verbose and\nspecific is a good thing.\n\n>  /*\n>   * Migrate the ref storage format used by the repository to the\n> diff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh\n> index a6d9b35a46eb59350aa0d59d982a2fbfaecf1448..28c0024a4c8cb8282bf586840265edba442f5056 100755\n> --- a/t/t1460-refs-migrate.sh\n> +++ b/t/t1460-refs-migrate.sh\n> @@ -9,14 +9,16 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\n>  \n>  # Migrate the provided repository from one format to the other and\n>  # verify that the references and logs are migrated over correctly.\n> -# Usage: test_migration <repo> <format> <skip_reflog_verify>\n> +# Usage: test_migration <repo> <format> <skip_reflog_verify> <...options>\n>  #   <repo> is the relative path to the repo to be migrated.\n>  #   <format> is the ref format to be migrated to.\n>  #   <skip_reflog_verify> (true or false) whether to skip reflog verification.\n> +#   <...options> are other options be passed directly to 'git refs migrate'.\n\nYuck.  I've never seen preceding three-dots.  Makes readers wonder\nhow this thing behaves differently from the usual <options...>.\n\nDoubly yuck is ...\n\n\n>  test_migration () {\n>  \trepo=$1 &&\n>  \tformat=$2 &&\n>  \tskip_reflog_verify=${3:-false} &&\n> +\tshift $(( $# >= 3 ? 3 : 2 )) &&\n\n... this thing.  The above usage declares that <skip_reflog_verify>,\njust like <repo> and <format>, are required so I do not see why we\nneed to be conditional here.  If you want to make it optional,\nwriting it this way instead ...\n\n\trepo=$1 &&\n        format=$2 &&\n\tshift 2 &&\n\n        skip_reflog_verify=false &&\n\tif test $# -gt 1\n\tthen\n\t\tskip_reflog_verify=$1\n\t\tshift\n\tfi\n\n... would make it easier to extend when you ever want to add the\nnext optional positional parameter.\n\n>  \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n>  \t\t--format='%(refname) %(objectname) %(symref)' >expect &&\n>  \tif ! $skip_reflog_verify\n> @@ -25,7 +27,7 @@ test_migration () {\n>  \t   git -C \"$repo\" reflog list >expect_log_list\n>  \tfi &&\n>  \n> -\tgit -C \"$repo\" refs migrate --ref-format=\"$2\" &&\n> +\tgit -C \"$repo\" refs migrate --ref-format=\"$format\" $@ &&\n\nIt is a good change to use the named variable we captured upfront,\nbut did you mean to leave $@ unquoted?\n\nUnless you want to use \"$@\" to invoke the magic \"pass each parameter\nseparately, even if it has $IFS whitespace in it\" semantics,\nchoosing between $* (when you want to split a parameter into many\nwhen it has $IFS whitespaces) and \"$*\" (when you want everything in\none string) is preferred.\n\n>  \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n>  \t\t--format='%(refname) %(objectname) %(symref)' >actual &&\n> @@ -241,6 +243,19 @@ do\n>  \t\t\t\ttest_cmp expect.reflog actual.reflog\n>  \t\t\t)\n>  \t\t'\n> +\n> +\t\ttest_expect_success \"$from_format -> $to_format: skip reflog with --skip-reflog\" '\n> +\t\t\ttest_when_finished \"rm -rf repo\" &&\n> +\t\t\tgit init --ref-format=$from_format repo &&\n> +\t\t\ttest_commit -C repo initial &&\n> +\t\t\t# we see that the repository contains reflogs.\n> +\t\t\tgit -C repo reflog --all >reflogs &&\n> +\t\t\ttest_line_count = 2 reflogs &&\n> +\t\t\ttest_migration repo \"$to_format\" true --skip-reflog &&\n> +\t\t\t# there should be no reflogs post migration.\n> +\t\t\tgit -C repo reflog --all >reflogs &&\n> +\t\t\ttest_must_be_empty reflogs\n> +\t\t'\n>  \tdone\n>  done\n>  \n>\n> ---\n>\n> base-commit: bc204b742735ae06f65bb20291c95985c9633b7f\n> change-id: 20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-8066f6df50ac\n>\n> Thanks\n> - Karthik\n"},{"id":"512324","messageId":"CAOLa=ZTc0ahGasJOyef0L5_uz6ui-fx66kJgWVSicLv1Pgqu2A@mail.gmail.com","threadId":"62917","inReplyTo":"xmqqcyfoz82h.fsf@gitster.g","subject":"Re: [PATCH v2] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-02-12T17:43:41Z","receivedAt":"2025-02-12T17:43:43Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> The 'git-refs(1)' migrate subcommand, which transfers repositories\n>> between reference backends, currently migrates reflogs by default as of\n>> 246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n>>\n>> While this behavior is desirable for most client-side repositories,\n>> server-side repositories are not expected to contain reflogs. However,\n>> due to historical reasons, some may still have them. This could be\n>> caused, for example, by bugs, misconfiguration, or an administrator\n>> enabling reflogs on the server for debugging purposes.\n>>\n>> To address this, introduce the --skip-reflog flag, allowing users to\n>> bypass reflog migration. This ensures that the repository ends up in the\n>> expected state after migration.\n>>\n>> Helped-by: Patrick Steinhardt <ps@pks.im>\n>> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n>> ---\n>> Changes in v2:\n>> - Fix typo in commit mesasge and clarify the intent.\n>> - Modify the test to use `test_line_count` and `test_must_be_empty`.\n>> - Link to v1: https://lore.kernel.org/r/20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v1-1-7d40f3b4e30b@gmail.com\n>> ---\n>> Range-diff versus v1:\n>>\n>> 1:  ce14d3d07e ! 1:  6b83089348 builtin/refs: add '--skip-reflog' flag to bypass reflog migration\n>>     @@ Commit message\n>>\n>>          The 'git-refs(1)' migrate subcommand, which transfers repositories\n>>          between reference backends, currently migrates reflogs by default as of\n>> ...\n>>      +\t\t'\n>>       \tdone\n>>       done\n>> ---\n>>  builtin/refs.c          |  3 +++\n>>  refs.c                  |  8 +++++---\n>>  refs.h                  |  5 ++++-\n>>  t/t1460-refs-migrate.sh | 19 +++++++++++++++++--\n>>  4 files changed, 29 insertions(+), 6 deletions(-)\n>\n> This is tangent that is totally unrelated to the theme of this\n> patch, but I find that the placement of range-diff makes it very\n> hard to follow.\n>\n> After skimming the proposed log message, the next thing I would want\n> to see is the list of paths that are modified, before deciding I\n> want to review the patch now.  Once I decide to read it _now_, the\n> changes from the previous iteration and range-diff becomes relevant.\n>\n> Is it just me who decides in what order to review the patches and\n> then reviews them in that order?\n>\n> Anyway.\n>\n>> diff --git a/builtin/refs.c b/builtin/refs.c\n>> index a29f19583474518ee0942ea53c39cbdf9661c5e2..30be0254c14dd3d07693d70c25dddc9990756e9c 100644\n>> --- a/builtin/refs.c\n>> +++ b/builtin/refs.c\n>> @@ -30,6 +30,9 @@ static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,\n>>  \t\tOPT_BIT(0, \"dry-run\", &flags,\n>>  \t\t\tN_(\"perform a non-destructive dry-run\"),\n>>  \t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN),\n>> +\t\tOPT_BIT(0, \"skip-reflog\", &flags,\n>> +\t\t\tN_(\"skip migrating reflogs\"),\n>> +\t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG),\n>>  \t\tOPT_END(),\n>>  \t};\n>>  \tstruct strbuf errbuf = STRBUF_INIT;\n>\n> OK.\n>\n>> diff --git a/refs.c b/refs.c\n>> index f4094a326a9f88f979654b668cc9c3d27d83cb5d..5e8f5c06fa68d16c93ee11edd9742995eea994b6 100644\n>> --- a/refs.c\n>> +++ b/refs.c\n>> @@ -3035,9 +3035,11 @@ int repo_migrate_ref_storage_format(struct repository *repo,\n>>  \tif (ret < 0)\n>>  \t\tgoto done;\n>>\n>> -\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n>> -\tif (ret < 0)\n>> -\t\tgoto done;\n>> +\tif (!(flags & REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG)) {\n>> +\t\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n>> +\t\tif (ret < 0)\n>> +\t\t\tgoto done;\n>> +\t}\n>>\n>>  \tret = ref_transaction_commit(transaction, errbuf);\n>>  \tif (ret < 0)\n>> diff --git a/refs.h b/refs.h\n>> index a0cdd99250e8286b55808b697b0a94afac5d8319..ccee8fc6705e6e93a1c6234e7395180f8dfd815b 100644\n>> --- a/refs.h\n>> +++ b/refs.h\n>> @@ -1157,8 +1157,11 @@ int is_pseudo_ref(const char *refname);\n>>   *   - REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN: perform a dry-run migration\n>>   *     without touching the main repository. The result will be written into a\n>>   *     temporary ref storage directory.\n>> + *\n>> + *   - REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG: skip migration of reflogs.\n>>   */\n>> -#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN (1 << 0)\n>> +#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN      (1 << 0)\n>> +#define REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG (1 << 1)\n>\n> These are quite a mouthful, but they are only used between the refs\n> subsystem and \"git refs\" command, so being overly verbose and\n> specific is a good thing.\n>\n>>  /*\n>>   * Migrate the ref storage format used by the repository to the\n>> diff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh\n>> index a6d9b35a46eb59350aa0d59d982a2fbfaecf1448..28c0024a4c8cb8282bf586840265edba442f5056 100755\n>> --- a/t/t1460-refs-migrate.sh\n>> +++ b/t/t1460-refs-migrate.sh\n>> @@ -9,14 +9,16 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\n>>\n>>  # Migrate the provided repository from one format to the other and\n>>  # verify that the references and logs are migrated over correctly.\n>> -# Usage: test_migration <repo> <format> <skip_reflog_verify>\n>> +# Usage: test_migration <repo> <format> <skip_reflog_verify> <...options>\n>>  #   <repo> is the relative path to the repo to be migrated.\n>>  #   <format> is the ref format to be migrated to.\n>>  #   <skip_reflog_verify> (true or false) whether to skip reflog verification.\n>> +#   <...options> are other options be passed directly to 'git refs migrate'.\n>\n> Yuck.  I've never seen preceding three-dots.  Makes readers wonder\n> how this thing behaves differently from the usual <options...>.\n>\n> Doubly yuck is ...\n>\n\nI will change it to <options...>. Thanks for pointing out.\n\n>>  test_migration () {\n>>  \trepo=$1 &&\n>>  \tformat=$2 &&\n>>  \tskip_reflog_verify=${3:-false} &&\n>> +\tshift $(( $# >= 3 ? 3 : 2 )) &&\n>\n> ... this thing.  The above usage declares that <skip_reflog_verify>,\n> just like <repo> and <format>, are required so I do not see why we\n> need to be conditional here.  If you want to make it optional,\n> writing it this way instead ...\n>\n\nRight, so <skip_reflog_verify> and <options...> should be optional. So\nlet me change the description to be:\n\n  Usage: test_migration <repo> <format> [<skip_reflog_verify> [<options...>]]\n\nWhich is more accurate.\n\n> \trepo=$1 &&\n>         format=$2 &&\n> \tshift 2 &&\n>\n>         skip_reflog_verify=false &&\n> \tif test $# -gt 1\n> \tthen\n> \t\tskip_reflog_verify=$1\n> \t\tshift\n> \tfi\n>\n> ... would make it easier to extend when you ever want to add the\n> next optional positional parameter.\n>\n\nThanks this looks good too, let me use it :)\n\n>>  \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n>>  \t\t--format='%(refname) %(objectname) %(symref)' >expect &&\n>>  \tif ! $skip_reflog_verify\n>> @@ -25,7 +27,7 @@ test_migration () {\n>>  \t   git -C \"$repo\" reflog list >expect_log_list\n>>  \tfi &&\n>>\n>> -\tgit -C \"$repo\" refs migrate --ref-format=\"$2\" &&\n>> +\tgit -C \"$repo\" refs migrate --ref-format=\"$format\" $@ &&\n>\n> It is a good change to use the named variable we captured upfront,\n> but did you mean to leave $@ unquoted?\n>\n\nGood catch. I didn't mean to.\n\n> Unless you want to use \"$@\" to invoke the magic \"pass each parameter\n> separately, even if it has $IFS whitespace in it\" semantics,\n> choosing between $* (when you want to split a parameter into many\n> when it has $IFS whitespaces) and \"$*\" (when you want everything in\n> one string) is preferred.\n>\n\nThe intention is to keep the arguments as provided, so \"$@\" would be the\nbest choice here. Will change.\n\n>>  \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n>>  \t\t--format='%(refname) %(objectname) %(symref)' >actual &&\n>> @@ -241,6 +243,19 @@ do\n>>  \t\t\t\ttest_cmp expect.reflog actual.reflog\n>>  \t\t\t)\n>>  \t\t'\n>> +\n>> +\t\ttest_expect_success \"$from_format -> $to_format: skip reflog with --skip-reflog\" '\n>> +\t\t\ttest_when_finished \"rm -rf repo\" &&\n>> +\t\t\tgit init --ref-format=$from_format repo &&\n>> +\t\t\ttest_commit -C repo initial &&\n>> +\t\t\t# we see that the repository contains reflogs.\n>> +\t\t\tgit -C repo reflog --all >reflogs &&\n>> +\t\t\ttest_line_count = 2 reflogs &&\n>> +\t\t\ttest_migration repo \"$to_format\" true --skip-reflog &&\n>> +\t\t\t# there should be no reflogs post migration.\n>> +\t\t\tgit -C repo reflog --all >reflogs &&\n>> +\t\t\ttest_must_be_empty reflogs\n>> +\t\t'\n>>  \tdone\n>>  done\n>>\n>>\n>> ---\n>>\n>> base-commit: bc204b742735ae06f65bb20291c95985c9633b7f\n>> change-id: 20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-8066f6df50ac\n>>\n>> Thanks\n>> - Karthik\n"},{"id":"512328","messageId":"20250212-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v3-1-98b2c4d2bb0c@gmail.com","threadId":"62917","inReplyTo":"20250211-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v2-1-991a2ec9a796@gmail.com","subject":"[PATCH v3] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-02-12T18:38:52Z","receivedAt":"2025-02-12T18:38:57Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"The 'git-refs(1)' migrate subcommand, which transfers repositories\nbetween reference backends, currently migrates reflogs by default as of\n246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n\nWhile this behavior is desirable for most client-side repositories,\nserver-side repositories are not expected to contain reflogs. However,\ndue to historical reasons, some may still have them. This could be\ncaused, for example, by bugs, misconfiguration, or an administrator\nenabling reflogs on the server for debugging purposes.\n\nTo address this, introduce the --skip-reflog flag, allowing users to\nbypass reflog migration. This ensures that the repository ends up in the\nexpected state after migration.\n\nHelped-by: Patrick Steinhardt <ps@pks.im>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n builtin/refs.c          |  3 +++\n refs.c                  |  8 +++++---\n refs.h                  |  5 ++++-\n t/t1460-refs-migrate.sh | 28 ++++++++++++++++++++++++----\n 4 files changed, 36 insertions(+), 8 deletions(-)\n\nKarthik Nayak (1):\n\nbuiltin/refs: add '--skip-reflog' flag to bypass reflog migration\n---\nChanges in v3:\n- Make changes to the test:\n  - Use \"$@\" instead of $@\n  - Mark optional arguments correctly\n  - Use <options...> instead of <...options> as the former is more widely\n    used.\n- Link to v2: https://lore.kernel.org/r/20250211-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v2-1-991a2ec9a796@gmail.com\n\nChanges in v2:\n- Fix typo in commit mesasge and clarify the intent.\n- Modify the test to use `test_line_count` and `test_must_be_empty`.\n- Link to v1: https://lore.kernel.org/r/20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v1-1-7d40f3b4e30b@gmail.com\n\nRange-diff versus v2:\n\n1:  fcc313ad3b ! 1:  bbc3d154cf builtin/refs: add '--skip-reflog' flag to bypass reflog migration\n    @@ t/t1460-refs-migrate.sh: export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\n      # Migrate the provided repository from one format to the other and\n      # verify that the references and logs are migrated over correctly.\n     -# Usage: test_migration <repo> <format> <skip_reflog_verify>\n    -+# Usage: test_migration <repo> <format> <skip_reflog_verify> <...options>\n    ++# Usage: test_migration <repo> <format> [<skip_reflog_verify> [<options...>]]\n      #   <repo> is the relative path to the repo to be migrated.\n      #   <format> is the ref format to be migrated to.\n    - #   <skip_reflog_verify> (true or false) whether to skip reflog verification.\n    -+#   <...options> are other options be passed directly to 'git refs migrate'.\n    +-#   <skip_reflog_verify> (true or false) whether to skip reflog verification.\n    ++#   <skip_reflog_verify> (default: false) whether to skip reflog verification.\n    ++#   <options...> are other options be passed directly to 'git refs migrate'.\n      test_migration () {\n      \trepo=$1 &&\n      \tformat=$2 &&\n    - \tskip_reflog_verify=${3:-false} &&\n    -+\tshift $(( $# >= 3 ? 3 : 2 )) &&\n    +-\tskip_reflog_verify=${3:-false} &&\n    ++\tshift 2 &&\n    ++\tskip_reflog_verify=false &&\n    ++\tif test $# -ge 1\n    ++\tthen\n    ++\t\tskip_reflog_verify=$1\n    ++\t\tshift\n    ++\tfi &&\n      \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n      \t\t--format='%(refname) %(objectname) %(symref)' >expect &&\n      \tif ! $skip_reflog_verify\n    @@ t/t1460-refs-migrate.sh: test_migration () {\n      \tfi &&\n      \n     -\tgit -C \"$repo\" refs migrate --ref-format=\"$2\" &&\n    -+\tgit -C \"$repo\" refs migrate --ref-format=\"$format\" $@ &&\n    ++\tgit -C \"$repo\" refs migrate --ref-format=\"$format\" \"$@\" &&\n      \n      \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n      \t\t--format='%(refname) %(objectname) %(symref)' >actual &&\n\n\nbase-commit: bc204b742735ae06f65bb20291c95985c9633b7f\n\nThanks\n- Karthik\n---\n builtin/refs.c          |  3 +++\n refs.c                  |  8 +++++---\n refs.h                  |  5 ++++-\n t/t1460-refs-migrate.sh | 28 ++++++++++++++++++++++++----\n 4 files changed, 36 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin/refs.c b/builtin/refs.c\nindex a29f19583474518ee0942ea53c39cbdf9661c5e2..30be0254c14dd3d07693d70c25dddc9990756e9c 100644\n--- a/builtin/refs.c\n+++ b/builtin/refs.c\n@@ -30,6 +30,9 @@ static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,\n \t\tOPT_BIT(0, \"dry-run\", &flags,\n \t\t\tN_(\"perform a non-destructive dry-run\"),\n \t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN),\n+\t\tOPT_BIT(0, \"skip-reflog\", &flags,\n+\t\t\tN_(\"skip migrating reflogs\"),\n+\t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG),\n \t\tOPT_END(),\n \t};\n \tstruct strbuf errbuf = STRBUF_INIT;\ndiff --git a/refs.c b/refs.c\nindex f4094a326a9f88f979654b668cc9c3d27d83cb5d..5e8f5c06fa68d16c93ee11edd9742995eea994b6 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -3035,9 +3035,11 @@ int repo_migrate_ref_storage_format(struct repository *repo,\n \tif (ret < 0)\n \t\tgoto done;\n \n-\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n-\tif (ret < 0)\n-\t\tgoto done;\n+\tif (!(flags & REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG)) {\n+\t\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n+\t\tif (ret < 0)\n+\t\t\tgoto done;\n+\t}\n \n \tret = ref_transaction_commit(transaction, errbuf);\n \tif (ret < 0)\ndiff --git a/refs.h b/refs.h\nindex a0cdd99250e8286b55808b697b0a94afac5d8319..ccee8fc6705e6e93a1c6234e7395180f8dfd815b 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -1157,8 +1157,11 @@ int is_pseudo_ref(const char *refname);\n  *   - REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN: perform a dry-run migration\n  *     without touching the main repository. The result will be written into a\n  *     temporary ref storage directory.\n+ *\n+ *   - REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG: skip migration of reflogs.\n  */\n-#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN (1 << 0)\n+#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN      (1 << 0)\n+#define REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG (1 << 1)\n \n /*\n  * Migrate the ref storage format used by the repository to the\ndiff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh\nindex a6d9b35a46eb59350aa0d59d982a2fbfaecf1448..83466bde1865071ee633c738fd5c2ad9ae65bca3 100755\n--- a/t/t1460-refs-migrate.sh\n+++ b/t/t1460-refs-migrate.sh\n@@ -9,14 +9,21 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\n \n # Migrate the provided repository from one format to the other and\n # verify that the references and logs are migrated over correctly.\n-# Usage: test_migration <repo> <format> <skip_reflog_verify>\n+# Usage: test_migration <repo> <format> [<skip_reflog_verify> [<options...>]]\n #   <repo> is the relative path to the repo to be migrated.\n #   <format> is the ref format to be migrated to.\n-#   <skip_reflog_verify> (true or false) whether to skip reflog verification.\n+#   <skip_reflog_verify> (default: false) whether to skip reflog verification.\n+#   <options...> are other options be passed directly to 'git refs migrate'.\n test_migration () {\n \trepo=$1 &&\n \tformat=$2 &&\n-\tskip_reflog_verify=${3:-false} &&\n+\tshift 2 &&\n+\tskip_reflog_verify=false &&\n+\tif test $# -ge 1\n+\tthen\n+\t\tskip_reflog_verify=$1\n+\t\tshift\n+\tfi &&\n \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n \t\t--format='%(refname) %(objectname) %(symref)' >expect &&\n \tif ! $skip_reflog_verify\n@@ -25,7 +32,7 @@ test_migration () {\n \t   git -C \"$repo\" reflog list >expect_log_list\n \tfi &&\n \n-\tgit -C \"$repo\" refs migrate --ref-format=\"$2\" &&\n+\tgit -C \"$repo\" refs migrate --ref-format=\"$format\" \"$@\" &&\n \n \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n \t\t--format='%(refname) %(objectname) %(symref)' >actual &&\n@@ -241,6 +248,19 @@ do\n \t\t\t\ttest_cmp expect.reflog actual.reflog\n \t\t\t)\n \t\t'\n+\n+\t\ttest_expect_success \"$from_format -> $to_format: skip reflog with --skip-reflog\" '\n+\t\t\ttest_when_finished \"rm -rf repo\" &&\n+\t\t\tgit init --ref-format=$from_format repo &&\n+\t\t\ttest_commit -C repo initial &&\n+\t\t\t# we see that the repository contains reflogs.\n+\t\t\tgit -C repo reflog --all >reflogs &&\n+\t\t\ttest_line_count = 2 reflogs &&\n+\t\t\ttest_migration repo \"$to_format\" true --skip-reflog &&\n+\t\t\t# there should be no reflogs post migration.\n+\t\t\tgit -C repo reflog --all >reflogs &&\n+\t\t\ttest_must_be_empty reflogs\n+\t\t'\n \tdone\n done\n \n\n"},{"id":"512333","messageId":"xmqqa5aqu7g9.fsf@gitster.g","threadId":"62917","inReplyTo":"20250212-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v3-1-98b2c4d2bb0c@gmail.com","subject":"Re: [PATCH v3] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-02-12T22:25:10Z","receivedAt":"2025-02-12T22:25:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> The 'git-refs(1)' migrate subcommand, which transfers repositories\n> between reference backends, currently migrates reflogs by default as of\n> 246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n>\n> While this behavior is desirable for most client-side repositories,\n> server-side repositories are not expected to contain reflogs. However,\n> due to historical reasons, some may still have them. This could be\n> caused, for example, by bugs, misconfiguration, or an administrator\n> enabling reflogs on the server for debugging purposes.\n>\n> To address this, introduce the --skip-reflog flag, allowing users to\n> bypass reflog migration. This ensures that the repository ends up in the\n> expected state after migration.\n\nI do not quite understand the motivation behind this change.\n\nIf a repository has reflog that you do not need by mistake or\nmisconfiguration, I agree that there should be a way for you to\nremove the reflog.  Removing it while converting the ref backend may\nbe a convenient way if and only if the reason why you noticed such a\nrepository with unwanted reflog is because you were about to migrate\nit, but regardless of when you notice such refs with unwanted log,\nyou would want to be able to drop their logs.  You may not even be\nplanning to migrate your backend when you noticed that the refs have\nunwanted log, you may have already migrated long time ago when you\nnoticed that the refs have unwanted log, or you may not even be\nplanning to migrate in the first place.  Even after you migrated\nyour backend, an administrator may have to enable reflog for\ndebugging, and then after the administrator is done, then what?\nShould the backend migrated back from reftable to files and then\nback again, only to pass this --skip-reflog option?\n\nWouldn't it be a lot more flexible if you add a new subcommand\n\"drop\" to the \"git reflog\" command?\n\n"},{"id":"512353","messageId":"CAOLa=ZSDLNLYQ=zsoOqJW6KhcUqeDahNfhG-n9k1t0O6B40OnA@mail.gmail.com","threadId":"62917","inReplyTo":"xmqqa5aqu7g9.fsf@gitster.g","subject":"Re: [PATCH v3] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-02-13T09:22:40Z","receivedAt":"2025-02-13T09:22:42Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> The 'git-refs(1)' migrate subcommand, which transfers repositories\n>> between reference backends, currently migrates reflogs by default as of\n>> 246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n>>\n>> While this behavior is desirable for most client-side repositories,\n>> server-side repositories are not expected to contain reflogs. However,\n>> due to historical reasons, some may still have them. This could be\n>> caused, for example, by bugs, misconfiguration, or an administrator\n>> enabling reflogs on the server for debugging purposes.\n>>\n>> To address this, introduce the --skip-reflog flag, allowing users to\n>> bypass reflog migration. This ensures that the repository ends up in the\n>> expected state after migration.\n>\n> I do not quite understand the motivation behind this change.\n>\n> If a repository has reflog that you do not need by mistake or\n> misconfiguration, I agree that there should be a way for you to\n> remove the reflog.  Removing it while converting the ref backend may\n> be a convenient way if and only if the reason why you noticed such a\n> repository with unwanted reflog is because you were about to migrate\n> it, but regardless of when you notice such refs with unwanted log,\n> you would want to be able to drop their logs.  You may not even be\n> planning to migrate your backend when you noticed that the refs have\n> unwanted log, you may have already migrated long time ago when you\n> noticed that the refs have unwanted log, or you may not even be\n> planning to migrate in the first place.  Even after you migrated\n> your backend, an administrator may have to enable reflog for\n> debugging, and then after the administrator is done, then what?\n> Should the backend migrated back from reftable to files and then\n> back again, only to pass this --skip-reflog option?\n>\n> Wouldn't it be a lot more flexible if you add a new subcommand\n> \"drop\" to the \"git reflog\" command?\n\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> The 'git-refs(1)' migrate subcommand, which transfers repositories\n>> between reference backends, currently migrates reflogs by default as of\n>> 246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n>>\n>> While this behavior is desirable for most client-side repositories,\n>> server-side repositories are not expected to contain reflogs. However,\n>> due to historical reasons, some may still have them. This could be\n>> caused, for example, by bugs, misconfiguration, or an administrator\n>> enabling reflogs on the server for debugging purposes.\n>>\n>> To address this, introduce the --skip-reflog flag, allowing users to\n>> bypass reflog migration. This ensures that the repository ends up in the\n>> expected state after migration.\n>\n> I do not quite understand the motivation behind this change.\n>\n> If a repository has reflog that you do not need by mistake or\n> misconfiguration, I agree that there should be a way for you to\n> remove the reflog.  Removing it while converting the ref backend may\n> be a convenient way if and only if the reason why you noticed such a\n> repository with unwanted reflog is because you were about to migrate\n> it, but regardless of when you notice such refs with unwanted log,\n> you would want to be able to drop their logs.  You may not even be\n> planning to migrate your backend when you noticed that the refs have\n> unwanted log, you may have already migrated long time ago when you\n> noticed that the refs have unwanted log, or you may not even be\n> planning to migrate in the first place.  Even after you migrated\n> your backend, an administrator may have to enable reflog for\n> debugging, and then after the administrator is done, then what?\n> Should the backend migrated back from reftable to files and then\n> back again, only to pass this --skip-reflog option?\n>\n> Wouldn't it be a lot more flexible if you add a new subcommand\n> \"drop\" to the \"git reflog\" command?\n\nTo just get rid of reflogs from a repository, I think 'git reflog drop'\nor something similar would indeed be a better way to go about it. As you\nstated, with this patch, we could still face the issue wherein the\nadministartor could re-enable reflog and we're back to square one.\n\nWhy I think this patch is important, is because while there could be\nexisting reflogs in a repository, if one doesn't care about _reflogs_\nthere could be significant performance gains while migrating repos from\none backend to the other, while also leaving the reflogs behind. The\nintent of the patch is not to be a detterrent for reflogs. The `git refs\nmigrate` command is not the pathway for that. Rather, the goal is to\nensure we skip them during migraiton because we do not want to bother\nmigrating them.\n\nSaying this, another option is to have `git reflog drop` and then\nperform the migration, but I think it does makes sense to provide users\nwith a fine-tuning during migration to allow them to choose what they\nwant to migrate.\n\nI know that in GitLab we have repositories with millions of references\nand while we generally have reflogs disabled. There could be\nrepositories with reflogs enabled during debugging or just old\nrepositories where reflogs always existed. Since migrating backends\nblocks all operations on the repository, it would be vital to also\noptimize it as much as possible.\n\nThanks,\nKarthik\n"},{"id":"512354","messageId":"CAOLa=ZSzLYWLckuEsCfLyXcgrukbNUgE-LZohUeH0=LZA+47bA@mail.gmail.com","threadId":"62917","inReplyTo":"xmqqcyfoz82h.fsf@gitster.g","subject":"Re: [PATCH v2] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-02-13T09:25:16Z","receivedAt":"2025-02-13T09:25:18Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> The 'git-refs(1)' migrate subcommand, which transfers repositories\n>> between reference backends, currently migrates reflogs by default as of\n>> 246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n>>\n>> While this behavior is desirable for most client-side repositories,\n>> server-side repositories are not expected to contain reflogs. However,\n>> due to historical reasons, some may still have them. This could be\n>> caused, for example, by bugs, misconfiguration, or an administrator\n>> enabling reflogs on the server for debugging purposes.\n>>\n>> To address this, introduce the --skip-reflog flag, allowing users to\n>> bypass reflog migration. This ensures that the repository ends up in the\n>> expected state after migration.\n>>\n>> Helped-by: Patrick Steinhardt <ps@pks.im>\n>> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n>> ---\n>> Changes in v2:\n>> - Fix typo in commit mesasge and clarify the intent.\n>> - Modify the test to use `test_line_count` and `test_must_be_empty`.\n>> - Link to v1: https://lore.kernel.org/r/20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v1-1-7d40f3b4e30b@gmail.com\n>> ---\n>> Range-diff versus v1:\n>>\n>> 1:  ce14d3d07e ! 1:  6b83089348 builtin/refs: add '--skip-reflog' flag to bypass reflog migration\n>>     @@ Commit message\n>>\n>>          The 'git-refs(1)' migrate subcommand, which transfers repositories\n>>          between reference backends, currently migrates reflogs by default as of\n>> ...\n>>      +\t\t'\n>>       \tdone\n>>       done\n>> ---\n>>  builtin/refs.c          |  3 +++\n>>  refs.c                  |  8 +++++---\n>>  refs.h                  |  5 ++++-\n>>  t/t1460-refs-migrate.sh | 19 +++++++++++++++++--\n>>  4 files changed, 29 insertions(+), 6 deletions(-)\n>\n> This is tangent that is totally unrelated to the theme of this\n> patch, but I find that the placement of range-diff makes it very\n> hard to follow.\n>\n> After skimming the proposed log message, the next thing I would want\n> to see is the list of paths that are modified, before deciding I\n> want to review the patch now.  Once I decide to read it _now_, the\n> changes from the previous iteration and range-diff becomes relevant.\n>\n> Is it just me who decides in what order to review the patches and\n> then reviews them in that order?\n>\n> Anyway.\n>\n\nI missed responding to this in my previous email, but I've been using b4\nfor sending patches and this was primarily due to how it sends single\npatch series.\n\nI've fixed the template to show the diff-stat first, and this should be\nthe case for upcoming patches.\n\nThanks for pointing it out!\n\n[snip]\n"},{"id":"512369","messageId":"xmqq4j0xpvmu.fsf@gitster.g","threadId":"62917","inReplyTo":"CAOLa=ZSDLNLYQ=zsoOqJW6KhcUqeDahNfhG-n9k1t0O6B40OnA@mail.gmail.com","subject":"Re: [PATCH v3] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-02-13T18:06:17Z","receivedAt":"2025-02-13T18:06:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> To just get rid of reflogs from a repository, I think 'git reflog drop'\n> or something similar would indeed be a better way to go about it. As you\n> stated, with this patch, we could still face the issue wherein the\n> administartor could re-enable reflog and we're back to square one.\n\nExactly.\n\n> Why I think this patch is important, is because while there could be\n> existing reflogs in a repository, if one doesn't care about _reflogs_\n> there could be significant performance gains while migrating repos from\n> one backend to the other, while also leaving the reflogs behind.\n\nSure.  It could be done with a combination of \"git reflog drop &&\ngit refs migrate\" (or \"git refs migrate && git reflog drop\", if the\nmigrated-to backend performs better when it drops reflogs).\n\nWith \"git refs migrate --skip-reflog\" alone, we are very limited.\nWe can lose reflogs _only_ when we are migrating.\n\nDoing it _during_ migration may very well be more efficient than\ndropping first and then migrate (or the other way around), so I do\nnot have much against the \"migrate --skip-reflog\" existing.  But I\nfind it backwards to add it first _before_ we have a tool that is\nmore generally applicable to wider situations, i.e., \"reflog drop\".\n\nIOW, it feels as if we are worried about icing on the cake long\nbefore we actually bake the cake.\n"},{"id":"512409","messageId":"CAOLa=ZRVPkPVwJd_Ce4krf1FzqEudh-oSCDUPkjwYAmfRMP1=A@mail.gmail.com","threadId":"62917","inReplyTo":"xmqq4j0xpvmu.fsf@gitster.g","subject":"Re: [PATCH v3] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-02-14T08:50:35Z","receivedAt":"2025-02-14T08:50:36Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> To just get rid of reflogs from a repository, I think 'git reflog drop'\n>> or something similar would indeed be a better way to go about it. As you\n>> stated, with this patch, we could still face the issue wherein the\n>> administartor could re-enable reflog and we're back to square one.\n>\n> Exactly.\n>\n>> Why I think this patch is important, is because while there could be\n>> existing reflogs in a repository, if one doesn't care about _reflogs_\n>> there could be significant performance gains while migrating repos from\n>> one backend to the other, while also leaving the reflogs behind.\n>\n> Sure.  It could be done with a combination of \"git reflog drop &&\n> git refs migrate\" (or \"git refs migrate && git reflog drop\", if the\n> migrated-to backend performs better when it drops reflogs).\n>\n> With \"git refs migrate --skip-reflog\" alone, we are very limited.\n> We can lose reflogs _only_ when we are migrating.\n>\n> Doing it _during_ migration may very well be more efficient than\n> dropping first and then migrate (or the other way around), so I do\n> not have much against the \"migrate --skip-reflog\" existing.  But I\n> find it backwards to add it first _before_ we have a tool that is\n> more generally applicable to wider situations, i.e., \"reflog drop\".\n>\n> IOW, it feels as if we are worried about icing on the cake long\n> before we actually bake the cake.\n\nI understand and agree. I do see a lot of benefits having 'git reflog\ndrop' too, so I'll pick it up and send a patch series towards the same\nnext (as soon as I send in the next version of the partial transactions\nseries :), which is taking me a bit of time with some other ongoing work\nat $DAYJOB).\n\nThanks!\n"},{"id":"512659","messageId":"87a5aiqmeq.fsf@iotcl.com","threadId":"62917","inReplyTo":"20250212-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v3-1-98b2c4d2bb0c@gmail.com","subject":"Re: [PATCH v3] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Toon Claes","fromEmail":"toon@iotcl.com","sentAt":"2025-02-19T10:06:05Z","receivedAt":"2025-02-19T10:06:26Z","isPatch":true,"sender":{"key":"toon@iotcl.com","avatar":"https://avatars.githubusercontent.com/u/121621?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> The 'git-refs(1)' migrate subcommand, which transfers repositories\n> between reference backends, currently migrates reflogs by default as of\n> 246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n>\n> While this behavior is desirable for most client-side repositories,\n> server-side repositories are not expected to contain reflogs. However,\n> due to historical reasons, some may still have them. This could be\n> caused, for example, by bugs, misconfiguration, or an administrator\n> enabling reflogs on the server for debugging purposes.\n>\n> To address this, introduce the --skip-reflog flag, allowing users to\n> bypass reflog migration. This ensures that the repository ends up in the\n> expected state after migration.\n\nIt wasn't really obvious to me this change removes the reflog, instead\nof \"skipping\". So I was surprised the reflog was removed after\nmigrating, instead of staying in tact using the files backend.\n\nOnly after reading through the test and the discussion in this thread I\nrealized that's the intented behavior.\n\nSo can I suggest to name the option `--no-reflog`? To me that makes it\nmore obvious the reflog won't exist no more after migrating, and is more\nin line with the common UX of Git. Also emphasizing this more clearly in\nthe commit message and help message also would be advised.\n\n-- \nToon\n"},{"id":"512719","messageId":"xmqqwmdlg92k.fsf@gitster.g","threadId":"62917","inReplyTo":"87a5aiqmeq.fsf@iotcl.com","subject":"Re: [PATCH v3] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-02-19T17:04:19Z","receivedAt":"2025-02-19T17:04:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Toon Claes <toon@iotcl.com> writes:\n\n> So can I suggest to name the option `--no-reflog`? To me that makes it\n> more obvious the reflog won't exist no more after migrating, and is more\n> in line with the common UX of Git. Also emphasizing this more clearly in\n> the commit message and help message also would be advised.\n\nI have always thought, until I saw the message I am responding to,\nthat everybody would expect that \"migrate --skip=X --skip=Y\" that\nusually migrates X and Y and Z would lose X and Y with the\ntransition.  But I realized that it was most likely because I happen\nto know that the choice between reftable and files backends is\n\"which one do you take, you cannot have both at the same time\", and\nit was clear that \"skip and keep using the old form\" is not on the\ntable.  For all others, your interpretation of the option name is\nentirely plausible.  So I agree `--no-reflog` is really an excellent\nsuggestion, even though `--reflog` option would be a no-op, and\n`--no-refs` would be a \"Huh?\" option that only logically makes sense\nto have for completeness but nobody would want to use ;-)\n\n\n\n\n"},{"id":"512729","messageId":"CAOLa=ZT025hWSG0JuoWTUe5aDgPg1fcHDaAhuQ+CxHQ2zvreXw@mail.gmail.com","threadId":"62917","inReplyTo":"xmqqwmdlg92k.fsf@gitster.g","subject":"Re: [PATCH v3] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-02-19T20:28:02Z","receivedAt":"2025-02-19T20:28:04Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Toon Claes <toon@iotcl.com> writes:\n>\n>> So can I suggest to name the option `--no-reflog`? To me that makes it\n>> more obvious the reflog won't exist no more after migrating, and is more\n>> in line with the common UX of Git. Also emphasizing this more clearly in\n>> the commit message and help message also would be advised.\n>\n> I have always thought, until I saw the message I am responding to,\n> that everybody would expect that \"migrate --skip=X --skip=Y\" that\n> usually migrates X and Y and Z would lose X and Y with the\n> transition.  But I realized that it was most likely because I happen\n> to know that the choice between reftable and files backends is\n> \"which one do you take, you cannot have both at the same time\", and\n> it was clear that \"skip and keep using the old form\" is not on the\n> table.  For all others, your interpretation of the option name is\n> entirely plausible.  So I agree `--no-reflog` is really an excellent\n> suggestion, even though `--reflog` option would be a no-op, and\n> `--no-refs` would be a \"Huh?\" option that only logically makes sense\n> to have for completeness but nobody would want to use ;-)\n\nI share the same reaction. I didn't consider that flow of thought at\nall. So I too agree with name change. Let me push in a new version.\nAlthough I'm not sure if, Junio, you want to wait for the `git reflog\ndrop` command that we were discussing before accepting this topic [1].\nI'll leave that to your discretion.\n\n[1]: https://lore.kernel.org/all/xmqq4j0xpvmu.fsf@gitster.g/\n"},{"id":"512744","messageId":"xmqqcyfdfwf5.fsf@gitster.g","threadId":"62917","inReplyTo":"CAOLa=ZT025hWSG0JuoWTUe5aDgPg1fcHDaAhuQ+CxHQ2zvreXw@mail.gmail.com","subject":"Re: [PATCH v3] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-02-19T21:37:34Z","receivedAt":"2025-02-19T21:37:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> I share the same reaction. I didn't consider that flow of thought at\n> all. So I too agree with name change. Let me push in a new version.\n> Although I'm not sure if, Junio, you want to wait for the `git reflog\n> drop` command that we were discussing before accepting this topic [1].\n> I'll leave that to your discretion.\n\nWell, from my point of view, \"reflog drop\", if can be done for both\nfiles and reftable without too much hassle, would be a greater\naddition to the toolset than the value \"you can drop while\nmigrating, but you need to remember to pass that option\" gives us\n;-)\n\nSo it really depends on how involved the work to add \"drop\" thing\nwould be.\n\nThanks.\n"},{"id":"512765","messageId":"20250220095614.62042-1-karthik.188@gmail.com","threadId":"62917","inReplyTo":"20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v1-1-7d40f3b4e30b@gmail.com","subject":"[PATCH v4] builtin/refs: add '--no-reflog' flag to drop reflogs","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-02-20T09:56:14Z","receivedAt":"2025-02-20T09:56:23Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"The 'git-refs(1)' migrate subcommand, which transfers repositories\nbetween reference backends, currently migrates reflogs by default as of\n246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n\nWhile this behavior is desirable for most client-side repositories,\nserver-side repositories are not expected to contain reflogs. However,\ndue to historical reasons, some may still have them. This could be\ncaused, for example, by bugs, misconfiguration, or an administrator\nenabling reflogs on the server for debugging purposes.\n\nTo handle this, introduce the '--no-reflog' flag, which skips reflog\nmigration. When this flag is used, reflogs from the original reference\nbackend are not transferred, and since only the new reference backend\nremains in the repository, all previous reflogs are permanently removed.\n\nHelped-by: Patrick Steinhardt <ps@pks.im>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n builtin/refs.c          |  3 +++\n refs.c                  |  8 +++++---\n refs.h                  |  5 ++++-\n t/t1460-refs-migrate.sh | 28 ++++++++++++++++++++++++----\n 4 files changed, 36 insertions(+), 8 deletions(-)\n\nChanges in v4:\n- Modify the flag to `--no-reflog` to better indicate that reflogs will\n  be dropped during the migration. This is also reflected in the help text\n  and the commit message.\n\nChanges in v3:\n- Make changes to the test:\n  - Use \"$@\" instead of $@\n  - Mark optional arguments correctly\n  - Use <options...> instead of <...options> as the former is more widely\n    used.\n- Link to v2: https://lore.kernel.org/r/20250211-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v2-1-991a2ec9a796@gmail.com\n\nChanges in v2:\n- Fix typo in commit mesasge and clarify the intent.\n- Modify the test to use `test_line_count` and `test_must_be_empty`.\n- Link to v1: https://lore.kernel.org/r/20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v1-1-7d40f3b4e30b@gmail.com\n\nRange-diff:\n\n1:  42c40d9617 ! 1:  3a02e8e526 builtin/refs: add '--skip-reflog' flag to bypass reflog migration\n    @@ Metadata\n     Author: Karthik Nayak <karthik.188@gmail.com>\n     \n      ## Commit message ##\n    -    builtin/refs: add '--skip-reflog' flag to bypass reflog migration\n    +    builtin/refs: add '--no-reflog' flag to drop reflogs\n     \n         The 'git-refs(1)' migrate subcommand, which transfers repositories\n         between reference backends, currently migrates reflogs by default as of\n    @@ Commit message\n         caused, for example, by bugs, misconfiguration, or an administrator\n         enabling reflogs on the server for debugging purposes.\n     \n    -    To address this, introduce the --skip-reflog flag, allowing users to\n    -    bypass reflog migration. This ensures that the repository ends up in the\n    -    expected state after migration.\n    +    To handle this, introduce the '--no-reflog' flag, which skips reflog\n    +    migration. When this flag is used, reflogs from the original reference\n    +    backend are not transferred, and since only the new reference backend\n    +    remains in the repository, all previous reflogs are permanently removed.\n     \n         Helped-by: Patrick Steinhardt <ps@pks.im>\n         Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n    @@ builtin/refs.c: static int cmd_refs_migrate(int argc, const char **argv, const c\n      \t\tOPT_BIT(0, \"dry-run\", &flags,\n      \t\t\tN_(\"perform a non-destructive dry-run\"),\n      \t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN),\n    -+\t\tOPT_BIT(0, \"skip-reflog\", &flags,\n    -+\t\t\tN_(\"skip migrating reflogs\"),\n    ++\t\tOPT_BIT(0, \"no-reflog\", &flags,\n    ++\t\t\tN_(\"drop reflogs entirely during the migration\"),\n     +\t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG),\n      \t\tOPT_END(),\n      \t};\n    @@ t/t1460-refs-migrate.sh: do\n     +\t\t\t# we see that the repository contains reflogs.\n     +\t\t\tgit -C repo reflog --all >reflogs &&\n     +\t\t\ttest_line_count = 2 reflogs &&\n    -+\t\t\ttest_migration repo \"$to_format\" true --skip-reflog &&\n    ++\t\t\ttest_migration repo \"$to_format\" true --no-reflog &&\n     +\t\t\t# there should be no reflogs post migration.\n     +\t\t\tgit -C repo reflog --all >reflogs &&\n     +\t\t\ttest_must_be_empty reflogs\n\n---\n\ndiff --git a/builtin/refs.c b/builtin/refs.c\nindex a29f195834..c459507d51 100644\n--- a/builtin/refs.c\n+++ b/builtin/refs.c\n@@ -30,6 +30,9 @@ static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,\n \t\tOPT_BIT(0, \"dry-run\", &flags,\n \t\t\tN_(\"perform a non-destructive dry-run\"),\n \t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN),\n+\t\tOPT_BIT(0, \"no-reflog\", &flags,\n+\t\t\tN_(\"drop reflogs entirely during the migration\"),\n+\t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG),\n \t\tOPT_END(),\n \t};\n \tstruct strbuf errbuf = STRBUF_INIT;\ndiff --git a/refs.c b/refs.c\nindex f4094a326a..5e8f5c06fa 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -3035,9 +3035,11 @@ int repo_migrate_ref_storage_format(struct repository *repo,\n \tif (ret < 0)\n \t\tgoto done;\n \n-\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n-\tif (ret < 0)\n-\t\tgoto done;\n+\tif (!(flags & REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG)) {\n+\t\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n+\t\tif (ret < 0)\n+\t\t\tgoto done;\n+\t}\n \n \tret = ref_transaction_commit(transaction, errbuf);\n \tif (ret < 0)\ndiff --git a/refs.h b/refs.h\nindex a0cdd99250..ccee8fc670 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -1157,8 +1157,11 @@ int is_pseudo_ref(const char *refname);\n  *   - REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN: perform a dry-run migration\n  *     without touching the main repository. The result will be written into a\n  *     temporary ref storage directory.\n+ *\n+ *   - REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG: skip migration of reflogs.\n  */\n-#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN (1 << 0)\n+#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN      (1 << 0)\n+#define REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG (1 << 1)\n \n /*\n  * Migrate the ref storage format used by the repository to the\ndiff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh\nindex a6d9b35a46..2ab97e1b7d 100755\n--- a/t/t1460-refs-migrate.sh\n+++ b/t/t1460-refs-migrate.sh\n@@ -9,14 +9,21 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\n \n # Migrate the provided repository from one format to the other and\n # verify that the references and logs are migrated over correctly.\n-# Usage: test_migration <repo> <format> <skip_reflog_verify>\n+# Usage: test_migration <repo> <format> [<skip_reflog_verify> [<options...>]]\n #   <repo> is the relative path to the repo to be migrated.\n #   <format> is the ref format to be migrated to.\n-#   <skip_reflog_verify> (true or false) whether to skip reflog verification.\n+#   <skip_reflog_verify> (default: false) whether to skip reflog verification.\n+#   <options...> are other options be passed directly to 'git refs migrate'.\n test_migration () {\n \trepo=$1 &&\n \tformat=$2 &&\n-\tskip_reflog_verify=${3:-false} &&\n+\tshift 2 &&\n+\tskip_reflog_verify=false &&\n+\tif test $# -ge 1\n+\tthen\n+\t\tskip_reflog_verify=$1\n+\t\tshift\n+\tfi &&\n \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n \t\t--format='%(refname) %(objectname) %(symref)' >expect &&\n \tif ! $skip_reflog_verify\n@@ -25,7 +32,7 @@ test_migration () {\n \t   git -C \"$repo\" reflog list >expect_log_list\n \tfi &&\n \n-\tgit -C \"$repo\" refs migrate --ref-format=\"$2\" &&\n+\tgit -C \"$repo\" refs migrate --ref-format=\"$format\" \"$@\" &&\n \n \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n \t\t--format='%(refname) %(objectname) %(symref)' >actual &&\n@@ -241,6 +248,19 @@ do\n \t\t\t\ttest_cmp expect.reflog actual.reflog\n \t\t\t)\n \t\t'\n+\n+\t\ttest_expect_success \"$from_format -> $to_format: skip reflog with --skip-reflog\" '\n+\t\t\ttest_when_finished \"rm -rf repo\" &&\n+\t\t\tgit init --ref-format=$from_format repo &&\n+\t\t\ttest_commit -C repo initial &&\n+\t\t\t# we see that the repository contains reflogs.\n+\t\t\tgit -C repo reflog --all >reflogs &&\n+\t\t\ttest_line_count = 2 reflogs &&\n+\t\t\ttest_migration repo \"$to_format\" true --no-reflog &&\n+\t\t\t# there should be no reflogs post migration.\n+\t\t\tgit -C repo reflog --all >reflogs &&\n+\t\t\ttest_must_be_empty reflogs\n+\t\t'\n \tdone\n done\n \n-- \n2.47.2\n\n"},{"id":"512766","messageId":"CAOLa=ZQRjYb23-Y1TL9R8Bt6Wc+aKjEavwfUJ6miFB9JBLNyLQ@mail.gmail.com","threadId":"62917","inReplyTo":"xmqqcyfdfwf5.fsf@gitster.g","subject":"Re: [PATCH v3] builtin/refs: add '--skip-reflog' flag to bypass reflog migration","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-02-20T10:00:14Z","receivedAt":"2025-02-20T10:00:16Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> I share the same reaction. I didn't consider that flow of thought at\n>> all. So I too agree with name change. Let me push in a new version.\n>> Although I'm not sure if, Junio, you want to wait for the `git reflog\n>> drop` command that we were discussing before accepting this topic [1].\n>> I'll leave that to your discretion.\n>\n> Well, from my point of view, \"reflog drop\", if can be done for both\n> files and reftable without too much hassle, would be a greater\n> addition to the toolset than the value \"you can drop while\n> migrating, but you need to remember to pass that option\" gives us\n> ;-)\n>\n\nI'm still dedicated to pick it up as the next topic that I'd be working\non. So overall I would like both of these topics to land.\n\n> So it really depends on how involved the work to add \"drop\" thing\n> would be.\n>\n> Thanks.\n"},{"id":"512775","messageId":"xmqqikp4eji8.fsf@gitster.g","threadId":"62917","inReplyTo":"20250220095614.62042-1-karthik.188@gmail.com","subject":"Re: [PATCH v4] builtin/refs: add '--no-reflog' flag to drop reflogs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-02-20T15:14:07Z","receivedAt":"2025-02-20T15:14:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> The 'git-refs(1)' migrate subcommand, which transfers repositories\n> between reference backends, currently migrates reflogs by default as of\n> 246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n\n\"transfer\" is a curious verb to use here, as it almost exclusively\nis used in the context of fetch-and-push object transfer over the\nwire.  \n\n\tThe \"git refs migrate\" subcommand converts the backend used\n\tfor ref storage.  It always migrates reflog data as well as\n\trefs.  Allow it to optionally discard reflog data.  This is\n\tuseful because ...\n\nor something?\n\n>  builtin/refs.c          |  3 +++\n>  refs.c                  |  8 +++++---\n>  refs.h                  |  5 ++++-\n>  t/t1460-refs-migrate.sh | 28 ++++++++++++++++++++++++----\n>  4 files changed, 36 insertions(+), 8 deletions(-)\n\nI notice there is something missing.\n\n> diff --git a/builtin/refs.c b/builtin/refs.c\n> index a29f195834..c459507d51 100644\n> --- a/builtin/refs.c\n> +++ b/builtin/refs.c\n> ...\n> +\t\tOPT_BIT(0, \"no-reflog\", &flags,\n> +\t\t\tN_(\"drop reflogs entirely during the migration\"),\n> +\t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG),\n\nThis is somewhat ugly, but parseopt API is nice enough to hide the\n\"--no-no-reflog\" nonsense from the end users, so this is OK.\n\nI think we are almost there but lack documentation updates?\n\n Documentation/git-refs.txt | 11 ++++++++---\n 1 file changed, 8 insertions(+), 3 deletions(-)\n\ndiff --git c/Documentation/git-refs.txt w/Documentation/git-refs.txt\nindex 9829984b0a..bb50d6f888 100644\n--- c/Documentation/git-refs.txt\n+++ w/Documentation/git-refs.txt\n@@ -8,9 +8,9 @@ git-refs - Low-level access to refs\n \n SYNOPSIS\n --------\n-[verse]\n-'git refs migrate' --ref-format=<format> [--dry-run]\n-'git refs verify' [--strict] [--verbose]\n+[synopsis]\n+git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]\n+git refs verify [--strict] [--verbose]\n \n DESCRIPTION\n -----------\n@@ -43,6 +43,11 @@ include::ref-storage-format.txt[]\n \tcan be used to double check that the migration works as expected before\n \tperforming the actual migration.\n \n+--reflog::\n+--no-reflog::\n+\tChoose between migrating the reflog data to the new backend,\n+\tand discarding them.  The default is \"--reflog\" to migrate.\n+\n The following options are specific to 'git refs verify':\n \n --strict::\n"},{"id":"512811","messageId":"CAOLa=ZSL-X_8s6vcDiWBp8G3+M8GGGA1wBRtNqqThyq94YS16w@mail.gmail.com","threadId":"62917","inReplyTo":"xmqqikp4eji8.fsf@gitster.g","subject":"Re: [PATCH v4] builtin/refs: add '--no-reflog' flag to drop reflogs","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-02-21T08:44:05Z","receivedAt":"2025-02-21T08:44:07Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"FJunio C Hamano <gitster@pobox.com> writes:\n\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> The 'git-refs(1)' migrate subcommand, which transfers repositories\n>> between reference backends, currently migrates reflogs by default as of\n>> 246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n>\n> \"transfer\" is a curious verb to use here, as it almost exclusively\n> is used in the context of fetch-and-push object transfer over the\n> wire.\n>\n> \tThe \"git refs migrate\" subcommand converts the backend used\n> \tfor ref storage.  It always migrates reflog data as well as\n> \trefs.  Allow it to optionally discard reflog data.  This is\n> \tuseful because ...\n>\n> or something?\n>\n\nSure, I'll modify it to something along these lines :)\n\n>>  builtin/refs.c          |  3 +++\n>>  refs.c                  |  8 +++++---\n>>  refs.h                  |  5 ++++-\n>>  t/t1460-refs-migrate.sh | 28 ++++++++++++++++++++++++----\n>>  4 files changed, 36 insertions(+), 8 deletions(-)\n>\n> I notice there is something missing.\n>\n\nFor a minute I thought I broke something here, but I'm assuming you mean\nthe lack of documentation.\n\n>\n>> diff --git a/builtin/refs.c b/builtin/refs.c\n>> index a29f195834..c459507d51 100644\n>> --- a/builtin/refs.c\n>> +++ b/builtin/refs.c\n>> ...\n>> +\t\tOPT_BIT(0, \"no-reflog\", &flags,\n>> +\t\t\tN_(\"drop reflogs entirely during the migration\"),\n>> +\t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG),\n>\n> This is somewhat ugly, but parseopt API is nice enough to hide the\n> \"--no-no-reflog\" nonsense from the end users, so this is OK.\n>\n> I think we are almost there but lack documentation updates?\n>\n\nYeah, this was a total miss. Thanks for pointing out. Will add it in.\n\n>\n>  Documentation/git-refs.txt | 11 ++++++++---\n>  1 file changed, 8 insertions(+), 3 deletions(-)\n>\n> diff --git c/Documentation/git-refs.txt w/Documentation/git-refs.txt\n> index 9829984b0a..bb50d6f888 100644\n> --- c/Documentation/git-refs.txt\n> +++ w/Documentation/git-refs.txt\n> @@ -8,9 +8,9 @@ git-refs - Low-level access to refs\n>\n>  SYNOPSIS\n>  --------\n> -[verse]\n> -'git refs migrate' --ref-format=<format> [--dry-run]\n> -'git refs verify' [--strict] [--verbose]\n> +[synopsis]\n\nI see '[synopsis]' being called out in 'Documentation/CodingGuidelines',\nbut nothing about '[verse]'.\n\n> +git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]\n> +git refs verify [--strict] [--verbose]\n>\n>  DESCRIPTION\n>  -----------\n> @@ -43,6 +43,11 @@ include::ref-storage-format.txt[]\n>  \tcan be used to double check that the migration works as expected before\n>  \tperforming the actual migration.\n>\n> +--reflog::\n> +--no-reflog::\n> +\tChoose between migrating the reflog data to the new backend,\n> +\tand discarding them.  The default is \"--reflog\" to migrate.\n> +\n>  The following options are specific to 'git refs verify':\n>\n>  --strict::\n\nWill add this in! Thanks for the review.\n"},{"id":"512817","messageId":"20250221100423.91075-1-karthik.188@gmail.com","threadId":"62917","inReplyTo":"20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v1-1-7d40f3b4e30b@gmail.com","subject":"[PATCH v5] builtin/refs: add '--no-reflog' flag to drop reflogs","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-02-21T10:04:23Z","receivedAt":"2025-02-21T10:04:27Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"The \"git refs migrate\" subcommand converts the backend used for ref\nstorage. It always migrates reflog data as well as refs. Introduce an\noption to exclude reflogs from migration, allowing them to be discarded\nwhen they are unnecessary.\n\nThis is particularly useful in server-side repositories, where reflogs\nare typically not expected. However, some repositories may still have\nthem due to historical reasons, such as bugs, misconfigurations, or\nadministrative decisions to enable reflogs for debugging. In such\nrepositories, it would be optimal to drop reflogs during the migration.\n\nTo address this, introduce the '--no-reflog' flag, which prevents reflog\nmigration. When this flag is used, reflogs from the original reference\nbackend are migrated. Since only the new reference backend remains in\nthe repository, all previous reflogs are permanently discarded.\n\nHelped-by: Junio C Hamano <gitster@pobox.com>\nHelped-by: Patrick Steinhardt <ps@pks.im>\nSigned-off-by: Karthik Nayak <karthik.188@gmail.com>\n---\n Documentation/git-refs.txt | 11 ++++++++---\n builtin/refs.c             |  3 +++\n refs.c                     |  8 +++++---\n refs.h                     |  5 ++++-\n t/t1460-refs-migrate.sh    | 28 ++++++++++++++++++++++++----\n 5 files changed, 44 insertions(+), 11 deletions(-)\n\nChanges in v5:\n- Add missing documentation and cleanup the commit message.\n- I also see that 'git-refs.txt' in master has been renamed to 'git-refs.adoc',\n  but I'm going to avoid rebasing on latest master, since the resolution is\n  quite simple here. Happy to do it if needed. \n\nChanges in v4:\n- Modify the flag to `--no-reflog` to better indicate that reflogs will\n  be dropped during the migration. This is also reflected in the help text\n  and the commit message.\n\nChanges in v3:\n- Make changes to the test:\n  - Use \"$@\" instead of $@\n  - Mark optional arguments correctly\n  - Use <options...> instead of <...options> as the former is more widely\n    used.\n- Link to v2: https://lore.kernel.org/r/20250211-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v2-1-991a2ec9a796@gmail.com\n\nChanges in v2:\n- Fix typo in commit mesasge and clarify the intent.\n- Modify the test to use `test_line_count` and `test_must_be_empty`.\n- Link to v1: https://lore.kernel.org/r/20250207-477-refs-migrate-add-a-flag-to-ignore-reflogs-during-migration-v1-1-7d40f3b4e30b@gmail.com\n\nRange-diff:\n\n1:  3a02e8e526 ! 1:  f0c11e6a4d builtin/refs: add '--no-reflog' flag to drop reflogs\n    @@ Metadata\n      ## Commit message ##\n         builtin/refs: add '--no-reflog' flag to drop reflogs\n     \n    -    The 'git-refs(1)' migrate subcommand, which transfers repositories\n    -    between reference backends, currently migrates reflogs by default as of\n    -    246cebe320 (refs: add support for migrating reflogs, 2024-12-16).\n    +    The \"git refs migrate\" subcommand converts the backend used for ref\n    +    storage. It always migrates reflog data as well as refs. Introduce an\n    +    option to exclude reflogs from migration, allowing them to be discarded\n    +    when they are unnecessary.\n     \n    -    While this behavior is desirable for most client-side repositories,\n    -    server-side repositories are not expected to contain reflogs. However,\n    -    due to historical reasons, some may still have them. This could be\n    -    caused, for example, by bugs, misconfiguration, or an administrator\n    -    enabling reflogs on the server for debugging purposes.\n    +    This is particularly useful in server-side repositories, where reflogs\n    +    are typically not expected. However, some repositories may still have\n    +    them due to historical reasons, such as bugs, misconfigurations, or\n    +    administrative decisions to enable reflogs for debugging. In such\n    +    repositories, it would be optimal to drop reflogs during the migration.\n     \n    -    To handle this, introduce the '--no-reflog' flag, which skips reflog\n    +    To address this, introduce the '--no-reflog' flag, which prevents reflog\n         migration. When this flag is used, reflogs from the original reference\n    -    backend are not transferred, and since only the new reference backend\n    -    remains in the repository, all previous reflogs are permanently removed.\n    +    backend are migrated. Since only the new reference backend remains in\n    +    the repository, all previous reflogs are permanently discarded.\n     \n    +    Helped-by: Junio C Hamano <gitster@pobox.com>\n         Helped-by: Patrick Steinhardt <ps@pks.im>\n         Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n     \n    + ## Documentation/git-refs.txt ##\n    +@@ Documentation/git-refs.txt: git-refs - Low-level access to refs\n    + \n    + SYNOPSIS\n    + --------\n    +-[verse]\n    +-'git refs migrate' --ref-format=<format> [--dry-run]\n    +-'git refs verify' [--strict] [--verbose]\n    ++[synopsis]\n    ++git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]\n    ++git refs verify [--strict] [--verbose]\n    + \n    + DESCRIPTION\n    + -----------\n    +@@ Documentation/git-refs.txt: include::ref-storage-format.txt[]\n    + \tcan be used to double check that the migration works as expected before\n    + \tperforming the actual migration.\n    + \n    ++--reflog::\n    ++--no-reflog::\n    ++\tChoose between migrating the reflog data to the new backend,\n    ++\tand discarding them.  The default is \"--reflog\", to migrate.\n    ++\n    + The following options are specific to 'git refs verify':\n    + \n    + --strict::\n    +\n      ## builtin/refs.c ##\n     @@ builtin/refs.c: static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,\n      \t\tOPT_BIT(0, \"dry-run\", &flags,\n\n---\n\ndiff --git a/Documentation/git-refs.txt b/Documentation/git-refs.txt\nindex 9829984b0a..733ada7d51 100644\n--- a/Documentation/git-refs.txt\n+++ b/Documentation/git-refs.txt\n@@ -8,9 +8,9 @@ git-refs - Low-level access to refs\n \n SYNOPSIS\n --------\n-[verse]\n-'git refs migrate' --ref-format=<format> [--dry-run]\n-'git refs verify' [--strict] [--verbose]\n+[synopsis]\n+git refs migrate --ref-format=<format> [--no-reflog] [--dry-run]\n+git refs verify [--strict] [--verbose]\n \n DESCRIPTION\n -----------\n@@ -43,6 +43,11 @@ include::ref-storage-format.txt[]\n \tcan be used to double check that the migration works as expected before\n \tperforming the actual migration.\n \n+--reflog::\n+--no-reflog::\n+\tChoose between migrating the reflog data to the new backend,\n+\tand discarding them.  The default is \"--reflog\", to migrate.\n+\n The following options are specific to 'git refs verify':\n \n --strict::\ndiff --git a/builtin/refs.c b/builtin/refs.c\nindex a29f195834..c459507d51 100644\n--- a/builtin/refs.c\n+++ b/builtin/refs.c\n@@ -30,6 +30,9 @@ static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,\n \t\tOPT_BIT(0, \"dry-run\", &flags,\n \t\t\tN_(\"perform a non-destructive dry-run\"),\n \t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN),\n+\t\tOPT_BIT(0, \"no-reflog\", &flags,\n+\t\t\tN_(\"drop reflogs entirely during the migration\"),\n+\t\t\tREPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG),\n \t\tOPT_END(),\n \t};\n \tstruct strbuf errbuf = STRBUF_INIT;\ndiff --git a/refs.c b/refs.c\nindex f4094a326a..5e8f5c06fa 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -3035,9 +3035,11 @@ int repo_migrate_ref_storage_format(struct repository *repo,\n \tif (ret < 0)\n \t\tgoto done;\n \n-\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n-\tif (ret < 0)\n-\t\tgoto done;\n+\tif (!(flags & REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG)) {\n+\t\tret = refs_for_each_reflog(old_refs, migrate_one_reflog, &data);\n+\t\tif (ret < 0)\n+\t\t\tgoto done;\n+\t}\n \n \tret = ref_transaction_commit(transaction, errbuf);\n \tif (ret < 0)\ndiff --git a/refs.h b/refs.h\nindex a0cdd99250..ccee8fc670 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -1157,8 +1157,11 @@ int is_pseudo_ref(const char *refname);\n  *   - REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN: perform a dry-run migration\n  *     without touching the main repository. The result will be written into a\n  *     temporary ref storage directory.\n+ *\n+ *   - REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG: skip migration of reflogs.\n  */\n-#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN (1 << 0)\n+#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN      (1 << 0)\n+#define REPO_MIGRATE_REF_STORAGE_FORMAT_SKIP_REFLOG (1 << 1)\n \n /*\n  * Migrate the ref storage format used by the repository to the\ndiff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh\nindex a6d9b35a46..2ab97e1b7d 100755\n--- a/t/t1460-refs-migrate.sh\n+++ b/t/t1460-refs-migrate.sh\n@@ -9,14 +9,21 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\n \n # Migrate the provided repository from one format to the other and\n # verify that the references and logs are migrated over correctly.\n-# Usage: test_migration <repo> <format> <skip_reflog_verify>\n+# Usage: test_migration <repo> <format> [<skip_reflog_verify> [<options...>]]\n #   <repo> is the relative path to the repo to be migrated.\n #   <format> is the ref format to be migrated to.\n-#   <skip_reflog_verify> (true or false) whether to skip reflog verification.\n+#   <skip_reflog_verify> (default: false) whether to skip reflog verification.\n+#   <options...> are other options be passed directly to 'git refs migrate'.\n test_migration () {\n \trepo=$1 &&\n \tformat=$2 &&\n-\tskip_reflog_verify=${3:-false} &&\n+\tshift 2 &&\n+\tskip_reflog_verify=false &&\n+\tif test $# -ge 1\n+\tthen\n+\t\tskip_reflog_verify=$1\n+\t\tshift\n+\tfi &&\n \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n \t\t--format='%(refname) %(objectname) %(symref)' >expect &&\n \tif ! $skip_reflog_verify\n@@ -25,7 +32,7 @@ test_migration () {\n \t   git -C \"$repo\" reflog list >expect_log_list\n \tfi &&\n \n-\tgit -C \"$repo\" refs migrate --ref-format=\"$2\" &&\n+\tgit -C \"$repo\" refs migrate --ref-format=\"$format\" \"$@\" &&\n \n \tgit -C \"$repo\" for-each-ref --include-root-refs \\\n \t\t--format='%(refname) %(objectname) %(symref)' >actual &&\n@@ -241,6 +248,19 @@ do\n \t\t\t\ttest_cmp expect.reflog actual.reflog\n \t\t\t)\n \t\t'\n+\n+\t\ttest_expect_success \"$from_format -> $to_format: skip reflog with --skip-reflog\" '\n+\t\t\ttest_when_finished \"rm -rf repo\" &&\n+\t\t\tgit init --ref-format=$from_format repo &&\n+\t\t\ttest_commit -C repo initial &&\n+\t\t\t# we see that the repository contains reflogs.\n+\t\t\tgit -C repo reflog --all >reflogs &&\n+\t\t\ttest_line_count = 2 reflogs &&\n+\t\t\ttest_migration repo \"$to_format\" true --no-reflog &&\n+\t\t\t# there should be no reflogs post migration.\n+\t\t\tgit -C repo reflog --all >reflogs &&\n+\t\t\ttest_must_be_empty reflogs\n+\t\t'\n \tdone\n done\n \n-- \n2.47.2\n\n"},{"id":"512838","messageId":"xmqq8qpzb2vb.fsf@gitster.g","threadId":"62917","inReplyTo":"20250221100423.91075-1-karthik.188@gmail.com","subject":"Re: [PATCH v5] builtin/refs: add '--no-reflog' flag to drop reflogs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-02-21T17:54:00Z","receivedAt":"2025-02-21T17:54:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karthik Nayak <karthik.188@gmail.com> writes:\n\n> The \"git refs migrate\" subcommand converts the backend used for ref\n> storage. It always migrates reflog data as well as refs. Introduce an\n> option to exclude reflogs from migration, allowing them to be discarded\n> when they are unnecessary.\n>\n> This is particularly useful in server-side repositories, where reflogs\n> are typically not expected. However, some repositories may still have\n> them due to historical reasons, such as bugs, misconfigurations, or\n> administrative decisions to enable reflogs for debugging. In such\n> repositories, it would be optimal to drop reflogs during the migration.\n>\n> To address this, introduce the '--no-reflog' flag, which prevents reflog\n> migration. When this flag is used, reflogs from the original reference\n> backend are migrated. Since only the new reference backend remains in\n> the repository, all previous reflogs are permanently discarded.\n>\n> Helped-by: Junio C Hamano <gitster@pobox.com>\n> Helped-by: Patrick Steinhardt <ps@pks.im>\n> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n> ---\n>  Documentation/git-refs.txt | 11 ++++++++---\n>  builtin/refs.c             |  3 +++\n>  refs.c                     |  8 +++++---\n>  refs.h                     |  5 ++++-\n>  t/t1460-refs-migrate.sh    | 28 ++++++++++++++++++++++++----\n>  5 files changed, 44 insertions(+), 11 deletions(-)\n>\n> Changes in v5:\n> - Add missing documentation and cleanup the commit message.\n> - I also see that 'git-refs.txt' in master has been renamed to 'git-refs.adoc',\n>   but I'm going to avoid rebasing on latest master, since the resolution is\n>   quite simple here. Happy to do it if needed. \n\nIt is a good rule of thumb to refrain from rebasing when in doubt.\n\nShall we declare victory and mark the topic for 'next' by now?\n\nThanks.\n"},{"id":"512884","messageId":"CAOLa=ZTTMZVq-2xWJtHXOcro7vd68SV7kHYXvChxFgDs1SL34Q@mail.gmail.com","threadId":"62917","inReplyTo":"xmqq8qpzb2vb.fsf@gitster.g","subject":"Re: [PATCH v5] builtin/refs: add '--no-reflog' flag to drop reflogs","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2025-02-23T20:30:17Z","receivedAt":"2025-02-23T20:30:19Z","isPatch":true,"sender":{"key":"karthik.188@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1786334?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Karthik Nayak <karthik.188@gmail.com> writes:\n>\n>> The \"git refs migrate\" subcommand converts the backend used for ref\n>> storage. It always migrates reflog data as well as refs. Introduce an\n>> option to exclude reflogs from migration, allowing them to be discarded\n>> when they are unnecessary.\n>>\n>> This is particularly useful in server-side repositories, where reflogs\n>> are typically not expected. However, some repositories may still have\n>> them due to historical reasons, such as bugs, misconfigurations, or\n>> administrative decisions to enable reflogs for debugging. In such\n>> repositories, it would be optimal to drop reflogs during the migration.\n>>\n>> To address this, introduce the '--no-reflog' flag, which prevents reflog\n>> migration. When this flag is used, reflogs from the original reference\n>> backend are migrated. Since only the new reference backend remains in\n>> the repository, all previous reflogs are permanently discarded.\n>>\n>> Helped-by: Junio C Hamano <gitster@pobox.com>\n>> Helped-by: Patrick Steinhardt <ps@pks.im>\n>> Signed-off-by: Karthik Nayak <karthik.188@gmail.com>\n>> ---\n>>  Documentation/git-refs.txt | 11 ++++++++---\n>>  builtin/refs.c             |  3 +++\n>>  refs.c                     |  8 +++++---\n>>  refs.h                     |  5 ++++-\n>>  t/t1460-refs-migrate.sh    | 28 ++++++++++++++++++++++++----\n>>  5 files changed, 44 insertions(+), 11 deletions(-)\n>>\n>> Changes in v5:\n>> - Add missing documentation and cleanup the commit message.\n>> - I also see that 'git-refs.txt' in master has been renamed to 'git-refs.adoc',\n>>   but I'm going to avoid rebasing on latest master, since the resolution is\n>>   quite simple here. Happy to do it if needed.\n>\n> It is a good rule of thumb to refrain from rebasing when in doubt.\n>\n> Shall we declare victory and mark the topic for 'next' by now?\n>\n> Thanks.\n\nThat would be nice!\n\nThanks\n"}]}