Skip to content

Commit 8ccc75c

Browse files
pks-tgitster
authored andcommitted
remote: announce removal of "branches/" and "remotes/"
Back when Git was in its infancy, remotes were configured via separate files in "branches/" (back in 2005). This mechanism was replaced later that year with the "remotes/" directory. Both mechanisms have eventually been replaced by config-based remotes, and it is very unlikely that anybody still uses these directories to configure their remotes. Both of these directories have been marked as deprecated, one in 2005 and the other one in 2011. Follow through with the deprecation and finally announce the removal of these features in Git 3.0. Signed-off-by: Patrick Steinhardt <[email protected]> [jc: with a small tweak to the help message] Signed-off-by: Junio C Hamano <[email protected]>
1 parent 68f5187 commit 8ccc75c

File tree

9 files changed

+99
-43
lines changed

9 files changed

+99
-43
lines changed

Documentation/BreakingChanges.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,31 @@ Cf. <[email protected]>,
154154
<CAKvOHKAFXQwt4D8yUCCkf_TQL79mYaJ=KAKhtpDNTvHJFuX1NA@mail.gmail.com>,
155155
156156

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+
157182
== Superseded features that will not be deprecated
158183

159184
Some features have gained newer replacements that aim to improve the design in

Documentation/gitrepository-layout.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ config.worktree::
153153
linkgit:git-worktree[1]).
154154

155155
branches::
156-
A slightly deprecated way to store shorthands to be used
156+
A deprecated way to store shorthands to be used
157157
to specify a URL to 'git fetch', 'git pull' and 'git push'.
158158
A file can be stored as `branches/<name>` and then
159159
'name' can be given to these commands in place of
@@ -162,7 +162,8 @@ branches::
162162
and not likely to be found in modern repositories. This
163163
directory is ignored if $GIT_COMMON_DIR is set and
164164
"$GIT_COMMON_DIR/branches" will be used instead.
165-
165+
+
166+
Git will stop reading remotes from this directory in Git 3.0.
166167

167168
hooks::
168169
Hooks are customization scripts used by various Git
@@ -238,6 +239,8 @@ remotes::
238239
and not likely to be found in modern repositories. This
239240
directory is ignored if $GIT_COMMON_DIR is set and
240241
"$GIT_COMMON_DIR/remotes" will be used instead.
242+
+
243+
Git will stop reading remotes from this directory in Git 3.0.
241244

242245
logs::
243246
Records of changes made to refs are stored in this directory.

builtin/remote.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,10 +640,12 @@ static int migrate_file(struct remote *remote)
640640
strbuf_addf(&buf, "remote.%s.fetch", remote->name);
641641
for (i = 0; i < remote->fetch.nr; i++)
642642
git_config_set_multivar(buf.buf, remote->fetch.items[i].raw, "^$", 0);
643+
#ifndef WITH_BREAKING_CHANGES
643644
if (remote->origin == REMOTE_REMOTES)
644645
unlink_or_warn(git_path("remotes/%s", remote->name));
645646
else if (remote->origin == REMOTE_BRANCHES)
646647
unlink_or_warn(git_path("branches/%s", remote->name));
648+
#endif /* WITH_BREAKING_CHANGES */
647649
strbuf_release(&buf);
648650

649651
return 0;

remote.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,13 +293,29 @@ static void add_instead_of(struct rewrite *rewrite, const char *instead_of)
293293
rewrite->instead_of_nr++;
294294
}
295295

296+
#ifndef WITH_BREAKING_CHANGES
296297
static const char *skip_spaces(const char *s)
297298
{
298299
while (isspace(*s))
299300
s++;
300301
return s;
301302
}
302303

