Как Git обрабатывает символические ссылки?

1369

Если у меня есть файл или каталог, который является символической ссылкой, и я помещаю его в репозиторий Git, что с ним происходит?

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

Что он делает, когда я удаляю файл, на который он ссылается? Это просто фиксирует висячую ссылку?

  • 15
    .gitignore видит символическую ссылку как файл, а не папку.
  • 5
    Ну, очевидно, есть больше вопроса, чем этот ответ предполагает. Например, мне интересно следующее: если я создам ссылку sym в своем репозитории на какой-то большой файл в этом репозитории, перенесу изменения, а затем перенесу эти изменения на другой компьютер, что произойдет? Будет ли большой файл храниться как большой файл в обоих местах или будет сохранена ссылка sym, чтобы на новом компьютере файл ссылки указывал на исходный большой файл?
Показать ещё 5 комментариев
Теги:
version-control
symlink

3 ответа

1203
Лучший ответ

Git просто хранит содержимое ссылки (т.е. Путь к объекту файловой системы, на которую он ссылается) в "blob", как это делается для обычного файла. Затем он сохраняет имя, режим и тип (включая тот факт, что это символическая ссылка) в объекте дерева, который представляет его содержащий каталог.

Когда вы извлекаете дерево, содержащее ссылку, он восстанавливает объект как символическую ссылку независимо от того, существует целевой объект файловой системы или нет.

Если вы удалите файл, на который ссылается символическая ссылка, он никак не повлияет на управляемую Git символическую ссылку. У вас будет свисающая ссылка. Пользователь может удалить или изменить ссылку, чтобы указать на что-то действительное, если это необходимо.

  • 295
    КСТАТИ. Если вы находитесь в файловой системе, такой как FAT, которая не поддерживает символические ссылки, и ваш репозиторий использует их, вы можете установить для переменной конфигурации core.symlinks значение false, и символические ссылки будут извлечены в виде небольших текстовых файлов, содержащих текст ссылки.
  • 13
    @ JakubNarębski Я видел это раньше. В нашем репо был текстовый файл с одной строкой, путь к библиотеке, которую мы используем. Не могу понять, какова была цель этого. Теперь я знаю, что случилось.
Показать ещё 3 комментария
180

TL; DR: данные, на которые ссылается символическая ссылка, не сохраняются в хранилище.


Вы можете узнать, что Git делает с файлом, увидев, что он делает, когда вы добавляете его в индекс. Индекс похож на предварительную фиксацию. После фиксации индекса вы можете использовать git checkout чтобы вернуть все, что было в индексе, обратно в рабочий каталог. Итак, что делает Git, когда вы добавляете в индекс символическую ссылку?

Чтобы выяснить это, сначала сделайте символическую ссылку:

$ ln -s /path/referenced/by/symlink symlink

Git еще не знает об этом файле. git ls-files позволяет вам проверить ваш индекс (-s stat -like):

$ git ls-files -s ./symlink
[nothing]

Теперь добавьте содержимое символической ссылки в хранилище объектов Git, добавив его в индекс. Когда вы добавляете файл в индекс, Git сохраняет его содержимое в хранилище объектов Git.

$ git add ./symlink

Итак, что было добавлено?

$ git ls-files -s ./symlink
120000 1596f9db1b9610f238b78dd168ae33faa2dec15c 0       symlink

Хеш является ссылкой на упакованный объект, который был создан в хранилище объектов Git. Вы можете проверить этот объект, если загляните в .git/objects/15/96f9db1b9610f238b78dd168ae33faa2dec15c в корне вашего хранилища. Этот файл - то, что хранит Git и что вы можете извлечь из своего хранилища, когда добавляете и фиксируете символическую ссылку. Если вы изучите этот файл, вы увидите, что он очень маленький. Он не хранит содержимое связанного файла.

(Обратите внимание, что 120000 - это файловый режим, указанный в выводе ls-files. Это будет что-то вроде 100644 для обычного файла.)

Но что Git делает с этим объектом, когда вы извлекаете его из хранилища и в свою файловую систему? Это зависит от конфигурации core.symlinks. Из man git-config:

core.symlinks

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

Таким образом, имея символическую ссылку в хранилище, при извлечении вы получаете либо текстовый файл со ссылкой на полный путь к файловой системе, либо правильную символическую ссылку, в зависимости от значения конфигурации core.symlinks.

В любом случае данные, на которые ссылается символическая ссылка, не сохраняются в хранилище.

150

Примечание "Редактора": эта публикация может содержать устаревшую информацию. Пожалуйста, смотрите комментарии и этот вопрос относительно изменений в Git начиная с 1.6.1.

Символьные каталоги:

Важно отметить, что происходит, когда существует каталог, который является мягкой ссылкой. Любое Git pull с обновлением удаляет ссылку и делает ее нормальной директорией. Это то, чему я научился трудным путем. Некоторые идеи здесь и здесь.

пример

До

 ls -l
 lrwxrwxrwx 1 admin adm   29 Sep 30 15:28 src/somedir -> /mnt/somedir

git add/commit/push

It remains the same

После git pull и некоторых обновлений найдено

 drwxrwsr-x 2 admin adm 4096 Oct  2 05:54 src/somedir
  • 4
    Стоит отметить, что эти предупреждения о каталогах с символическими ссылками не относятся к версионным символическим ссылкам. Основным вопросом, о котором идет речь, было то, что люди символически связывали некоторые или все рабочее дерево по другому пути (скажем, в другой раздел с большим дисковым пространством) и ожидали, что git проверит код через существующую символическую ссылку. То есть, если у вас есть проект, который содержит версионные символические ссылки на файлы или каталоги, нормальное поведение symlink-as-blob сохранит символические ссылки, правильно изменит версию этих сим-ссылок и в противном случае будет работать так, как ожидается.
  • 0
    Вышеупомянутое поведение протестировано с git 1.6.5.6; но я сильно подозреваю, что версионное поведение в git уже довольно давно.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню