Как я могу заставить Git следовать символическим ссылкам? - PullRequest
183 голосов
/ 17 сентября 2008

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

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

Ответы [ 12 ]

128 голосов
/ 17 января 2010

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

sudo mount --bind SOURCEDIRECTORY TARGETDIRECTORY

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

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

67 голосов
/ 26 апреля 2011

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

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

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

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

43 голосов
/ 18 июня 2014

Вместо этого используйте жесткие ссылки. Это отличается от мягкой (символической) ссылки. Все программы, включая 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"
39 голосов
/ 17 сентября 2008

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


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

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

т.е:.

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

делая

 git add /bar/foo/baz

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

19 голосов
/ 09 сентября 2013

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

Поместите это в .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, возможно, среди прочего.

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

12 голосов
/ 01 января 2009

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

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

7 голосов
/ 06 марта 2018

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

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

6 голосов
/ 04 марта 2015

В Git 2.3.2+ (1-й квартал 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
4 голосов
/ 19 февраля 2010

Хммм, mount --bind не похоже на Дарвина.

У кого-нибудь есть трюк?

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

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

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

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

3 голосов
/ 10 января 2019

Вкл. 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

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

...