Git fork

Merge branch 'ps/3.0-remote-deprecation'

Following the procedure we established to introduce breaking
changes for Git 3.0, allow an early opt-in for removing support of
$GIT_DIR/branches/ and $GIT_DIR/remotes/ directories to configure
remotes.

* ps/3.0-remote-deprecation:
remote: announce removal of "branches/" and "remotes/"
builtin/pack-redundant: remove subcommand with breaking changes
ci: repurpose "linux-gcc" job for deprecations
ci: merge linux-gcc-default into linux-gcc
Makefile: wire up build option for deprecated features

+129 -56
+1 -5
.github/workflows/main.yml
··· 265 265 - jobname: linux-reftable 266 266 cc: clang 267 267 pool: ubuntu-latest 268 - - jobname: linux-gcc 268 + - jobname: linux-breaking-changes 269 269 cc: gcc 270 - cc_package: gcc-8 271 270 pool: ubuntu-20.04 272 271 - jobname: linux-TEST-vars 273 272 cc: gcc ··· 285 284 - jobname: osx-meson 286 285 cc: clang 287 286 pool: macos-13 288 - - jobname: linux-gcc-default 289 - cc: gcc 290 - pool: ubuntu-latest 291 287 - jobname: linux-leaks 292 288 cc: gcc 293 289 pool: ubuntu-latest
+1 -5
.gitlab-ci.yml
··· 45 45 - jobname: linux-reftable 46 46 image: ubuntu:latest 47 47 CC: clang 48 - - jobname: linux-gcc 48 + - jobname: linux-breaking-changes 49 49 image: ubuntu:20.04 50 50 CC: gcc 51 - CC_PACKAGE: gcc-8 52 51 - jobname: linux-TEST-vars 53 52 image: ubuntu:20.04 54 53 CC: gcc 55 54 CC_PACKAGE: gcc-8 56 - - jobname: linux-gcc-default 57 - image: ubuntu:latest 58 - CC: gcc 59 55 - jobname: linux-leaks 60 56 image: ubuntu:latest 61 57 CC: gcc
+25
Documentation/BreakingChanges.txt
··· 154 154 <CAKvOHKAFXQwt4D8yUCCkf_TQL79mYaJ=KAKhtpDNTvHJFuX1NA@mail.gmail.com>, 155 155 <20230323204047.GA9290@coredump.intra.peff.net>, 156 156 157 + * Support for storing shorthands for remote URLs in "$GIT_COMMON_DIR/branches/" 158 + and "$GIT_COMMON_DIR/remotes/" has been long superseded by storing remotes in 159 + the repository configuration. 160 + + 161 + The mechanism has originally been introduced in f170e4b39d ([PATCH] fetch/pull: 162 + short-hand notation for remote repositories., 2005-07-16) and was superseded by 163 + 6687f8fea2 ([PATCH] Use .git/remote/origin, not .git/branches/origin., 164 + 2005-08-20), where we switched from ".git/branches/" to ".git/remotes/". That 165 + commit already mentions an upcoming deprecation of the ".git/branches/" 166 + directory, and starting with a1d4aa7424 (Add repository-layout document., 167 + 2005-09-01) we have also marked this layout as deprecated. Eventually we also 168 + started to migrate away from ".git/remotes/" in favor of config-based remotes, 169 + and we have marked the directory as legacy in 3d3d282146 (Documentation: 170 + Grammar correction, wording fixes and cleanup, 2011-08-23) 171 + + 172 + As our documentation mentions, these directories are not to be found in modern 173 + repositories at all and most users aren't even aware of these mechanisms. They 174 + have been deprecated for almost 20 years and 14 years respectively, and we are 175 + not aware of any active users that have complained about this deprecation. 176 + Furthermore, the ".git/branches/" directory is nowadays misleadingly named and 177 + may cause confusion as "branches" are almost exclusively used in the context of 178 + references. 179 + + 180 + These features will be removed. 181 + 157 182 == Superseded features that will not be deprecated 158 183 159 184 Some features have gained newer replacements that aim to improve the design in
+5 -2
Documentation/gitrepository-layout.txt
··· 153 153 linkgit:git-worktree[1]). 154 154 155 155 branches:: 156 - A slightly deprecated way to store shorthands to be used 156 + A deprecated way to store shorthands to be used 157 157 to specify a URL to 'git fetch', 'git pull' and 'git push'. 158 158 A file can be stored as `branches/<name>` and then 159 159 'name' can be given to these commands in place of ··· 162 162 and not likely to be found in modern repositories. This 163 163 directory is ignored if $GIT_COMMON_DIR is set and 164 164 "$GIT_COMMON_DIR/branches" will be used instead. 165 - 165 + + 166 + Git will stop reading remotes from this directory in Git 3.0. 166 167 167 168 hooks:: 168 169 Hooks are customization scripts used by various Git ··· 238 239 and not likely to be found in modern repositories. This 239 240 directory is ignored if $GIT_COMMON_DIR is set and 240 241 "$GIT_COMMON_DIR/remotes" will be used instead. 242 + + 243 + Git will stop reading remotes from this directory in Git 3.0. 241 244 242 245 logs:: 243 246 Records of changes made to refs are stored in this directory.
+1
GIT-BUILD-OPTIONS.in
··· 45 45 TEST_SHELL_PATH=@TEST_SHELL_PATH@ 46 46 USE_GETTEXT_SCHEME=@USE_GETTEXT_SCHEME@ 47 47 USE_LIBPCRE2=@USE_LIBPCRE2@ 48 + WITH_BREAKING_CHANGES=@WITH_BREAKING_CHANGES@ 48 49 X=@X@
+7
Makefile
··· 1273 1273 BUILTIN_OBJS += builtin/name-rev.o 1274 1274 BUILTIN_OBJS += builtin/notes.o 1275 1275 BUILTIN_OBJS += builtin/pack-objects.o 1276 + ifndef WITH_BREAKING_CHANGES 1276 1277 BUILTIN_OBJS += builtin/pack-redundant.o 1278 + endif 1277 1279 BUILTIN_OBJS += builtin/pack-refs.o 1278 1280 BUILTIN_OBJS += builtin/patch-id.o 1279 1281 BUILTIN_OBJS += builtin/prune-packed.o ··· 2236 2238 COMPAT_OBJS += compat/fsmonitor/fsm-path-utils-$(FSMONITOR_OS_SETTINGS).o 2237 2239 endif 2238 2240 2241 + ifdef WITH_BREAKING_CHANGES 2242 + BASIC_CFLAGS += -DWITH_BREAKING_CHANGES 2243 + endif 2244 + 2239 2245 ifeq ($(TCLTK_PATH),) 2240 2246 NO_TCLTK = NoThanks 2241 2247 endif ··· 3194 3200 -e "s|@TEST_SHELL_PATH@|\'$(TEST_SHELL_PATH_SQ)\'|" \ 3195 3201 -e "s|@USE_GETTEXT_SCHEME@|\'$(USE_GETTEXT_SCHEME)\'|" \ 3196 3202 -e "s|@USE_LIBPCRE2@|\'$(USE_LIBPCRE2)\'|" \ 3203 + -e "s|@WITH_BREAKING_CHANGES@|\'$(WITH_BREAKING_CHANGES)\'|" \ 3197 3204 -e "s|@X@|\'$(X)\'|" \ 3198 3205 GIT-BUILD-OPTIONS.in >$@+ 3199 3206 @if grep -q '^[A-Z][A-Z_]*=@.*@$$' $@+; then echo "Unsubstituted build options in $@" >&2 && exit 1; fi
+2
builtin/remote.c
··· 642 642 strbuf_addf(&buf, "remote.%s.fetch", remote->name); 643 643 for (i = 0; i < remote->fetch.nr; i++) 644 644 git_config_set_multivar(buf.buf, remote->fetch.items[i].raw, "^$", 0); 645 + #ifndef WITH_BREAKING_CHANGES 645 646 if (remote->origin == REMOTE_REMOTES) 646 647 unlink_or_warn(git_path("remotes/%s", remote->name)); 647 648 else if (remote->origin == REMOTE_BRANCHES) 648 649 unlink_or_warn(git_path("branches/%s", remote->name)); 650 + #endif /* WITH_BREAKING_CHANGES */ 649 651 strbuf_release(&buf); 650 652 651 653 return 0;
-5
ci/lib.sh
··· 329 329 330 330 case "$distro" in 331 331 ubuntu-*) 332 - if test "$jobname" = "linux-gcc-default" 333 - then 334 - break 335 - fi 336 - 337 332 # Python 2 is end of life, and Ubuntu 23.04 and newer don't actually 338 333 # have it anymore. We thus only test with Python 2 on older LTS 339 334 # releases.
+2 -1
ci/run-build-and-tests.sh
··· 13 13 run_tests=t 14 14 15 15 case "$jobname" in 16 - linux-gcc) 16 + linux-breaking-changes) 17 17 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 18 + export WITH_BREAKING_CHANGES=YesPlease 18 19 ;; 19 20 linux-TEST-vars) 20 21 export OPENSSL_SHA1_UNSAFE=YesPlease
+1
contrib/buildsystems/CMakeLists.txt
··· 1205 1205 string(REPLACE "@TEST_SHELL_PATH@" "'${TEST_SHELL_PATH}'" git_build_options "${git_build_options}") 1206 1206 string(REPLACE "@USE_GETTEXT_SCHEME@" "" git_build_options "${git_build_options}") 1207 1207 string(REPLACE "@USE_LIBPCRE2@" "" git_build_options "${git_build_options}") 1208 + string(REPLACE "@WITH_BREAKING_CHANGES@" "" git_build_options "${git_build_options}") 1208 1209 string(REPLACE "@X@" "${EXE_EXTENSION}" git_build_options "${git_build_options}") 1209 1210 if(USE_VCPKG) 1210 1211 string(APPEND git_build_options "PATH=\"$PATH:$TEST_DIRECTORY/../compat/vcbuild/vcpkg/installed/x64-windows/bin\"\n")
+2
git.c
··· 587 587 { "name-rev", cmd_name_rev, RUN_SETUP }, 588 588 { "notes", cmd_notes, RUN_SETUP }, 589 589 { "pack-objects", cmd_pack_objects, RUN_SETUP }, 590 + #ifndef WITH_BREAKING_CHANGES 590 591 { "pack-redundant", cmd_pack_redundant, RUN_SETUP | NO_PARSEOPT }, 592 + #endif 591 593 { "pack-refs", cmd_pack_refs, RUN_SETUP }, 592 594 { "patch-id", cmd_patch_id, RUN_SETUP_GENTLY | NO_PARSEOPT }, 593 595 { "pickaxe", cmd_blame, RUN_SETUP },
+6
meson.build
··· 655 655 build_options_config.set_quoted('LOCALEDIR', fs.as_posix(get_option('prefix') / get_option('localedir'))) 656 656 build_options_config.set('GITWEBDIR', fs.as_posix(get_option('prefix') / get_option('datadir') / 'gitweb')) 657 657 658 + if get_option('breaking_changes') 659 + build_options_config.set('WITH_BREAKING_CHANGES', 'YesPlease') 660 + else 661 + build_options_config.set('WITH_BREAKING_CHANGES', '') 662 + endif 663 + 658 664 if get_option('sane_tool_path') != '' 659 665 build_options_config.set_quoted('BROKEN_PATH_FIX', 's|^\# @BROKEN_PATH_FIX@$|git_broken_path_fix "' + get_option('sane_tool_path') + '"|') 660 666 else
+2
meson_options.txt
··· 59 59 description: 'The backend used for hashing objects with the SHA256 object format.') 60 60 61 61 # Build tweaks. 62 + option('breaking_changes', type: 'boolean', value: false, 63 + description: 'Enable upcoming breaking changes.') 62 64 option('macos_use_homebrew_gettext', type: 'boolean', value: true, 63 65 description: 'Use gettext from Homebrew instead of the slightly-broken system-provided one.') 64 66
+26
remote.c
··· 294 294 rewrite->instead_of_nr++; 295 295 } 296 296 297 + #ifndef WITH_BREAKING_CHANGES 297 298 static const char *skip_spaces(const char *s) 298 299 { 299 300 while (isspace(*s)) ··· 301 302 return s; 302 303 } 303 304 305 + static void warn_about_deprecated_remote_type(const char *type, 306 + const struct remote *remote) 307 + { 308 + warning(_("reading remote from \"%s/%s\", which is nominated for removal.\n" 309 + "\n" 310 + "If you still use the \"remotes/\" directory it is recommended to\n" 311 + "migrate to config-based remotes:\n" 312 + "\n" 313 + "\tgit remote rename %s %s\n" 314 + "\n" 315 + "If you cannot, please let us know why you still need to use it by\n" 316 + "sending an e-mail to <git@vger.kernel.org>."), 317 + type, remote->name, remote->name, remote->name); 318 + } 319 + 304 320 static void read_remotes_file(struct remote_state *remote_state, 305 321 struct remote *remote) 306 322 { ··· 309 325 310 326 if (!f) 311 327 return; 328 + 329 + warn_about_deprecated_remote_type("remotes", remote); 330 + 312 331 remote->configured_in_repo = 1; 313 332 remote->origin = REMOTE_REMOTES; 314 333 while (strbuf_getline(&buf, f) != EOF) { ··· 338 357 if (!f) 339 358 return; 340 359 360 + warn_about_deprecated_remote_type("branches", remote); 361 + 341 362 strbuf_getline_lf(&buf, f); 342 363 fclose(f); 343 364 strbuf_trim(&buf); ··· 375 396 strbuf_release(&buf); 376 397 free(to_free); 377 398 } 399 + #endif /* WITH_BREAKING_CHANGES */ 378 400 379 401 static int handle_config(const char *key, const char *value, 380 402 const struct config_context *ctx, void *cb) ··· 591 613 alias_all_urls(repo->remote_state); 592 614 } 593 615 616 + #ifndef WITH_BREAKING_CHANGES 594 617 static int valid_remote_nick(const char *name) 595 618 { 596 619 if (!name[0] || is_dot_or_dotdot(name)) ··· 602 625 return 0; 603 626 return 1; 604 627 } 628 + #endif /* WITH_BREAKING_CHANGES */ 605 629 606 630 static const char *remotes_remote_for_branch(struct remote_state *remote_state, 607 631 struct branch *branch, ··· 744 768 &name_given); 745 769 746 770 ret = make_remote(remote_state, name, 0); 771 + #ifndef WITH_BREAKING_CHANGES 747 772 if (valid_remote_nick(name) && have_git_dir()) { 748 773 if (!valid_remote(ret)) 749 774 read_remotes_file(remote_state, ret); 750 775 if (!valid_remote(ret)) 751 776 read_branches_file(remote_state, ret); 752 777 } 778 + #endif /* WITH_BREAKING_CHANGES */ 753 779 if (name_given && !valid_remote(ret)) 754 780 add_url_alias(remote_state, ret, name); 755 781 if (!valid_remote(ret))
+2
remote.h
··· 21 21 enum { 22 22 REMOTE_UNCONFIGURED = 0, 23 23 REMOTE_CONFIG, 24 + #ifndef WITH_BREAKING_CHANGES 24 25 REMOTE_REMOTES, 25 26 REMOTE_BRANCHES 27 + #endif /* WITH_BREAKING_CHANGES */ 26 28 }; 27 29 28 30 struct rewrite {
+6
t/t5323-pack-redundant.sh
··· 36 36 37 37 . ./test-lib.sh 38 38 39 + if ! test_have_prereq WITHOUT_BREAKING_CHANGES 40 + then 41 + skip_all='skipping git-pack-redundant tests; built with breaking changes' 42 + test_done 43 + fi 44 + 39 45 main_repo=main.git 40 46 shared_repo=shared.git 41 47
+3 -3
t/t5505-remote.sh
··· 1113 1113 Pull: refs/heads/next:refs/heads/origin2 1114 1114 EOF 1115 1115 1116 - test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' ' 1116 + test_expect_success WITHOUT_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/remotes' ' 1117 1117 git clone one five && 1118 1118 origin_url=$(pwd)/one && 1119 1119 ( ··· 1139 1139 ) 1140 1140 ' 1141 1141 1142 - test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' ' 1142 + test_expect_success WITHOUT_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/branches' ' 1143 1143 git clone --template= one six && 1144 1144 origin_url=$(pwd)/one && 1145 1145 ( ··· 1155 1155 ) 1156 1156 ' 1157 1157 1158 - test_expect_success 'migrate a remote from named file in $GIT_DIR/branches (2)' ' 1158 + test_expect_success WITHOUT_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/branches (2)' ' 1159 1159 git clone --template= one seven && 1160 1160 ( 1161 1161 cd seven &&
+5 -8
t/t5510-fetch.sh
··· 34 34 git clone . three && 35 35 ( 36 36 cd three && 37 - git config branch.main.remote two && 38 - git config branch.main.merge refs/heads/one && 39 - mkdir -p .git/remotes && 40 - cat >.git/remotes/two <<-\EOF 41 - URL: ../two/.git/ 42 - Pull: refs/heads/main:refs/heads/two 43 - Pull: refs/heads/one:refs/heads/one 44 - EOF 37 + git config set remote.two.url ../two/.git/ && 38 + git config set remote.two.fetch refs/heads/main:refs/heads/two && 39 + git config set --append remote.two.fetch refs/heads/one:refs/heads/one && 40 + git config set branch.main.remote two && 41 + git config set branch.main.merge refs/heads/one 45 42 ) && 46 43 git clone . bundle && 47 44 git clone . seven
+22 -19
t/t5515-fetch-merge-logic.sh
··· 104 104 git config remote.config-glob.fetch refs/heads/*:refs/remotes/rem/* && 105 105 remotes="$remotes config-glob" && 106 106 107 - mkdir -p .git/remotes && 108 - cat >.git/remotes/remote-explicit <<-\EOF && 109 - URL: ../.git/ 110 - Pull: refs/heads/main:remotes/rem/main 111 - Pull: refs/heads/one:remotes/rem/one 112 - Pull: two:remotes/rem/two 113 - Pull: refs/heads/three:remotes/rem/three 114 - EOF 115 - remotes="$remotes remote-explicit" && 107 + if test_have_prereq WITHOUT_BREAKING_CHANGES 108 + then 109 + mkdir -p .git/remotes && 110 + cat >.git/remotes/remote-explicit <<-\EOF && 111 + URL: ../.git/ 112 + Pull: refs/heads/main:remotes/rem/main 113 + Pull: refs/heads/one:remotes/rem/one 114 + Pull: two:remotes/rem/two 115 + Pull: refs/heads/three:remotes/rem/three 116 + EOF 117 + remotes="$remotes remote-explicit" && 116 118 117 - cat >.git/remotes/remote-glob <<-\EOF && 118 - URL: ../.git/ 119 - Pull: refs/heads/*:refs/remotes/rem/* 120 - EOF 121 - remotes="$remotes remote-glob" && 119 + cat >.git/remotes/remote-glob <<-\EOF && 120 + URL: ../.git/ 121 + Pull: refs/heads/*:refs/remotes/rem/* 122 + EOF 123 + remotes="$remotes remote-glob" && 122 124 123 - mkdir -p .git/branches && 124 - echo "../.git" > .git/branches/branches-default && 125 - remotes="$remotes branches-default" && 125 + mkdir -p .git/branches && 126 + echo "../.git" > .git/branches/branches-default && 127 + remotes="$remotes branches-default" && 126 128 127 - echo "../.git#one" > .git/branches/branches-one && 128 - remotes="$remotes branches-one" && 129 + echo "../.git#one" > .git/branches/branches-one && 130 + remotes="$remotes branches-one" 131 + fi && 129 132 130 133 for remote in $remotes ; do 131 134 git config branch.br-$remote.remote $remote &&
+6 -8
t/t5516-fetch-push.sh
··· 975 975 ! grep "warning: updating the current branch" stderr 976 976 ' 977 977 978 - test_expect_success 'fetch with branches' ' 978 + test_expect_success WITHOUT_BREAKING_CHANGES 'fetch with branches' ' 979 979 mk_empty testrepo && 980 980 git branch second $the_first_commit && 981 981 git checkout second && ··· 991 991 git checkout main 992 992 ' 993 993 994 - test_expect_success 'fetch with branches containing #' ' 994 + test_expect_success WITHOUT_BREAKING_CHANGES 'fetch with branches containing #' ' 995 995 mk_empty testrepo && 996 996 mkdir testrepo/.git/branches && 997 997 echo "..#second" > testrepo/.git/branches/branch2 && ··· 1005 1005 git checkout main 1006 1006 ' 1007 1007 1008 - test_expect_success 'push with branches' ' 1008 + test_expect_success WITHOUT_BREAKING_CHANGES 'push with branches' ' 1009 1009 mk_empty testrepo && 1010 1010 git checkout second && 1011 1011 ··· 1022 1022 ) 1023 1023 ' 1024 1024 1025 - test_expect_success 'push with branches containing #' ' 1025 + test_expect_success WITHOUT_BREAKING_CHANGES 'push with branches containing #' ' 1026 1026 mk_empty testrepo && 1027 1027 1028 1028 test_when_finished "rm -rf .git/branches" && ··· 1211 1211 ' 1212 1212 1213 1213 test_expect_success 'push --prune' ' 1214 - mk_test testrepo heads/main heads/second heads/foo heads/bar && 1214 + mk_test testrepo heads/main heads/foo heads/bar && 1215 1215 git push --prune testrepo : && 1216 1216 check_push_result testrepo $the_commit heads/main && 1217 - check_push_result testrepo $the_first_commit heads/second && 1218 1217 ! check_push_result testrepo $the_first_commit heads/foo heads/bar 1219 1218 ' 1220 1219 1221 1220 test_expect_success 'push --prune refspec' ' 1222 - mk_test testrepo tmp/main tmp/second tmp/foo tmp/bar && 1221 + mk_test testrepo tmp/main tmp/foo tmp/bar && 1223 1222 git push --prune testrepo "refs/heads/*:refs/tmp/*" && 1224 1223 check_push_result testrepo $the_commit tmp/main && 1225 - check_push_result testrepo $the_first_commit tmp/second && 1226 1224 ! check_push_result testrepo $the_first_commit tmp/foo tmp/bar 1227 1225 ' 1228 1226
+4
t/test-lib.sh
··· 1862 1862 curl --version 1863 1863 ' 1864 1864 1865 + test_lazy_prereq WITHOUT_BREAKING_CHANGES ' 1866 + test -z "$WITH_BREAKING_CHANGES" 1867 + ' 1868 + 1865 1869 # SHA1 is a test if the hash algorithm in use is SHA-1. This is both for tests 1866 1870 # which will not work with other hash algorithms and tests that work but don't 1867 1871 # test anything meaningful (e.g. special values which cause short collisions).