Как я могу заставить Git следовать символическим ссылкам?

Лучше всего будет сценарий оболочки, который заменяет символические ссылки на копии, или есть другой способ сказать Git следовать символическим ссылкам?

PS: я знаю, что это не очень безопасно, но я хочу сделать это только в нескольких конкретных случаях.

Ответ 1

ПРИМЕЧАНИЕ: этот совет устарел согласно комментарию со времен Git 1.6.1. Git обычно так себя ведет и больше не делает.


Git по умолчанию пытается хранить символические ссылки вместо того, чтобы следовать за ними (для компактности, и это вообще то, что люди хотят).

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

То есть:

  /foo/
  /foo/baz
  /bar/foo --> /foo
  /bar/foo/baz

при выполнении

 git add /bar/foo/baz

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

Ответ 2

Что я сделал, чтобы добавить файлы внутри символической ссылки в Git (я не использовал символическую ссылку, но):

sudo mount --bind SOURCEDIRECTORY TARGETDIRECTORY

Выполните эту команду в каталоге, управляемом Git. TARGETDIRECTORY должна быть создана до того, как SOURCEDIRECTORY смонтирована в нее.

Он отлично работает на Linux, но не на OS X! Этот трюк помог мне и с Subversion. Я использую его для включения файлов из учетной записи Dropbox, где веб-дизайнер делает свое дело.

Ответ 3

Почему бы не создать символические ссылки наоборот? То есть вместо того, чтобы ссылаться из репозитория Git на каталог приложения, просто сделайте ссылку наоборот.

Например, допустим, я настраиваю приложение, установленное в ~/application, для которого требуется файл конфигурации config.conf:

  • Я добавляю config.conf в мой репозиторий Git, например, в ~/repos/application/config.conf.
  • Затем я создаю символическую ссылку из ~/application, запустив ln -s ~/repos/application/config.conf.

Этот подход может не всегда работать, но он до сих пор работал хорошо для меня.

Ответ 4

Вместо этого используйте жесткие ссылки. Это отличается от мягкой (символической) ссылки. Все программы, включая git будут обрабатывать файл как обычный файл. Обратите внимание, что содержимое может быть изменено путем изменения источника или назначения.

В macOS (до 10.13 High Sierra)

Если у вас уже установлены git и Xcode, установите hardlink. Это микроскопический инструмент для создания жестких ссылок.

Чтобы создать жесткую ссылку, просто:

hln source destination

Обновление macOS High Sierra

Поддерживает ли Apple File System жесткие ссылки на каталоги?

Жесткие ссылки на каталоги не поддерживаются файловой системой Apple. Все жесткие ссылки на каталоги преобразуются в символические ссылки или псевдонимы при преобразовании из форматов тома HFS+ в APFS в macOS.

Из часто задаваемых вопросов APFS на developer.apple.com

Следуйте https://github.com/selkhateeb/hardlink/issues/31 для будущих альтернатив.

В Linux и других разновидностях Unix

Команда ln может создавать жесткие ссылки:

ln source destination

В Windows (Vista, 7, 8,…)

Кто-то предложил использовать mklink для создания соединения в Windows, но я не пробовал:

mklink /j "source" "destination"

Ответ 5

Это pre-commit hook, который заменяет символьные ссылки в индексе содержимым этих символических ссылок.

Поместите это в .git/hooks/pre-commit и сделайте его выполнимым:

#!/bin/sh
# (replace "find ." with "find ./<path>" below, to work with only specific paths)

# (these lines are really all one line, on multiple lines for clarity)
# ...find symlinks which do not dereference to directories...
find . -type l -exec test '!' -d {} ';' -print -exec sh -c \
# ...remove the symlink blob, and add the content diff, to the index/cache
    'git rm --cached "$1"; diff -au /dev/null "$1" | git apply --cached -p1 -' \
# ...and call out to "sh".
    "process_links_to_nondir" {} ';'

