↓Перейти к содержанию
  1. Git: руководства и команды/

Символические ссылки в Git: как работают и почему не пушатся

·6 минут·

Символические ссылки (symlinks) — это хитрая штука в Git. Многие разработчики сталкиваются с ситуацией, когда симлинк добавляют в репозиторий, пушат его на удалённый сервер, а на машине коллеги вместо симлинка появляется обычный текстовый файл. Или наоборот — на Windows симлинк вообще не создаётся. Давайте разберёмся, как на самом деле Git работает с символическими ссылками и почему возникают эти проблемы.

Как Git хранит символические ссылки #

На первый взгляд может показаться, что Git хранит содержимое файла, на который указывает симлинк. На самом деле это не так. Git хранит саму ссылку — то есть путь, на который указывает симлинк, а не содержимое целевого файла.

Когда вы добавляете символическую ссылку в Git, она сохраняется как объект типа blob с режимом 120000. Это специальный режим в Git, который означает “это символическая ссылка”. Проверить это можно командой:

git ls-files -s

В выводе вы увидите что-то вроде:

100644 abc1234... 0  обычный-файл.txt
120000 def5678... 0  мой-симлинк -> target/path

Первое число — это режим доступа. 100644 — обычный файл, 120000 — это и есть символическая ссылка.

Чтобы посмотреть, что именно хранится в этом blob-объекте, используйте git cat-file:

git cat-file -p def5678...

Вывод покажет просто текст пути: target/path. Больше ничего. Git не хранит содержимое файла, на который указывает ссылка. Он хранит только путь назначения.

“Симлинк не передаётся” — на самом деле это не совсем верно #

Если вы столкнулись с ситуацией, когда симлинк “не передаётся” на удалённый репозиторий, скорее всего, передаётся, но на машине коллеги (особенно на Windows) создаётся обычный файл вместо ссылки.

Проблема: Windows и core.symlinks=false #

На Windows Git по умолчанию настроен так, что он не может создавать реальные символические ссылки. Причина? На Windows создание симлинков требует либо прав администратора, либо включённого режима разработчика (Developer Mode) в Windows 10/11.

Когда core.symlinks=false, Git поступает очень практично: вместо создания симлинка он создаёт обычный текстовый файл с содержимым, которое должно быть путём ссылки. Это может привести к путанице.

Проверить текущее значение можно:

git config core.symlinks

Если вывод пуст или вы видите false, значит симлинки отключены.

Для Windows 10/11 с Developer Mode:

git config core.symlinks true

Это включит поддержку симлинков глобально. Но важно: на вашей машине должен быть включён Developer Mode. Включается через Settings → Update & Security → For developers → Developer Mode.

Для администраторов или локальной настройки:

Если вы хотите настроить только для одного репозитория:

cd /path/to/repo
git config core.symlinks true

Другие файловые системы #

Некоторые файловые системы просто не поддерживают символические ссылки:

  • FAT32 — полностью не поддерживает
  • exFAT — не поддерживает
  • NTFS — поддерживает, но требует прав администратора

Если вы работаете с флеш-накопителем или внешним диском с FAT32, симлинки в Git просто не будут работать.

Найти все символические ссылки в репозитории #

В вашем рабочем каталоге:

find . -type l

В индексе Git:

git ls-files --stage | grep "^120000"

Это покажет все объекты, которые Git считает символическими ссылками.

Добавить символическую ссылку в репозиторий #

Сначала создайте симлинк в файловой системе:

ln -s target/path мой-симлинк

Затем добавьте его в Git как обычно:

git add мой-симлинк
git commit -m "Add symlink"

Git автоматически определит, что это симлинк, и сохранит его как blob с режимом 120000.

Зафиксировать сломанный симлинк #

Если у вас в репозитории есть “сломанный” симлинк (dangling symlink) — ссылка на файл, который не существует в рабочей директории — это совершенно нормально для Git. Он всё равно сохранит этот путь:

ln -s несуществующий/файл broken-symlink
git add broken-symlink
git commit -m "Add broken symlink"

Git будет счастлив. А вот при клонировании репозитория на другую машину такой симлинк остаётся сломанным и в файловой системе, что может быть или не быть проблемой в зависимости от вашего use case.

Допустим, вы на Linux создали симлинк и закоммитили:

ln -s ../target target-link
git add target-link
git commit -m "Add symlink"
git push