304+
static void warn_about_deprecated_remote_type(const char *type,
305+
const struct remote *remote)
306+
{
307+
warning(_("reading remote from \"%s/%s\", which is nominated for removal.\n"
308+
"\n"
309+
"If you still use the \"remotes/\" directory it is recommended to\n"
310+
"migrate to config-based remotes:\n"
311+
"\n"
312+
"\tgit remote rename %s %s\n"
313+
"\n"
314+
"If you cannot, please let us know why you still need to use it by\n"
315+
"sending an e-mail to <[email protected]>."),
316+
type, remote->name, remote->name, remote->name);
317+
}
318+
303319
static void read_remotes_file(struct remote_state *remote_state,
304320
struct remote *remote)
305321
{
@@ -308,6 +324,9 @@ static void read_remotes_file(struct remote_state *remote_state,
308324

309325
if (!f)
310326
return;
327+
328+
warn_about_deprecated_remote_type("remotes", remote);
329+
311330
remote->configured_in_repo = 1;
312331
remote->origin = REMOTE_REMOTES;
313332
while (strbuf_getline(&buf, f) != EOF) {
@@ -337,6 +356,8 @@ static void read_branches_file(struct remote_state *remote_state,
337356
if (!f)
338357
return;
339358

359+
warn_about_deprecated_remote_type("branches", remote);
360+
340361
strbuf_getline_lf(&buf, f);
341362
fclose(f);
342363
strbuf_trim(&buf);
@@ -374,6 +395,7 @@ static void read_branches_file(struct remote_state *remote_state,
374395
strbuf_release(&buf);
375396
free(to_free);
376397
}
398+
#endif /* WITH_BREAKING_CHANGES */
377399

378400
static int handle_config(const char *key, const char *value,
379401
const struct config_context *ctx, void *cb)
@@ -572,6 +594,7 @@ static void read_config(struct repository *repo, int early)
572594
alias_all_urls(repo->remote_state);
573595
}
574596

597+
#ifndef WITH_BREAKING_CHANGES
575598
static int valid_remote_nick(const char *name)
576599
{
577600
if (!name[0] || is_dot_or_dotdot(name))
@@ -583,6 +606,7 @@ static int valid_remote_nick(const char *name)
583606
return 0;
584607
return 1;
585608
}
609+
#endif /* WITH_BREAKING_CHANGES */
586610

587611
static const char *remotes_remote_for_branch(struct remote_state *remote_state,
588612
struct branch *branch,
@@ -725,12 +749,14 @@ remotes_remote_get_1(struct remote_state *remote_state, const char *name,
725749
&name_given);
726750

727751
ret = make_remote(remote_state, name, 0);
752+
#ifndef WITH_BREAKING_CHANGES
728753
if (valid_remote_nick(name) && have_git_dir()) {
729754
if (!valid_remote(ret))
730755
read_remotes_file(remote_state, ret);
731756
if (!valid_remote(ret))
732757
read_branches_file(remote_state, ret);
733758
}
759+
#endif /* WITH_BREAKING_CHANGES */
734760
if (name_given && !valid_remote(ret))
735761
add_url_alias(remote_state, ret, name);
736762
if (!valid_remote(ret))

remote.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ struct transport_ls_refs_options;
2121
enum {
2222
REMOTE_UNCONFIGURED = 0,
2323
REMOTE_CONFIG,
24+
#ifndef WITH_BREAKING_CHANGES
2425
REMOTE_REMOTES,
2526
REMOTE_BRANCHES
27+
#endif /* WITH_BREAKING_CHANGES */
2628
};
2729

2830
struct rewrite {

t/t5505-remote.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,7 @@ Pull: refs/heads/main:refs/heads/origin
10071007
Pull: refs/heads/next:refs/heads/origin2
10081008
EOF
10091009

1010-
test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' '
1010+
test_expect_success WITHOUT_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/remotes' '
10111011
git clone one five &&
10121012
origin_url=$(pwd)/one &&
10131013
(
@@ -1033,7 +1033,7 @@ test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' '
10331033
)
10341034
'
10351035

1036-
test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' '
1036+
test_expect_success WITHOUT_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/branches' '
10371037
git clone --template= one six &&
10381038
origin_url=$(pwd)/one &&
10391039
(
@@ -1049,7 +1049,7 @@ test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' '
10491049
)
10501050
'
10511051

1052-
test_expect_success 'migrate a remote from named file in $GIT_DIR/branches (2)' '
1052+
test_expect_success WITHOUT_BREAKING_CHANGES 'migrate a remote from named file in $GIT_DIR/branches (2)' '
10531053
git clone --template= one seven &&
10541054
(
10551055
cd seven &&

t/t5510-fetch.sh

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,11 @@ test_expect_success "clone and setup child repos" '
3434
git clone . three &&
3535
(
3636
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
4542
) &&
4643
git clone . bundle &&
4744
git clone . seven

t/t5515-fetch-merge-logic.sh

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -104,28 +104,31 @@ test_expect_success setup '
104104
git config remote.config-glob.fetch refs/heads/*:refs/remotes/rem/* &&
105105
remotes="$remotes config-glob" &&
106106
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" &&
116-
117-
cat >.git/remotes/remote-glob <<-\EOF &&
118-
URL: ../.git/
119-
Pull: refs/heads/*:refs/remotes/rem/*
120-
EOF
121-
remotes="$remotes remote-glob" &&
122-
123-
mkdir -p .git/branches &&
124-
echo "../.git" > .git/branches/branches-default &&
125-
remotes="$remotes branches-default" &&
126-
127-
echo "../.git#one" > .git/branches/branches-one &&
128-
remotes="$remotes branches-one" &&
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" &&
118+
119+
cat >.git/remotes/remote-glob <<-\EOF &&
120+
URL: ../.git/
121+
Pull: refs/heads/*:refs/remotes/rem/*
122+
EOF
123+
remotes="$remotes remote-glob" &&
124+
125+
mkdir -p .git/branches &&
126+
echo "../.git" > .git/branches/branches-default &&
127+
remotes="$remotes branches-default" &&
128+
129+
echo "../.git#one" > .git/branches/branches-one &&
130+
remotes="$remotes branches-one"
131+
fi &&
129132
130133
for remote in $remotes ; do
131134
git config branch.br-$remote.remote $remote &&

t/t5516-fetch-push.sh

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -975,7 +975,7 @@ test_expect_success 'allow push to HEAD of non-bare repository (config)' '
975975
! grep "warning: updating the current branch" stderr
976976
'
977977

978-
test_expect_success 'fetch with branches' '
978+
test_expect_success WITHOUT_BREAKING_CHANGES 'fetch with branches' '
979979
mk_empty testrepo &&
980980
git branch second $the_first_commit &&
981981
git checkout second &&
@@ -991,7 +991,7 @@ test_expect_success 'fetch with branches' '
991991
git checkout main
992992
'
993993

994-
test_expect_success 'fetch with branches containing #' '
994+
test_expect_success WITHOUT_BREAKING_CHANGES 'fetch with branches containing #' '
995995
mk_empty testrepo &&
996996
mkdir testrepo/.git/branches &&
997997
echo "..#second" > testrepo/.git/branches/branch2 &&
@@ -1005,7 +1005,7 @@ test_expect_success 'fetch with branches containing #' '
10051005
git checkout main
10061006
'
10071007

1008-
test_expect_success 'push with branches' '
1008+
test_expect_success WITHOUT_BREAKING_CHANGES 'push with branches' '
10091009
mk_empty testrepo &&
10101010
git checkout second &&
10111011
@@ -1022,7 +1022,7 @@ test_expect_success 'push with branches' '
10221022
)
10231023
'
10241024

1025-
test_expect_success 'push with branches containing #' '
1025+
test_expect_success WITHOUT_BREAKING_CHANGES 'push with branches containing #' '
10261026
mk_empty testrepo &&
10271027
10281028
test_when_finished "rm -rf .git/branches" &&
@@ -1211,18 +1211,16 @@ test_expect_success 'push --porcelain --dry-run rejected' '
12111211
'
12121212

12131213
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 &&
12151215
git push --prune testrepo : &&
12161216
check_push_result testrepo $the_commit heads/main &&
1217-
check_push_result testrepo $the_first_commit heads/second &&
12181217
! check_push_result testrepo $the_first_commit heads/foo heads/bar
12191218
'
12201219

12211220
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 &&
12231222
git push --prune testrepo "refs/heads/*:refs/tmp/*" &&
12241223
check_push_result testrepo $the_commit tmp/main &&
1225-
check_push_result testrepo $the_first_commit tmp/second &&
12261224
! check_push_result testrepo $the_first_commit tmp/foo tmp/bar
12271225
'
12281226

0 commit comments

Comments
 (0)