{"thread":{"id":"62830","subject":"[PATCH v3 1/5] Makefile: wire up build option for deprecated features","startedAt":"2025-01-20T07:43:05Z","lastAt":"2025-01-22T17:58:26Z","messageCount":10,"participants":["Patrick Steinhardt","Junio C Hamano"],"isPatch":true,"patchVersion":3,"patchTotal":5},"messages":[{"id":"510926","messageId":"20250120-pks-remote-branches-deprecation-v3-0-c7e539b6a84f@pks.im","threadId":"62830","inReplyTo":"20241211-pks-remote-branches-deprecation-v1-0-1431e2369135@pks.im","subject":"[PATCH v3 0/5] remote: announce removal of \"branches/\" and \"remotes/\"","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-01-20T07:42:57Z","receivedAt":"2025-01-20T07:43:05Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Hi,\n\nback when Git was in its infancy, remotes were configured via separate\nfiles in \"branches/\" (back in 2005). Later that year we introduced a\nmore powerful mechanism with the \"remotes/\" directory. These mechanism\nhave eventually been superseded by config-based remotes, and it is very\nunlikely that anybody still uses these directories to configure their\nremotes. Both of these directories have been marked as deprecated, one\nin 2005 and the other one in 2011.\n\nThis patch series follows through with the deprecation of these and\nannounces them for removal in Git 3.0. Furthermore, it creates the infra\nto compile Git with such breaking changes enabled and wires up a CI job\nboth for GitHub and GitLab to test those breaking changes.\n\nThe series is based on top caacdb5dfd (The fifteenth batch, 2024-12-10)\nwith ps/build at 904339edbd (Introduce support for the Meson build\nsystem, 2024-12-06) merged into it.\n\nChanges in v2:\n- Some small fixes to the deprecation notice of \"branches/\" and\n  \"remotes/\".\n- Some small fixes to commit messages.\n- Link to v1: https://lore.kernel.org/r/20241211-pks-remote-branches-deprecation-v1-0-1431e2369135@pks.im\n\nChanges in v3:\n- Print warnings when reading remotes from \"remotes/\" or \"branches/\".\n- A couple of commit mesasge improvements.\n- Link to v2: https://lore.kernel.org/r/20250106-pks-remote-branches-deprecation-v2-0-2ce87c053536@pks.im\n\nThanks!\n\nPatrick\n\n---\nPatrick Steinhardt (5):\n      Makefile: wire up build option for deprecated features\n      ci: merge linux-gcc-default into linux-gcc\n      ci: repurpose \"linux-gcc\" job for deprecations\n      builtin/pack-redundant: remove subcommand with breaking changes\n      remote: announce removal of \"branches/\" and \"remotes/\"\n\n .github/workflows/main.yml             |  6 +----\n .gitlab-ci.yml                         |  6 +----\n Documentation/BreakingChanges.txt      | 25 ++++++++++++++++++\n Documentation/gitrepository-layout.txt |  7 +++--\n GIT-BUILD-OPTIONS.in                   |  1 +\n Makefile                               |  7 +++++\n builtin/remote.c                       |  2 ++\n ci/lib.sh                              |  5 ----\n ci/run-build-and-tests.sh              |  3 ++-\n contrib/buildsystems/CMakeLists.txt    |  1 +\n git.c                                  |  2 ++\n meson.build                            |  6 +++++\n meson_options.txt                      |  2 ++\n remote.c                               | 19 ++++++++++++++\n remote.h                               |  2 ++\n t/t5323-pack-redundant.sh              |  6 +++++\n t/t5505-remote.sh                      |  6 ++---\n t/t5510-fetch.sh                       | 13 ++++------\n t/t5515-fetch-merge-logic.sh           | 47 ++++++++++++++++++----------------\n t/t5516-fetch-push.sh                  | 14 +++++-----\n t/test-lib.sh                          |  4 +++\n 21 files changed, 125 insertions(+), 59 deletions(-)\n\nRange-diff versus v2:\n\n1:  bc6d8bcb19 ! 1:  3ceab66906 Makefile: wire up build option for deprecated features\n    @@ Commit message\n         such a switch because they predate those instructions.\n     \n         Introduce the proposed `WITH_BREAKING_CHANGES` preprocessor macro and\n    -    wire it up with both our Makefiles and Meson.\n    +    wire it up with both our Makefiles and Meson. This does not yet wire up\n    +    the build flag for existing deprecations.\n     \n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n2:  015a70e998 ! 2:  408f3afa48 ci: merge linux-gcc-default into linux-gcc\n    @@ Commit message\n             have other testcases that don't and also some that explicitly use\n             \"master\".\n     \n    -    So overall, the job does not add much to our test coverage. Merge it\n    -    into our \"linux-gcc\" job to reduce our test matrix a bit.\n    +      - We use \"ubuntu:20.04\" in one job and \"ubuntu:latest\" in another. We\n    +        already have a couple other jobs testing these respectively.\n    +\n    +    So overall, the job does not add much to our test coverage.\n    +\n    +    Drop the \"linux-gcc-default\" job and adapt \"linux-gcc\" to start using\n    +    the default GCC compiler, effectively merging those two jobs into one.\n     \n         Signed-off-by: Patrick Steinhardt <ps@pks.im>\n     \n3:  f776eb0e4e = 3:  545df94c7d ci: repurpose \"linux-gcc\" job for deprecations\n4:  c40f85dde2 = 4:  0142480800 builtin/pack-redundant: remove subcommand with breaking changes\n5:  78bda8dd6b ! 5:  a67bde4eda remote: announce removal of \"branches/\" and \"remotes/\"\n    @@ Commit message\n     \n         Back when Git was in its infancy, remotes were configured via separate\n         files in \"branches/\" (back in 2005). This mechanism was replaced later\n    -    that year with the \"remotes/\" directory. These mechanism have eventually\n    +    that year with the \"remotes/\" directory. Both mechanisms have eventually\n         been replaced by config-based remotes, and it is very unlikely that\n         anybody still uses these directories to configure their remotes.\n     \n    @@ remote.c: static void add_instead_of(struct rewrite *rewrite, const char *instea\n      static const char *skip_spaces(const char *s)\n      {\n      \twhile (isspace(*s))\n    +@@ remote.c: static void read_remotes_file(struct remote_state *remote_state,\n    + \n    + \tif (!f)\n    + \t\treturn;\n    ++\n    ++\twarning(_(\"Reading remote from \\\"remotes/%s\\\", which is nominated\\n\"\n    ++\t\t  \"for removal. If you still use the \\\"remotes/\\\" directory\\n\"\n    ++\t\t  \"it is recommended to migrate to config-based remotes. If\\n\"\n    ++\t\t  \"you cannot, please let us know you still use it by sending\\n\"\n    ++\t\t  \"an e-mail to <git@vger.kernel.org>.\"), remote->name);\n    ++\n    + \tremote->configured_in_repo = 1;\n    + \tremote->origin = REMOTE_REMOTES;\n    + \twhile (strbuf_getline(&buf, f) != EOF) {\n    +@@ remote.c: static void read_branches_file(struct remote_state *remote_state,\n    + \tif (!f)\n    + \t\treturn;\n    + \n    ++\twarning(_(\"Reading remote from \\\"branches/%s\\\", which is nominated\\n\"\n    ++\t\t  \"for removal. If you still use the \\\"branches/\\\" directory\\n\"\n    ++\t\t  \"it is recommended to migrate to config-based remotes. If\\n\"\n    ++\t\t  \"you cannot, please let us know you still use it by sending\\n\"\n    ++\t\t  \"an e-mail to <git@vger.kernel.org>.\"), remote->name);\n    ++\n    + \tstrbuf_getline_lf(&buf, f);\n    + \tfclose(f);\n    + \tstrbuf_trim(&buf);\n     @@ remote.c: static void read_branches_file(struct remote_state *remote_state,\n      \tstrbuf_release(&buf);\n      \tfree(to_free);\n\n---\nbase-commit: 713ec79a9091cec60b110d605b418904759982ab\nchange-id: 20241205-pks-remote-branches-deprecation-037a4389a377\n\n"},{"id":"510925","messageId":"20250120-pks-remote-branches-deprecation-v3-1-c7e539b6a84f@pks.im","threadId":"62830","inReplyTo":"20250120-pks-remote-branches-deprecation-v3-0-c7e539b6a84f@pks.im","subject":"[PATCH v3 1/5] Makefile: wire up build option for deprecated features","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-01-20T07:42:58Z","receivedAt":"2025-01-20T07:43:06Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"With 57ec9254eb (docs: introduce document to announce breaking changes,\n2024-06-14), we have introduced a new document that tracks upcoming\nbreaking changes in the Git project. In 2454970930 (BreakingChanges:\nearly adopter option, 2024-10-11) we have amended the document a bit to\nmention that any introduced breaking changes must be accompanied by\nlogic that allows us to enable the breaking change at compile-time.\nWhile we already have two breaking changes lined up, neither of them has\nsuch a switch because they predate those instructions.\n\nIntroduce the proposed `WITH_BREAKING_CHANGES` preprocessor macro and\nwire it up with both our Makefiles and Meson. This does not yet wire up\nthe build flag for existing deprecations.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n GIT-BUILD-OPTIONS.in                | 1 +\n Makefile                            | 5 +++++\n contrib/buildsystems/CMakeLists.txt | 1 +\n meson.build                         | 6 ++++++\n meson_options.txt                   | 2 ++\n t/test-lib.sh                       | 4 ++++\n 6 files changed, 19 insertions(+)\n\ndiff --git a/GIT-BUILD-OPTIONS.in b/GIT-BUILD-OPTIONS.in\nindex f651116102..f1d0ecf123 100644\n--- a/GIT-BUILD-OPTIONS.in\n+++ b/GIT-BUILD-OPTIONS.in\n@@ -45,3 +45,4 @@ GITWEBDIR=@GITWEBDIR@\n USE_GETTEXT_SCHEME=@USE_GETTEXT_SCHEME@\n LOCALEDIR=@LOCALEDIR@\n BROKEN_PATH_FIX=@BROKEN_PATH_FIX@\n+WITH_BREAKING_CHANGES=@WITH_BREAKING_CHANGES@\ndiff --git a/Makefile b/Makefile\nindex 06f01149ec..dc3c980aa7 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -2230,6 +2230,10 @@ ifdef FSMONITOR_OS_SETTINGS\n \tCOMPAT_OBJS += compat/fsmonitor/fsm-path-utils-$(FSMONITOR_OS_SETTINGS).o\n endif\n \n+ifdef WITH_BREAKING_CHANGES\n+\tBASIC_CFLAGS += -DWITH_BREAKING_CHANGES\n+endif\n+\n ifeq ($(TCLTK_PATH),)\n NO_TCLTK = NoThanks\n endif\n@@ -3187,6 +3191,7 @@ GIT-BUILD-OPTIONS: FORCE\n \t\t-e \"s|@USE_GETTEXT_SCHEME@|\\'$(USE_GETTEXT_SCHEME)\\'|\" \\\n \t\t-e \"s|@LOCALEDIR@|\\'$(localedir_SQ)\\'|\" \\\n \t\t-e \"s!@BROKEN_PATH_FIX@!\\'$(BROKEN_PATH_FIX)\\'!\" \\\n+\t\t-e \"s|@WITH_BREAKING_CHANGES@|\\'$(WITH_BREAKING_CHANGES)\\'|\" \\\n \t\tGIT-BUILD-OPTIONS.in >$@+\n \t@if grep -q '^[A-Z][A-Z_]*=@.*@$$' $@+; then echo \"Unsubstituted build options in $@\" >&2 && exit 1; fi\n \t@if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi\ndiff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt\nindex 49904ca8a9..63d0088928 100644\n--- a/contrib/buildsystems/CMakeLists.txt\n+++ b/contrib/buildsystems/CMakeLists.txt\n@@ -1198,6 +1198,7 @@ string(REPLACE \"@GITWEBDIR@\" \"'${GITWEBDIR}'\" git_build_options \"${git_build_opt\n string(REPLACE \"@USE_GETTEXT_SCHEME@\" \"\" git_build_options \"${git_build_options}\")\n string(REPLACE \"@LOCALEDIR@\" \"'${LOCALEDIR}'\" git_build_options \"${git_build_options}\")\n string(REPLACE \"@BROKEN_PATH_FIX@\" \"\" git_build_options \"${git_build_options}\")\n+string(REPLACE \"@WITH_BREAKING_CHANGES@\" \"\" git_build_options \"${git_build_options}\")\n if(USE_VCPKG)\n \tstring(APPEND git_build_options \"PATH=\\\"$PATH:$TEST_DIRECTORY/../compat/vcbuild/vcpkg/installed/x64-windows/bin\\\"\\n\")\n endif()\ndiff --git a/meson.build b/meson.build\nindex 0dccebcdf1..316cd93264 100644\n--- a/meson.build\n+++ b/meson.build\n@@ -644,6 +644,12 @@ build_options_config.set('GIT_TEST_UTF8_LOCALE', '')\n build_options_config.set_quoted('LOCALEDIR', fs.as_posix(get_option('prefix') / get_option('localedir')))\n build_options_config.set('GITWEBDIR', fs.as_posix(get_option('prefix') / get_option('datadir') / 'gitweb'))\n \n+if get_option('breaking_changes')\n+  build_options_config.set('WITH_BREAKING_CHANGES', 'YesPlease')\n+else\n+  build_options_config.set('WITH_BREAKING_CHANGES', '')\n+endif\n+\n if get_option('sane_tool_path') != ''\n   build_options_config.set_quoted('BROKEN_PATH_FIX', 's|^\\# @BROKEN_PATH_FIX@$|git_broken_path_fix \"' + get_option('sane_tool_path') + '\"|')\n else\ndiff --git a/meson_options.txt b/meson_options.txt\nindex 32a72139ba..800e518d95 100644\n--- a/meson_options.txt\n+++ b/meson_options.txt\n@@ -43,6 +43,8 @@ option('sha256_backend', type: 'combo', choices: ['openssl', 'nettle', 'gcrypt',\n   description: 'The backend used for hashing objects with the SHA256 object format')\n \n # Build tweaks.\n+option('breaking_changes', type: 'boolean', value: false,\n+  description: 'Enable upcoming breaking changes.')\n option('macos_use_homebrew_gettext', type: 'boolean', value: true,\n   description: 'Use gettext from Homebrew instead of the slightly-broken system-provided one.')\n \ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 62dfcc4aaf..6e423f655d 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -1864,6 +1864,10 @@ test_lazy_prereq CURL '\n \tcurl --version\n '\n \n+test_lazy_prereq WITHOUT_BREAKING_CHANGES '\n+\ttest -z \"$WITH_BREAKING_CHANGES\"\n+'\n+\n # SHA1 is a test if the hash algorithm in use is SHA-1.  This is both for tests\n # which will not work with other hash algorithms and tests that work but don't\n # test anything meaningful (e.g. special values which cause short collisions).\n\n-- \n2.48.0.257.gd3603152ad.dirty\n\n"},{"id":"510927","messageId":"20250120-pks-remote-branches-deprecation-v3-2-c7e539b6a84f@pks.im","threadId":"62830","inReplyTo":"20250120-pks-remote-branches-deprecation-v3-0-c7e539b6a84f@pks.im","subject":"[PATCH v3 2/5] ci: merge linux-gcc-default into linux-gcc","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-01-20T07:42:59Z","receivedAt":"2025-01-20T07:43:07Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The \"linux-gcc-default\" job is mostly doing the same as the \"linux-gcc\"\njob, except for a couple of minor differences:\n\n  - We use an explicit GCC version instead of the default version\n    provided by the distribution. We have other jobs that test with\n    \"gcc-8\", making this distinction pointless.\n\n  - We don't set up the Python version explicitly, and instead use the\n    default Python version. Python 2 has been end-of-life for quite a\n    while now though, making this distinction less interesting.\n\n  - We set up the default branch name to be \"main\" in \"linux-gcc\". We\n    have other testcases that don't and also some that explicitly use\n    \"master\".\n\n  - We use \"ubuntu:20.04\" in one job and \"ubuntu:latest\" in another. We\n    already have a couple other jobs testing these respectively.\n\nSo overall, the job does not add much to our test coverage.\n\nDrop the \"linux-gcc-default\" job and adapt \"linux-gcc\" to start using\nthe default GCC compiler, effectively merging those two jobs into one.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .github/workflows/main.yml | 4 ----\n .gitlab-ci.yml             | 4 ----\n ci/lib.sh                  | 5 -----\n 3 files changed, 13 deletions(-)\n\ndiff --git a/.github/workflows/main.yml b/.github/workflows/main.yml\nindex 808ddc19b8..32d35d2257 100644\n--- a/.github/workflows/main.yml\n+++ b/.github/workflows/main.yml\n@@ -271,7 +271,6 @@ jobs:\n             pool: ubuntu-latest\n           - jobname: linux-gcc\n             cc: gcc\n-            cc_package: gcc-8\n             pool: ubuntu-20.04\n           - jobname: linux-TEST-vars\n             cc: gcc\n@@ -286,9 +285,6 @@ jobs:\n           - jobname: osx-gcc\n             cc: gcc-13\n             pool: macos-13\n-          - jobname: linux-gcc-default\n-            cc: gcc\n-            pool: ubuntu-latest\n           - jobname: linux-leaks\n             cc: gcc\n             pool: ubuntu-latest\ndiff --git a/.gitlab-ci.yml b/.gitlab-ci.yml\nindex a1bc92893f..b86bb0bdb3 100644\n--- a/.gitlab-ci.yml\n+++ b/.gitlab-ci.yml\n@@ -46,14 +46,10 @@ test:linux:\n       - jobname: linux-gcc\n         image: ubuntu:20.04\n         CC: gcc\n-        CC_PACKAGE: gcc-8\n       - jobname: linux-TEST-vars\n         image: ubuntu:20.04\n         CC: gcc\n         CC_PACKAGE: gcc-8\n-      - jobname: linux-gcc-default\n-        image: ubuntu:latest\n-        CC: gcc\n       - jobname: linux-leaks\n         image: ubuntu:latest\n         CC: gcc\ndiff --git a/ci/lib.sh b/ci/lib.sh\nindex 930f98d722..e67c481d4f 100755\n--- a/ci/lib.sh\n+++ b/ci/lib.sh\n@@ -328,11 +328,6 @@ export SKIP_DASHED_BUILT_INS=YesPlease\n \n case \"$distro\" in\n ubuntu-*)\n-\tif test \"$jobname\" = \"linux-gcc-default\"\n-\tthen\n-\t\tbreak\n-\tfi\n-\n \t# Python 2 is end of life, and Ubuntu 23.04 and newer don't actually\n \t# have it anymore. We thus only test with Python 2 on older LTS\n \t# releases.\n\n-- \n2.48.0.257.gd3603152ad.dirty\n\n"},{"id":"510928","messageId":"20250120-pks-remote-branches-deprecation-v3-3-c7e539b6a84f@pks.im","threadId":"62830","inReplyTo":"20250120-pks-remote-branches-deprecation-v3-0-c7e539b6a84f@pks.im","subject":"[PATCH v3 3/5] ci: repurpose \"linux-gcc\" job for deprecations","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-01-20T07:43:00Z","receivedAt":"2025-01-20T07:43:08Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The \"linux-gcc\" job isn't all that interesting by itself and can be\nconsidered more or less the \"standard\" job: it is running with a\nreasonably up-to-date image and uses GCC as a compiler, both of which we\nalready cover in other jobs.\n\nThere is one exception though: we change the default branch to be \"main\"\ninstead of \"master\", so it is forging ahead a bit into the future to\nmake sure that this change does not cause havoc. So let's expand on this\na bit and also add the new \"WITH_BREAKING_CHANGES\" flag to the mix.\n\nRename the job to \"linux-breaking-changes\" accordingly.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n .github/workflows/main.yml | 2 +-\n .gitlab-ci.yml             | 2 +-\n ci/run-build-and-tests.sh  | 3 ++-\n 3 files changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git a/.github/workflows/main.yml b/.github/workflows/main.yml\nindex 32d35d2257..46b96fb96c 100644\n--- a/.github/workflows/main.yml\n+++ b/.github/workflows/main.yml\n@@ -269,7 +269,7 @@ jobs:\n           - jobname: linux-reftable\n             cc: clang\n             pool: ubuntu-latest\n-          - jobname: linux-gcc\n+          - jobname: linux-breaking-changes\n             cc: gcc\n             pool: ubuntu-20.04\n           - jobname: linux-TEST-vars\ndiff --git a/.gitlab-ci.yml b/.gitlab-ci.yml\nindex b86bb0bdb3..492e5d9082 100644\n--- a/.gitlab-ci.yml\n+++ b/.gitlab-ci.yml\n@@ -43,7 +43,7 @@ test:linux:\n       - jobname: linux-reftable\n         image: ubuntu:latest\n         CC: clang\n-      - jobname: linux-gcc\n+      - jobname: linux-breaking-changes\n         image: ubuntu:20.04\n         CC: gcc\n       - jobname: linux-TEST-vars\ndiff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh\nindex 2e28d02b20..2ccd812fb4 100755\n--- a/ci/run-build-and-tests.sh\n+++ b/ci/run-build-and-tests.sh\n@@ -13,8 +13,9 @@ esac\n run_tests=t\n \n case \"$jobname\" in\n-linux-gcc)\n+linux-breaking-changes)\n \texport GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n+\texport WITH_BREAKING_CHANGES=YesPlease\n \t;;\n linux-TEST-vars)\n \texport GIT_TEST_SPLIT_INDEX=yes\n\n-- \n2.48.0.257.gd3603152ad.dirty\n\n"},{"id":"510929","messageId":"20250120-pks-remote-branches-deprecation-v3-4-c7e539b6a84f@pks.im","threadId":"62830","inReplyTo":"20250120-pks-remote-branches-deprecation-v3-0-c7e539b6a84f@pks.im","subject":"[PATCH v3 4/5] builtin/pack-redundant: remove subcommand with breaking changes","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-01-20T07:43:01Z","receivedAt":"2025-01-20T07:43:09Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"The git-pack-redundant(1) subcommand has been announced for removal with\n53a92c9552 (Documentation/BreakingChanges: announce removal of\ngit-pack-redundant(1), 2024-09-02). Stop compiling the subcommand in\ncase the `WITH_BREAKING_CHANGES` build flag is set.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Makefile                  | 2 ++\n git.c                     | 2 ++\n t/t5323-pack-redundant.sh | 6 ++++++\n 3 files changed, 10 insertions(+)\n\ndiff --git a/Makefile b/Makefile\nindex dc3c980aa7..e6b0d85980 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1278,7 +1278,9 @@ BUILTIN_OBJS += builtin/mv.o\n BUILTIN_OBJS += builtin/name-rev.o\n BUILTIN_OBJS += builtin/notes.o\n BUILTIN_OBJS += builtin/pack-objects.o\n+ifndef WITH_BREAKING_CHANGES\n BUILTIN_OBJS += builtin/pack-redundant.o\n+endif\n BUILTIN_OBJS += builtin/pack-refs.o\n BUILTIN_OBJS += builtin/patch-id.o\n BUILTIN_OBJS += builtin/prune-packed.o\ndiff --git a/git.c b/git.c\nindex 46b3c740c5..a13c32bcdc 100644\n--- a/git.c\n+++ b/git.c\n@@ -589,7 +589,9 @@ static struct cmd_struct commands[] = {\n \t{ \"name-rev\", cmd_name_rev, RUN_SETUP },\n \t{ \"notes\", cmd_notes, RUN_SETUP },\n \t{ \"pack-objects\", cmd_pack_objects, RUN_SETUP },\n+#ifndef WITH_BREAKING_CHANGES\n \t{ \"pack-redundant\", cmd_pack_redundant, RUN_SETUP | NO_PARSEOPT },\n+#endif\n \t{ \"pack-refs\", cmd_pack_refs, RUN_SETUP },\n \t{ \"patch-id\", cmd_patch_id, RUN_SETUP_GENTLY | NO_PARSEOPT },\n \t{ \"pickaxe\", cmd_blame, RUN_SETUP },\ndiff --git a/t/t5323-pack-redundant.sh b/t/t5323-pack-redundant.sh\nindex 8dbbcc5e51..688cd9706c 100755\n--- a/t/t5323-pack-redundant.sh\n+++ b/t/t5323-pack-redundant.sh\n@@ -36,6 +36,12 @@ relationship between packs and objects is as follows:\n \n . ./test-lib.sh\n \n+if ! test_have_prereq WITHOUT_BREAKING_CHANGES\n+then\n+\tskip_all='skipping git-pack-redundant tests; built with breaking changes'\n+\ttest_done\n+fi\n+\n main_repo=main.git\n shared_repo=shared.git\n \n\n-- \n2.48.0.257.gd3603152ad.dirty\n\n"},{"id":"510930","messageId":"20250120-pks-remote-branches-deprecation-v3-5-c7e539b6a84f@pks.im","threadId":"62830","inReplyTo":"20250120-pks-remote-branches-deprecation-v3-0-c7e539b6a84f@pks.im","subject":"[PATCH v3 5/5] remote: announce removal of \"branches/\" and \"remotes/\"","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-01-20T07:43:02Z","receivedAt":"2025-01-20T07:43:10Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"Back when Git was in its infancy, remotes were configured via separate\nfiles in \"branches/\" (back in 2005). This mechanism was replaced later\nthat year with the \"remotes/\" directory. Both mechanisms have eventually\nbeen replaced by config-based remotes, and it is very unlikely that\nanybody still uses these directories to configure their remotes.\n\nBoth of these directories have been marked as deprecated, one in 2005\nand the other one in 2011. Follow through with the deprecation and\nfinally announce the removal of these features in Git 3.0.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\n Documentation/BreakingChanges.txt      | 25 ++++++++++++++++++\n Documentation/gitrepository-layout.txt |  7 +++--\n builtin/remote.c                       |  2 ++\n remote.c                               | 19 ++++++++++++++\n remote.h                               |  2 ++\n t/t5505-remote.sh                      |  6 ++---\n t/t5510-fetch.sh                       | 13 ++++------\n t/t5515-fetch-merge-logic.sh           | 47 ++++++++++++++++++----------------\n t/t5516-fetch-push.sh                  | 14 +++++-----\n 9 files changed, 92 insertions(+), 43 deletions(-)\n\ndiff --git a/Documentation/BreakingChanges.txt b/Documentation/BreakingChanges.txt\nindex 27acff86db..a91eb3bc55 100644\n--- a/Documentation/BreakingChanges.txt\n+++ b/Documentation/BreakingChanges.txt\n@@ -154,6 +154,31 @@ Cf. <xmqq1rjuz6n3.fsf_-_@gitster.c.googlers.com>,\n     <CAKvOHKAFXQwt4D8yUCCkf_TQL79mYaJ=KAKhtpDNTvHJFuX1NA@mail.gmail.com>,\n     <20230323204047.GA9290@coredump.intra.peff.net>,\n \n+* Support for storing shorthands for remote URLs in \"$GIT_COMMON_DIR/branches/\"\n+  and \"$GIT_COMMON_DIR/remotes/\" has been long superseded by storing remotes in\n+  the repository configuration.\n++\n+The mechanism has originally been introduced in f170e4b39d ([PATCH] fetch/pull:\n+short-hand notation for remote repositories., 2005-07-16) and was superseded by\n+6687f8fea2 ([PATCH] Use .git/remote/origin, not .git/branches/origin.,\n+2005-08-20), where we switched from \".git/branches/\" to \".git/remotes/\". That\n+commit already mentions an upcoming deprecation of the \".git/branches/\"\n+directory, and starting with a1d4aa7424 (Add repository-layout document.,\n+2005-09-01) we have also marked this layout as deprecated. Eventually we also\n+started to migrate away from \".git/remotes/\" in favor of config-based remotes,\n+and we have marked the directory as legacy in 3d3d282146 (Documentation:\n+Grammar correction, wording fixes and cleanup, 2011-08-23)\n++\n+As our documentation mentions, these directories are not to be found in modern\n+repositories at all and most users aren't even aware of these mechanisms. They\n+have been deprecated for almost 20 years and 14 years respectively, and we are\n+not aware of any reason why anybody would want to use these mechanisms.\n+Furthermore, the \".git/branches/\" directory is nowadays misleadingly named and\n+may cause confusion as \"branches\" are almost exclusively used in the context of\n+references.\n++\n+These features will be removed.\n+\n == Superseded features that will not be deprecated\n \n Some features have gained newer replacements that aim to improve the design in\ndiff --git a/Documentation/gitrepository-layout.txt b/Documentation/gitrepository-layout.txt\nindex fa8b51daf0..85911ca8ea 100644\n--- a/Documentation/gitrepository-layout.txt\n+++ b/Documentation/gitrepository-layout.txt\n@@ -153,7 +153,7 @@ config.worktree::\n \tlinkgit:git-worktree[1]).\n \n branches::\n-\tA slightly deprecated way to store shorthands to be used\n+\tA deprecated way to store shorthands to be used\n \tto specify a URL to 'git fetch', 'git pull' and 'git push'.\n \tA file can be stored as `branches/<name>` and then\n \t'name' can be given to these commands in place of\n@@ -162,7 +162,8 @@ branches::\n \tand not likely to be found in modern repositories. This\n \tdirectory is ignored if $GIT_COMMON_DIR is set and\n \t\"$GIT_COMMON_DIR/branches\" will be used instead.\n-\n++\n+Git will stop reading remotes from this directory in Git 3.0.\n \n hooks::\n \tHooks are customization scripts used by various Git\n@@ -238,6 +239,8 @@ remotes::\n \tand not likely to be found in modern repositories. This\n \tdirectory is ignored if $GIT_COMMON_DIR is set and\n \t\"$GIT_COMMON_DIR/remotes\" will be used instead.\n++\n+Git will stop reading remotes from this directory in Git 3.0.\n \n logs::\n \tRecords of changes made to refs are stored in this directory.\ndiff --git a/builtin/remote.c b/builtin/remote.c\nindex 1ad3e70a6b..e565b2b3fe 100644\n--- a/builtin/remote.c\n+++ b/builtin/remote.c\n@@ -640,10 +640,12 @@ static int migrate_file(struct remote *remote)\n \tstrbuf_addf(&buf, \"remote.%s.fetch\", remote->name);\n \tfor (i = 0; i < remote->fetch.nr; i++)\n \t\tgit_config_set_multivar(buf.buf, remote->fetch.items[i].raw, \"^$\", 0);\n+#ifndef WITH_BREAKING_CHANGES\n \tif (remote->origin == REMOTE_REMOTES)\n \t\tunlink_or_warn(git_path(\"remotes/%s\", remote->name));\n \telse if (remote->origin == REMOTE_BRANCHES)\n \t\tunlink_or_warn(git_path(\"branches/%s\", remote->name));\n+#endif /* WITH_BREAKING_CHANGES */\n \tstrbuf_release(&buf);\n \n \treturn 0;\ndiff --git a/remote.c b/remote.c\nindex 10104d11e3..5feb0ae886 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -293,6 +293,7 @@ static void add_instead_of(struct rewrite *rewrite, const char *instead_of)\n \trewrite->instead_of_nr++;\n }\n \n+#ifndef WITH_BREAKING_CHANGES\n static const char *skip_spaces(const char *s)\n {\n \twhile (isspace(*s))\n@@ -308,6 +309,13 @@ static void read_remotes_file(struct remote_state *remote_state,\n \n \tif (!f)\n \t\treturn;\n+\n+\twarning(_(\"Reading remote from \\\"remotes/%s\\\", which is nominated\\n\"\n+\t\t  \"for removal. If you still use the \\\"remotes/\\\" directory\\n\"\n+\t\t  \"it is recommended to migrate to config-based remotes. If\\n\"\n+\t\t  \"you cannot, please let us know you still use it by sending\\n\"\n+\t\t  \"an e-mail to <git@vger.kernel.org>.\"), remote->name);\n+\n \tremote->configured_in_repo = 1;\n \tremote->origin = REMOTE_REMOTES;\n \twhile (strbuf_getline(&buf, f) != EOF) {\n@@ -337,6 +345,12 @@ static void read_branches_file(struct remote_state *remote_state,\n \tif (!f)\n \t\treturn;\n \n+\twarning(_(\"Reading remote from \\\"branches/%s\\\", which is nominated\\n\"\n+\t\t  \"for removal. If you still use the \\\"branches/\\\" directory\\n\"\n+\t\t  \"it is recommended to migrate to config-based remotes. If\\n\"\n+\t\t  \"you cannot, please let us know you still use it by sending\\n\"\n+\t\t  \"an e-mail to <git@vger.kernel.org>.\"), remote->name);\n+\n \tstrbuf_getline_lf(&buf, f);\n \tfclose(f);\n \tstrbuf_trim(&buf);\n@@ -374,6 +388,7 @@ static void read_branches_file(struct remote_state *remote_state,\n \tstrbuf_release(&buf);\n \tfree(to_free);\n }\n+#endif /* WITH_BREAKING_CHANGES */\n \n static int handle_config(const char *key, const char *value,\n \t\t\t const struct config_context *ctx, void *cb)\n@@ -572,6 +587,7 @@ static void read_config(struct repository *repo, int early)\n \talias_all_urls(repo->remote_state);\n }\n \n+#ifndef WITH_BREAKING_CHANGES\n static int valid_remote_nick(const char *name)\n {\n \tif (!name[0] || is_dot_or_dotdot(name))\n@@ -583,6 +599,7 @@ static int valid_remote_nick(const char *name)\n \t\t\treturn 0;\n \treturn 1;\n }\n+#endif /* WITH_BREAKING_CHANGES */\n \n static const char *remotes_remote_for_branch(struct remote_state *remote_state,\n \t\t\t\t\t     struct branch *branch,\n@@ -725,12 +742,14 @@ remotes_remote_get_1(struct remote_state *remote_state, const char *name,\n \t\t\t\t   &name_given);\n \n \tret = make_remote(remote_state, name, 0);\n+#ifndef WITH_BREAKING_CHANGES\n \tif (valid_remote_nick(name) && have_git_dir()) {\n \t\tif (!valid_remote(ret))\n \t\t\tread_remotes_file(remote_state, ret);\n \t\tif (!valid_remote(ret))\n \t\t\tread_branches_file(remote_state, ret);\n \t}\n+#endif /* WITH_BREAKING_CHANGES */\n \tif (name_given && !valid_remote(ret))\n \t\tadd_url_alias(remote_state, ret, name);\n \tif (!valid_remote(ret))\ndiff --git a/remote.h b/remote.h\nindex a7e5c4e07c..45b0c9babb 100644\n--- a/remote.h\n+++ b/remote.h\n@@ -21,8 +21,10 @@ struct transport_ls_refs_options;\n enum {\n \tREMOTE_UNCONFIGURED = 0,\n \tREMOTE_CONFIG,\n+#ifndef WITH_BREAKING_CHANGES\n \tREMOTE_REMOTES,\n \tREMOTE_BRANCHES\n+#endif /* WITH_BREAKING_CHANGES */\n };\n \n struct rewrite {\ndiff --git a/t/t5505-remote.sh b/t/t5505-remote.sh\nindex 08424e878e..e96ac8c767 100755\n--- a/t/t5505-remote.sh\n+++ b/t/t5505-remote.sh\n@@ -1007,7 +1007,7 @@ Pull: refs/heads/main:refs/heads/origin\n Pull: refs/heads/next:refs/heads/origin2\n EOF\n \n-test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' '\n+test_expect_success WITHOUT_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/remotes' '\n \tgit clone one five &&\n \torigin_url=$(pwd)/one &&\n \t(\n@@ -1033,7 +1033,7 @@ test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' '\n \t)\n '\n \n-test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' '\n+test_expect_success WITHOUT_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/branches' '\n \tgit clone --template= one six &&\n \torigin_url=$(pwd)/one &&\n \t(\n@@ -1049,7 +1049,7 @@ test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' '\n \t)\n '\n \n-test_expect_success 'migrate a remote from named file in $GIT_DIR/branches (2)' '\n+test_expect_success WITHOUT_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/branches (2)' '\n \tgit clone --template= one seven &&\n \t(\n \t\tcd seven &&\ndiff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh\nindex 3b3991ab86..04d8a96367 100755\n--- a/t/t5510-fetch.sh\n+++ b/t/t5510-fetch.sh\n@@ -34,14 +34,11 @@ test_expect_success \"clone and setup child repos\" '\n \tgit clone . three &&\n \t(\n \t\tcd three &&\n-\t\tgit config branch.main.remote two &&\n-\t\tgit config branch.main.merge refs/heads/one &&\n-\t\tmkdir -p .git/remotes &&\n-\t\tcat >.git/remotes/two <<-\\EOF\n-\t\tURL: ../two/.git/\n-\t\tPull: refs/heads/main:refs/heads/two\n-\t\tPull: refs/heads/one:refs/heads/one\n-\t\tEOF\n+\t\tgit config set remote.two.url ../two/.git/ &&\n+\t\tgit config set remote.two.fetch refs/heads/main:refs/heads/two &&\n+\t\tgit config set --append remote.two.fetch refs/heads/one:refs/heads/one &&\n+\t\tgit config set branch.main.remote two &&\n+\t\tgit config set branch.main.merge refs/heads/one\n \t) &&\n \tgit clone . bundle &&\n \tgit clone . seven\ndiff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh\nindex 320d26796d..4e6026c611 100755\n--- a/t/t5515-fetch-merge-logic.sh\n+++ b/t/t5515-fetch-merge-logic.sh\n@@ -104,28 +104,31 @@ test_expect_success setup '\n \tgit config remote.config-glob.fetch refs/heads/*:refs/remotes/rem/* &&\n \tremotes=\"$remotes config-glob\" &&\n \n-\tmkdir -p .git/remotes &&\n-\tcat >.git/remotes/remote-explicit <<-\\EOF &&\n-\tURL: ../.git/\n-\tPull: refs/heads/main:remotes/rem/main\n-\tPull: refs/heads/one:remotes/rem/one\n-\tPull: two:remotes/rem/two\n-\tPull: refs/heads/three:remotes/rem/three\n-\tEOF\n-\tremotes=\"$remotes remote-explicit\" &&\n-\n-\tcat >.git/remotes/remote-glob <<-\\EOF &&\n-\tURL: ../.git/\n-\tPull: refs/heads/*:refs/remotes/rem/*\n-\tEOF\n-\tremotes=\"$remotes remote-glob\" &&\n-\n-\tmkdir -p .git/branches &&\n-\techo \"../.git\" > .git/branches/branches-default &&\n-\tremotes=\"$remotes branches-default\" &&\n-\n-\techo \"../.git#one\" > .git/branches/branches-one &&\n-\tremotes=\"$remotes branches-one\" &&\n+\tif test_have_prereq WITHOUT_BREAKING_CHANGES\n+\tthen\n+\t\tmkdir -p .git/remotes &&\n+\t\tcat >.git/remotes/remote-explicit <<-\\EOF &&\n+\t\tURL: ../.git/\n+\t\tPull: refs/heads/main:remotes/rem/main\n+\t\tPull: refs/heads/one:remotes/rem/one\n+\t\tPull: two:remotes/rem/two\n+\t\tPull: refs/heads/three:remotes/rem/three\n+\t\tEOF\n+\t\tremotes=\"$remotes remote-explicit\" &&\n+\n+\t\tcat >.git/remotes/remote-glob <<-\\EOF &&\n+\t\tURL: ../.git/\n+\t\tPull: refs/heads/*:refs/remotes/rem/*\n+\t\tEOF\n+\t\tremotes=\"$remotes remote-glob\" &&\n+\n+\t\tmkdir -p .git/branches &&\n+\t\techo \"../.git\" > .git/branches/branches-default &&\n+\t\tremotes=\"$remotes branches-default\" &&\n+\n+\t\techo \"../.git#one\" > .git/branches/branches-one &&\n+\t\tremotes=\"$remotes branches-one\"\n+\tfi &&\n \n \tfor remote in $remotes ; do\n \t\tgit config branch.br-$remote.remote $remote &&\ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex 9d693eb57f..e705aedbf4 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -975,7 +975,7 @@ test_expect_success 'allow push to HEAD of non-bare repository (config)' '\n \t! grep \"warning: updating the current branch\" stderr\n '\n \n-test_expect_success 'fetch with branches' '\n+test_expect_success WITHOUT_BREAKING_CHANGES 'fetch with branches' '\n \tmk_empty testrepo &&\n \tgit branch second $the_first_commit &&\n \tgit checkout second &&\n@@ -991,7 +991,7 @@ test_expect_success 'fetch with branches' '\n \tgit checkout main\n '\n \n-test_expect_success 'fetch with branches containing #' '\n+test_expect_success WITHOUT_BREAKING_CHANGES 'fetch with branches containing #' '\n \tmk_empty testrepo &&\n \tmkdir testrepo/.git/branches &&\n \techo \"..#second\" > testrepo/.git/branches/branch2 &&\n@@ -1005,7 +1005,7 @@ test_expect_success 'fetch with branches containing #' '\n \tgit checkout main\n '\n \n-test_expect_success 'push with branches' '\n+test_expect_success WITHOUT_BREAKING_CHANGES 'push with branches' '\n \tmk_empty testrepo &&\n \tgit checkout second &&\n \n@@ -1022,7 +1022,7 @@ test_expect_success 'push with branches' '\n \t)\n '\n \n-test_expect_success 'push with branches containing #' '\n+test_expect_success WITHOUT_BREAKING_CHANGES 'push with branches containing #' '\n \tmk_empty testrepo &&\n \n \ttest_when_finished \"rm -rf .git/branches\" &&\n@@ -1211,18 +1211,16 @@ test_expect_success 'push --porcelain --dry-run rejected' '\n '\n \n test_expect_success 'push --prune' '\n-\tmk_test testrepo heads/main heads/second heads/foo heads/bar &&\n+\tmk_test testrepo heads/main heads/foo heads/bar &&\n \tgit push --prune testrepo : &&\n \tcheck_push_result testrepo $the_commit heads/main &&\n-\tcheck_push_result testrepo $the_first_commit heads/second &&\n \t! check_push_result testrepo $the_first_commit heads/foo heads/bar\n '\n \n test_expect_success 'push --prune refspec' '\n-\tmk_test testrepo tmp/main tmp/second tmp/foo tmp/bar &&\n+\tmk_test testrepo tmp/main tmp/foo tmp/bar &&\n \tgit push --prune testrepo \"refs/heads/*:refs/tmp/*\" &&\n \tcheck_push_result testrepo $the_commit tmp/main &&\n-\tcheck_push_result testrepo $the_first_commit tmp/second &&\n \t! check_push_result testrepo $the_first_commit tmp/foo tmp/bar\n '\n \n\n-- \n2.48.0.257.gd3603152ad.dirty\n\n"},{"id":"511021","messageId":"xmqqed0vzxep.fsf@gitster.g","threadId":"62830","inReplyTo":"20250120-pks-remote-branches-deprecation-v3-4-c7e539b6a84f@pks.im","subject":"Re: [PATCH v3 4/5] builtin/pack-redundant: remove subcommand with breaking changes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-01-21T21:09:50Z","receivedAt":"2025-01-21T21:09:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> The git-pack-redundant(1) subcommand has been announced for removal with\n> 53a92c9552 (Documentation/BreakingChanges: announce removal of\n> git-pack-redundant(1), 2024-09-02). Stop compiling the subcommand in\n> case the `WITH_BREAKING_CHANGES` build flag is set.\n\nNice.\n\nThe date it was added to BreakingChanges document is probably of\nmuch lessor impact and importance to the end users than when we\nstopped working unless the user gave \"--i-still-use-this\" which was\ndone by 4406522b (pack-redundant: escalate deprecation warning to an\nerror, 2023-03-23) that was in Git 2.41.\n\nOther than that, I love this step.  The fewer the subcommands, the\nhappier the users ;-)\n"},{"id":"511023","messageId":"xmqqtt9ryi3f.fsf@gitster.g","threadId":"62830","inReplyTo":"20250120-pks-remote-branches-deprecation-v3-5-c7e539b6a84f@pks.im","subject":"Re: [PATCH v3 5/5] remote: announce removal of \"branches/\" and \"remotes/\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-01-21T21:25:56Z","receivedAt":"2025-01-21T21:25:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> +repositories at all and most users aren't even aware of these mechanisms. They\n> +have been deprecated for almost 20 years and 14 years respectively, and we are\n> +not aware of any reason why anybody would want to use these mechanisms.\n\nI am aware of one reason why some folks may prefer being able to say\n\n    $ ls .git/branches/*pattern*\n    $ echo \"$URL#branch\" >\".git/branches/$shortname\"\n    $ git fetch $shortname\n\nover the configuration file based mechanism, especially when they\nhave to deal with dozens of remotes that change the branch name to\nbe pulled from.  And as I already said the above while reviewing the\nprevious round of this series, _we_ are now aware of it.\n\nI however am in favor of deprecating and removing the support, but\nthat is not because I am not aware how useful they could be.  I am\nand we are aware, but we haven't heard anybody jumping up and down\nto advocate for its undeprecation for a long time, and that is why\nI am personally OK with this removal.\n\n>  branches::\n> -\tA slightly deprecated way to store shorthands to be used\n> +\tA deprecated way to store shorthands to be used\n>  \tto specify a URL to 'git fetch', 'git pull' and 'git push'.\n>  \tA file can be stored as `branches/<name>` and then\n>  \t'name' can be given to these commands in place of\n> @@ -162,7 +162,8 @@ branches::\n>  \tand not likely to be found in modern repositories. This\n>  \tdirectory is ignored if $GIT_COMMON_DIR is set and\n>  \t\"$GIT_COMMON_DIR/branches\" will be used instead.\n> -\n> ++\n> +Git will stop reading remotes from this directory in Git 3.0.\n>  \n>  hooks::\n>  \tHooks are customization scripts used by various Git\n> @@ -238,6 +239,8 @@ remotes::\n>  \tand not likely to be found in modern repositories. This\n>  \tdirectory is ignored if $GIT_COMMON_DIR is set and\n>  \t\"$GIT_COMMON_DIR/remotes\" will be used instead.\n> ++\n> +Git will stop reading remotes from this directory in Git 3.0.\n\nOK.\n\n> diff --git a/builtin/remote.c b/builtin/remote.c\n> index 1ad3e70a6b..e565b2b3fe 100644\n> --- a/builtin/remote.c\n> +++ b/builtin/remote.c\n> @@ -640,10 +640,12 @@ static int migrate_file(struct remote *remote)\n>  \tstrbuf_addf(&buf, \"remote.%s.fetch\", remote->name);\n>  \tfor (i = 0; i < remote->fetch.nr; i++)\n>  \t\tgit_config_set_multivar(buf.buf, remote->fetch.items[i].raw, \"^$\", 0);\n> +#ifndef WITH_BREAKING_CHANGES\n>  \tif (remote->origin == REMOTE_REMOTES)\n>  \t\tunlink_or_warn(git_path(\"remotes/%s\", remote->name));\n>  \telse if (remote->origin == REMOTE_BRANCHES)\n>  \t\tunlink_or_warn(git_path(\"branches/%s\", remote->name));\n> +#endif /* WITH_BREAKING_CHANGES */\n>  \tstrbuf_release(&buf);\n\nInteresting.  I wonder if our new warning should talk about whatever\nend-user facing interface that triggers this code path.  It would\nhelp them wean themselves away from the old interface, no?\n\n> diff --git a/remote.c b/remote.c\n> index 10104d11e3..5feb0ae886 100644\n> --- a/remote.c\n> +++ b/remote.c\n> @@ -293,6 +293,7 @@ static void add_instead_of(struct rewrite *rewrite, const char *instead_of)\n>  \trewrite->instead_of_nr++;\n>  }\n>  \n> +#ifndef WITH_BREAKING_CHANGES\n>  static const char *skip_spaces(const char *s)\n>  {\n>  \twhile (isspace(*s))\n> @@ -308,6 +309,13 @@ static void read_remotes_file(struct remote_state *remote_state,\n>  \n>  \tif (!f)\n>  \t\treturn;\n> +\n> +\twarning(_(\"Reading remote from \\\"remotes/%s\\\", which is nominated\\n\"\n> +\t\t  \"for removal. If you still use the \\\"remotes/\\\" directory\\n\"\n> +\t\t  \"it is recommended to migrate to config-based remotes. If\\n\"\n\nDo we have a way to concisely say \"how\" to do this?  If I am reading\nthe caller of migrate_file() in builtin/remote.c, it would be\n\n    $ git remote mv foo foo\n\nfor any foo in .git/remotes/* or .git/branches/* hierarchy?\n\nOf course they may be an ancient leftover file that the user even no\nlonger is aware of having, in which case\n\n    $ rm .git/remotes/foo\n\nmight be an OK answer, but even then\n\n    $ git remote rm foo\n\nwould probably be more appropriate.\n\n> +\t\t  \"you cannot, please let us know you still use it by sending\\n\"\n\nI do not think we care to receive a piece of e-mail that only says\n\"I still use it\".  We may want to learn _why_ they cannot switch\naway, though.\n\nThe same comment applies to the other side.\n\nEverything else in this patch looked superb.\n\nThanks.\n"},{"id":"511049","messageId":"Z5DRESPpegE41xaT@pks.im","threadId":"62830","inReplyTo":"xmqqtt9ryi3f.fsf@gitster.g","subject":"Re: [PATCH v3 5/5] remote: announce removal of \"branches/\" and \"remotes/\"","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2025-01-22T11:05:53Z","receivedAt":"2025-01-22T11:06:03Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Tue, Jan 21, 2025 at 01:25:56PM -0800, Junio C Hamano wrote:\n> Patrick Steinhardt <ps@pks.im> writes:\n> > diff --git a/builtin/remote.c b/builtin/remote.c\n> > index 1ad3e70a6b..e565b2b3fe 100644\n> > --- a/builtin/remote.c\n> > +++ b/builtin/remote.c\n> > @@ -640,10 +640,12 @@ static int migrate_file(struct remote *remote)\n> >  \tstrbuf_addf(&buf, \"remote.%s.fetch\", remote->name);\n> >  \tfor (i = 0; i < remote->fetch.nr; i++)\n> >  \t\tgit_config_set_multivar(buf.buf, remote->fetch.items[i].raw, \"^$\", 0);\n> > +#ifndef WITH_BREAKING_CHANGES\n> >  \tif (remote->origin == REMOTE_REMOTES)\n> >  \t\tunlink_or_warn(git_path(\"remotes/%s\", remote->name));\n> >  \telse if (remote->origin == REMOTE_BRANCHES)\n> >  \t\tunlink_or_warn(git_path(\"branches/%s\", remote->name));\n> > +#endif /* WITH_BREAKING_CHANGES */\n> >  \tstrbuf_release(&buf);\n> \n> Interesting.  I wonder if our new warning should talk about whatever\n> end-user facing interface that triggers this code path.  It would\n> help them wean themselves away from the old interface, no?\n\nNot quite sure that I understand what you're saying. Is it that we\nshould tell whether we were reading from \"branches/\" or \"remotes/\"? If\nso we already do that.\n\n> > diff --git a/remote.c b/remote.c\n> > index 10104d11e3..5feb0ae886 100644\n> > --- a/remote.c\n> > +++ b/remote.c\n> > @@ -293,6 +293,7 @@ static void add_instead_of(struct rewrite *rewrite, const char *instead_of)\n> >  \trewrite->instead_of_nr++;\n> >  }\n> >  \n> > +#ifndef WITH_BREAKING_CHANGES\n> >  static const char *skip_spaces(const char *s)\n> >  {\n> >  \twhile (isspace(*s))\n> > @@ -308,6 +309,13 @@ static void read_remotes_file(struct remote_state *remote_state,\n> >  \n> >  \tif (!f)\n> >  \t\treturn;\n> > +\n> > +\twarning(_(\"Reading remote from \\\"remotes/%s\\\", which is nominated\\n\"\n> > +\t\t  \"for removal. If you still use the \\\"remotes/\\\" directory\\n\"\n> > +\t\t  \"it is recommended to migrate to config-based remotes. If\\n\"\n> \n> Do we have a way to concisely say \"how\" to do this?  If I am reading\n> the caller of migrate_file() in builtin/remote.c, it would be\n> \n>     $ git remote mv foo foo\n> \n> for any foo in .git/remotes/* or .git/branches/* hierarchy?\n> \n> Of course they may be an ancient leftover file that the user even no\n> longer is aware of having, in which case\n> \n>     $ rm .git/remotes/foo\n> \n> might be an OK answer, but even then\n> \n>     $ git remote rm foo\n> \n> would probably be more appropriate.\n\nVery good idea indeed. We also have tests that exercise this behaviour\nin t5505 (with the slight exception that it is `git remote rename`, not\n`git remote mv`).\n\nPatrick\n"},{"id":"511080","messageId":"xmqqo6zywx1c.fsf@gitster.g","threadId":"62830","inReplyTo":"Z5DRESPpegE41xaT@pks.im","subject":"Re: [PATCH v3 5/5] remote: announce removal of \"branches/\" and \"remotes/\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-01-22T17:58:23Z","receivedAt":"2025-01-22T17:58:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> On Tue, Jan 21, 2025 at 01:25:56PM -0800, Junio C Hamano wrote:\n>> Patrick Steinhardt <ps@pks.im> writes:\n>> > diff --git a/builtin/remote.c b/builtin/remote.c\n>> > index 1ad3e70a6b..e565b2b3fe 100644\n>> > --- a/builtin/remote.c\n>> > +++ b/builtin/remote.c\n>> > @@ -640,10 +640,12 @@ static int migrate_file(struct remote *remote)\n>> >  \tstrbuf_addf(&buf, \"remote.%s.fetch\", remote->name);\n>> >  \tfor (i = 0; i < remote->fetch.nr; i++)\n>> >  \t\tgit_config_set_multivar(buf.buf, remote->fetch.items[i].raw, \"^$\", 0);\n>> > +#ifndef WITH_BREAKING_CHANGES\n>> >  \tif (remote->origin == REMOTE_REMOTES)\n>> >  \t\tunlink_or_warn(git_path(\"remotes/%s\", remote->name));\n>> >  \telse if (remote->origin == REMOTE_BRANCHES)\n>> >  \t\tunlink_or_warn(git_path(\"branches/%s\", remote->name));\n>> > +#endif /* WITH_BREAKING_CHANGES */\n>> >  \tstrbuf_release(&buf);\n>> \n>> Interesting.  I wonder if our new warning should talk about whatever\n>> end-user facing interface that triggers this code path.  It would\n>> help them wean themselves away from the old interface, no?\n>\n> Not quite sure that I understand what you're saying. Is it that we\n> should tell whether we were reading from \"branches/\" or \"remotes/\"? If\n> so we already do that.\n\nNo, what I meant was to say \"You are using outdated remotes/\nhierarchy to describe this remote.  You can run 'remote mv %s %s'\nto migrate its definition to the more modern config-based system\".\n\nThe message already says the first sentence, but not the latter.\n\n"}]}