summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2025-10-15 08:26:08 +0200
committerJunio C Hamano <gitster@pobox.com>2025-10-15 09:11:08 -0700
commitf570bd91b3b2c6c5ef2035e3ce3ed76e613e74a7 (patch)
tree0b8d2d0b7282b00064be165f1f92a8bb04e32d14
parentac7d021f0659f5a81be7b69a54a19c9618ce9dba (diff)
refs/files: deprecate writing symrefs as symbolic links
The "files" backend has the ability to store symbolic refs as symbolic links, which can be configured via "core.preferSymlinkRefs". This feature stems back from the early days: the initial implementation of symbolic refs used symlinks exclusively. The symref format was only introduced in 9b143c6e15 (Teach update-ref about a symbolic ref stored in a textfile., 2005-09-25) and made the default in 9f0bb90d16 (core.prefersymlinkrefs: use symlinks for .git/HEAD, 2006-05-02). This is all about 20 years ago, and there are no known reasons nowadays why one would want to use symlinks instead of symrefs. Mark the feature for deprecation in Git 3.0. Note that this only deprecates _writing_ symrefs as symbolic links. Reading such symrefs is still supported for now. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--Documentation/BreakingChanges.adoc20
-rw-r--r--Documentation/config/core.adoc3
-rw-r--r--refs/files-backend.c19
-rwxr-xr-xt/t0600-reffiles-backend.sh26
4 files changed, 63 insertions, 5 deletions
diff --git a/Documentation/BreakingChanges.adoc b/Documentation/BreakingChanges.adoc
index 90b53abcea..f814450d2f 100644
--- a/Documentation/BreakingChanges.adoc
+++ b/Documentation/BreakingChanges.adoc
@@ -295,6 +295,26 @@ The command will be removed.
+
cf. <xmqqa59i45wc.fsf@gitster.g>
+* Support for `core.preferSymlinkRefs=true` has been deprecated and will be
+ removed in Git 3.0. Writing symbolic refs as symbolic links will be phased
+ out in favor of using plain files using the textual representation of
+ symbolic refs.
++
+Symbolic references were initially always stored as a symbolic link. This was
+changed in 9b143c6e15 (Teach update-ref about a symbolic ref stored in a
+textfile., 2005-09-25), where a new textual symref format was introduced to
+store those symbolic refs in a plain file. In 9f0bb90d16
+(core.prefersymlinkrefs: use symlinks for .git/HEAD, 2006-05-02), the Git
+project switched the default to use the textual symrefs in favor of symbolic
+links.
++
+The migration away from symbolic links has happened almost 20 years ago by now,
+and there is no known reason why one should prefer them nowadays. Furthermore,
+symbolic links are not supported on some platforms.
++
+Note that only the writing side for such symbolic links is deprecated. Reading
+such symbolic links is still supported for now.
+
== Superseded features that will not be deprecated
Some features have gained newer replacements that aim to improve the design in
diff --git a/Documentation/config/core.adoc b/Documentation/config/core.adoc
index 08739bb9d4..406d7029d9 100644
--- a/Documentation/config/core.adoc
+++ b/Documentation/config/core.adoc
@@ -290,6 +290,9 @@ core.preferSymlinkRefs::
and other symbolic reference files, use symbolic links.
This is sometimes needed to work with old scripts that
expect HEAD to be a symbolic link.
++
+This configuration is deprecated and will be removed in Git 3.0. Symbolic refs
+will always be written as textual symrefs.
core.alternateRefsCommand::
When advertising tips of available history from an alternate, use the shell to
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 5ddf418b18..2c48526ef2 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -2113,20 +2113,35 @@ static int commit_ref_update(struct files_ref_store *refs,
return 0;
}
-#ifdef NO_SYMLINK_HEAD
+#if defined(NO_SYMLINK_HEAD) || defined(WITH_BREAKING_CHANGES)
#define create_ref_symlink(a, b) (-1)
#else
static int create_ref_symlink(struct ref_lock *lock, const char *target)
{
+ static int warn_once = 1;
+ char *ref_path;
int ret = -1;
- char *ref_path = get_locked_file_path(&lock->lk);
+ ref_path = get_locked_file_path(&lock->lk);
unlink(ref_path);
ret = symlink(target, ref_path);
free(ref_path);
if (ret)
fprintf(stderr, "no symlink - falling back to symbolic ref\n");
+
+ if (warn_once)
+ warning(_("'core.preferSymlinkRefs=true' is nominated for removal.\n"
+ "hint: The use of symbolic links for symbolic refs is deprecated\n"
+ "hint: and will be removed in Git 3.0. The configuration that\n"
+ "hint: tells Git to use them is thus going away. You can unset\n"
+ "hint: it with:\n"
+ "hint:\n"
+ "hint:\tgit config unset core.preferSymlinkRefs\n"
+ "hint:\n"
+ "hint: Git will then use the textual symref format instead."));
+ warn_once = 0;
+
return ret;
}
#endif
diff --git a/t/t0600-reffiles-backend.sh b/t/t0600-reffiles-backend.sh
index 1e62c791d9..b11126ed47 100755
--- a/t/t0600-reffiles-backend.sh
+++ b/t/t0600-reffiles-backend.sh
@@ -477,9 +477,29 @@ test_expect_success SYMLINKS 'symref transaction supports symlinks' '
prepare
commit
EOF
- git update-ref --no-deref --stdin <stdin &&
- test_path_is_symlink .git/TEST_SYMREF_HEAD &&
- test "$(test_readlink .git/TEST_SYMREF_HEAD)" = refs/heads/new
+ git update-ref --no-deref --stdin <stdin 2>err &&
+ if test_have_prereq WITH_BREAKING_CHANGES
+ then
+ test_path_is_file .git/TEST_SYMREF_HEAD &&
+ echo "ref: refs/heads/new" >expect &&
+ test_cmp expect .git/TEST_SYMREF_HEAD &&
+ test_must_be_empty err
+ else
+ test_path_is_symlink .git/TEST_SYMREF_HEAD &&
+ test "$(test_readlink .git/TEST_SYMREF_HEAD)" = refs/heads/new &&
+ cat >expect <<-EOF &&
+ warning: ${SQ}core.preferSymlinkRefs=true${SQ} is nominated for removal.
+ hint: The use of symbolic links for symbolic refs is deprecated
+ hint: and will be removed in Git 3.0. The configuration that
+ hint: tells Git to use them is thus going away. You can unset
+ hint: it with:
+ hint:
+ hint: git config unset core.preferSymlinkRefs
+ hint:
+ hint: Git will then use the textual symref format instead.
+ EOF
+ test_cmp expect err
+ fi
'
test_expect_success 'symref transaction supports false symlink config' '