# the end

Примечания

Мы используем POSIX-совместимую функциональность как можно больше; однако diff -a не совместим с POSIX, возможно, между прочим.

В этом коде могут быть ошибки/ошибки, хотя они были несколько проверены.

Ответ 6

Я использовал для добавления файлов за символические ссылки в течение достаточно долгого времени. Раньше это работало просто отлично, без каких-либо специальных мер. Поскольку я обновился до Git 1.6.1, это больше не работает.

Вы можете переключиться на Git 1.6.0, чтобы сделать это. Я надеюсь, что в будущей версии Git будет флаг git-add позволяющий ему снова следовать символическим ссылкам.

Ответ 7

С Git 2.3.2+ (Q1 2015) есть еще один случай, когда Git больше не будет следовать символической ссылке: см. commit e0d201b с помощью Junio ​​C Hamano (gitster) (основной Git сопровождающий)

apply: не касайтесь файла за символической ссылкой

Поскольку Git отслеживает символические ссылки как символические ссылки, путь, который имеет символическую ссылку в своей ведущей части (например, path/to/dir/file, где path/to/dir является символической ссылкой в ​​другое место, будь то внутри или вне рабочего дерево) никогда не может появляться в патче, который действительно применим, если только тот же патч не удаляет символическую ссылку, чтобы разрешить создание каталога.

Обнаружение и отклонение такого патча.

Аналогично, когда ввод создает символическую ссылку path/to/dir, а затем создает файл path/to/dir/file, мы должны указывать его как ошибку, фактически не создавая символическую ссылку path/to/dir в файловой системе.

Вместо этого для любого патча на входе, который оставляет путь (т.е. без удаления) в результате, мы проверяем все ведущие пути к результирующему дереву, которое будет создавать патч, проверяя все патчи на входе, а затем целевой патч-приложение (либо индекс, либо рабочее дерево).

Таким образом, мы:

  • поймайте вред или ошибку, чтобы добавить символическую ссылку path/to/dir и файл path/to/dir/file в то же время,
  • при разрешении допустимого патча, который удаляет символический link path/to/dir, а затем добавляет файл path/to/dir/file.

Это означает, что в этом случае сообщение об ошибке не будет общим, например "%s: patch does not apply", но более конкретным:

affected file '%s' is beyond a symbolic link

Ответ 8

Я устал от того, что каждое решение здесь устарело или требует root, поэтому я создал решение на основе LD_PRELOAD (только для Linux).

Он подключается к внутренностям Git, переопределяя "это символическая ссылка?" функция, позволяющая обрабатывать символические ссылки как их содержимое. По умолчанию все ссылки на внешние репо являются встроенными; см. ссылку для деталей.

Ответ 9

Хммм, mount --bind не работает на Дарвине.

У кого-нибудь есть трюк, который делает?

[Редактировать]

Хорошо, я нашел ответ на Mac OS X, чтобы сделать жесткую ссылку. За исключением того, что этот API не предоставляется через ln, поэтому для этого вам нужно использовать собственную крошечную программу. Вот ссылка на эту программу:

Создание каталогов жестких ссылок в Mac OS X

Наслаждайтесь!

Ответ 10

Я использую Git 1.5.4.3, и он следует переданной символической ссылке, если он имеет косую черту. Например

# Adds the symlink itself
$ git add symlink

# Follows symlink and adds the denoted directory contents
$ git add symlink/

Ответ 11

На MacOS (у меня Mojave/10.14, git версия 2.7.1), используйте bindfs.

brew install bindfs

cd/path/to/git_controlled_dir

mkdir local_copy_dir

bindfs <source_dir> local_copy_dir

На это намекали другие комментарии, но в других ответах это явно не указано. Надеюсь, это сэкономит кому-то время.

Ответ 12

Преобразование из символических ссылок может быть полезным. Ссылка в папке Git вместо символической ссылки скриптом.