Ваш коллега клонирует репозиторий на Windows с core.symlinks=false. Вместо реального симлинка он получит файл с содержимым ../target. Если в его коде используется этот “файл” как путь, вещи могут сломаться.

Решение: договориться с командой о том, какая настройка core.symlinks должна быть, или вообще избежать использования симлинков в многоплатформных проектах.

Права доступа к симлинкам #

На Unix-системах у симлинка есть права доступа, но они обычно игнорируются. Git не хранит права доступа симлинков специально — он хранит только путь.

Если вы хотите явно указать Git, как обращаться с определёнными файлами или шаблонами, можно использовать .gitattributes. Это особенно полезно в многоплатформных проектах.

# Никогда не конвертировать эти файлы при клонировании
*.symlink eol=lf

# Для определённых путей
node_modules/** text=auto

Однако .gitattributes не может напрямую “исправить” проблему с core.symlinks=false. Это больше о нормализации окончаний строк и других атрибутах.

Честно говоря, использование симлинков в репозитории часто приводит к больше проблем, чем пользы, особенно в многоплатформных проектах. Давайте посмотрим на альтернативы.

Альтернатива 1: Git submodules #

Если вы хотите ссылаться на другой репозиторий, используйте Git submodules:

git submodule add https://github.com/example/repo.git path/to/submodule

Это более надёжно и явно отражает зависимость.

Альтернатива 2: Git worktree #

Если вам нужна отдельная рабочая копия одного репозитория, используйте git worktree:

git worktree add ../related-work main

Это создаст новую рабочую директорию, связанную с тем же репозиторием.

Альтернатива 3: Просто скопируйте файлы #

Если вам нужно, чтобы один и тот же файл был в нескольких местах, просто поддерживайте его синхронизацию вручную или через скрипты. Это может быть скучнее, но намного надёжнее.

Практические команды и рецепты #

Показать тип объекта для файла в индексе #

git ls-files --stage | head -5

Смотрим на первое число в каждой строке. 120000 означает симлинк.

git ls-files --stage | grep "^120000" | awk '{print $2}' | while read hash; do
  git cat-file -p "$hash"
done
git rm --cached мой-симлинк
git commit -m "Remove symlink"

Файл останется в вашей рабочей директории, но будет удалён из Git.

На Ubuntu/Debian, если что-то пошло не так и симлинки стали файлами:

git rm --cached -r .
git reset --hard

Это удалит всё из индекса и восстановит файлы из Git. Симлинки будут восстановлены правильно (если core.symlinks=true).

FAQ: вопросы, которые часто задают #

Почему мой симлинк превратился в текстовый файл? #

Скорее всего, вы работаете на Windows с core.symlinks=false. Проверьте:

git config core.symlinks

Если нужно включить (и у вас есть Developer Mode), выполните:

git config core.symlinks true
git reset --hard

GitHub хранит symlinks как нормальные объекты Git (blob с режимом 120000) и вся информация передаётся корректно. Проблема возникает на вашей локальной машине при клонировании, в зависимости от вашей настройки core.symlinks.

Можно, но не рекомендуется. Лучше использовать переменные окружения, конфигурационные файлы или Git branches. Симлинки могут привести к путанице в многоплатформных командах.

Что означает режим 120000? #

В Git режимы доступа унаследованы из Unix:

  • 100644 — обычный файл
  • 100755 — исполняемый файл
  • 120000 — символическая ссылка (это специальный режим Git)
  • 160000 — Git submodule

Git хранит режим доступа (mode) вместе с объектом. Если режим 120000, то это symlink, даже если содержимое выглядит как текст пути.

Заключение #

Символические ссылки в Git — это мощный, но потенциально опасный инструмент для многоплатформных проектов. Git корректно хранит информацию о symlinks как объекты с режимом 120000, но проблемы возникают на клиентской стороне, особенно на Windows.

Основные моменты:

  • Git хранит путь ссылки, а не содержимое файла
  • На Windows нужна настройка core.symlinks=true и Developer Mode
  • Проверяйте git ls-files --stage чтобы убедиться, что symlinks сохранены правильно
  • Рассмотрите альтернативы (submodules, worktree) для критичных случаев
  • Документируйте требования к конфигурации в README вашего проекта

Если у вас в команде разные платформы, лучше обсудить, нужны ли вообще symlinks, или выбрать более надёжный подход.

По теме #