Як я можу змусити Git слідувати посиланнями?


217

Моє найкраще буде сценарій оболонки, який замінює символьні посилання копіями, чи є інший спосіб сказати Git слідувати посиланнями?

PS: Я знаю, що це не дуже безпечно, але я хочу це зробити лише в кількох конкретних випадках.


5
Чи є недоліком використання жорстких посилань для чогось подібного?
Ehtesh Choudhury

12
У Windows 7 "mklink / d" (символічне посилання каталогу) не працює з git, але "mklink / j" (juction) працює чудово.
yoyo

1
Якщо файл автоматично генерується додатком, який регенерує його таким чином, що він видаляє файл і створює новий, то так, це проблема, яку жорсткі посилання на файли не вирішать.
Мартін Печка

1
@EhteshChoudhury ви не можете робити посилання на каталоги
Gaurav Kansal

Відповіді:


46

ПРИМІТКА: Ця порада застаріла за коментарем, оскільки Git 1.6.1. Гіт звик поводитись так, і більше не робить.


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

Однак мені випадково вдалося змусити його додати файли за межами симпосилання, коли символьне посилання є каталогом.

Тобто:

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

роблячи

 git add /bar/foo/baz

виявилося, що це спрацювало, коли я спробував це. Така поведінка в той час для мене була небажаною, тому я не можу дати тобі інформацію поза цим.


72
Коміти 725b06050a083474e240a2436121e0a80bb9f175 та 806d13b1ccdbdde4bbdfb96902791c4b7ed125f6 внесли зміни, які зупиняли додавання файлів за межами пов'язаних каталогів, тому це не працюватиме у версіях git з 1.6.1
Марк Longair

1
$ git add src / main / path / ConvertSymlinkToDir fatal: 'src / main / path / ConvertSymlinkToDir' знаходиться поза символічним посиланням
користувач1767316

2
@ user1767316 прочитав все це та коментарі. Раніше це працювало, це більше не робить. Програмне забезпечення змінюється, але прийняті відповіді щодо переповнення стека не відповідають цим. Я уточнив, це вже не працює. Подивіться на іншу відповідь.
Кент Фредрік

так @KentFrederic, але вказуючи точне повідомлення про помилку, повернувся довідковий користувач у пошуку вирішення проблеми. Спробував скасувати протокол, але заблоковано вибачте. З одного боку, ваша відповідь правильна з урахуванням попередження, з іншого боку, слід віддавати перевагу відповідям, які працюють зараз, а не раніше
користувач1767316

144

Що я зробив, щоб додати файли в симпосилання в Git (я не використовував, але):

sudo mount --bind SOURCEDIRECTORY TARGETDIRECTORY

Виконайте цю команду в каталогу, керованому Git. TARGETDIRECTORYмає бути створено до SOURCEDIRECTORYвстановлення в нього.

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


8
Було б дуже приємно підходити, якщо судо не було потрібно.
MestreLion

13
Щоб скасувати цю прив'язку, використовуйте umount [mydir]. (+1 для вашої чудової поради, @ user252400)
JellicleCat

10
Це працює лише під час сеансу. Який найкращий спосіб зробити його "вічним"?
Adobe

17
@Adobe: помістіть його в / etc / fstab, як так: / sourcedir / targetdir нікого не пов’язують
Олександр Сад

8
sshfs можуть домогтися такого виду, не вимагаючи тут судо.
PypeBros

75

Чому б не створити посилання навпаки? Значить замість того, щоб посилатися з репозиторію Git до каталогу додатків, просто зв’яжіть навпаки.

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

  • Я додаю config.confдо свого сховища Git, наприклад, в ~/repos/application/config.conf.
  • Потім я створюю посилання з символу ~/application, запустивши ln -s ~/repos/application/config.conf.

Цей підхід може не завжди спрацювати, але для мене він працював добре.


5
Здається, це єдиний спосіб, і це не так вже й погано ... я думаю, що ваш - це досить елегантний підхід. git відстежує вміст, а не файли. Тож зберігати весь вміст разом і посилатися звідти на інші місця має сенс
MestreLion

12
У моєму випадку я хотів посилання з одного git repo на інший, тому я можу редагувати файли в будь-якому місці та повертатись до відповідних віддалених програм. У Windows 7 перехід ("mklink / j") зробив свою справу.
yoyo

3
звичайно. іноді відповідь просто така проста.
BBW Перед Windows

що робити, якщо ви хочете отримати джерело та місце призначення? (тому що обидва належать до різних кодів, які ви хочете мати у різних сховищах)
DrGC,

1
Не відповідає на запитання :( Я хотів, щоб частина мого репозиторію синхронізувалася в iCloud. На жаль, iCloud не дотримується символьних посилань, тому я подумав, що я можу змусити git слідувати посиланнями і зберігати оригінальні файли в iCloud. Виявляється, ніхто не слідкує символьні посилання: \
Джеррі Грін

49

Використовуйте натомість жорсткі посилання. Це відрізняється від м'якого (символічного) зв’язку. Усі програми, в тому числі gitбудуть розглядати файл як звичайний файл. Зверніть увагу , що вміст може бути змінена шляхом зміни або джерела або призначення.

На macOS (до 10.13 Висока Сьєрра)

Якщо у вас вже встановлено git та Xcode, встановіть жорстке посилання . Це мікроскопічний інструмент для створення жорстких зв’язків .

Щоб створити жорстке посилання, просто:

hln source destination

оновлення високої Sierra macOS

Чи підтримує каталог файлової системи Apple жорсткі посилання?

Файлова система Apple не підтримує жорсткі посилання каталогів. Усі жорсткі посилання каталогів перетворюються на символічні посилання або псевдоніми, коли ви перетворюєте з форматів томів HFS + в APFS на macOS.

З FAQ щодо APFS на developer.apple.com

Слідкуйте за https://github.com/selkhateeb/hardlink/isissue/31, щоб отримати майбутні варіанти.

На Linux та інших ароматах Unix

lnКоманда може зробити жорсткі посилання:

ln source destination

У Windows (Vista, 7, 8,…)

Хтось запропонував використовувати mklink для створення переходу в Windows, але я не пробував цього:

mklink /j "source" "destination"

7
Лише зауваження: це в основному те, що я шукав, але потім я дізнався, що в Linux жорстке посилання, на жаль, не може перетнути межі файлової системи (що є моїм випадком використання).
sdaau

26
Ви не можете посилатися на каталоги, чи не так?
Нанна

1
ln source destinationпрацює і в OS X. Випробуваний на Ель-Капітан.
Махді Дібайе

7
@Nanne немає, але ви можете зробити: cp -al source destination. `-l 'означає файли жорсткого посилання замість копіювання.
Паоло

6
На жаль, ви не можете мати жорсткі посилання каталогів або через межі файлової системи. Це робить це рішення вдвічі непрацездатним для мене.
Конрад Рудольф

25

Це гачок, що попередньо здійснює заміну, яка замінює крапки символьної посилання в індексі із вмістом цих символьних посилань.

Помістіть це .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, можливо, серед іншого.

У цьому коді можуть бути деякі помилки / помилки, хоча він був дещо перевірений.


4
Чудово бачити спробу насправді відповісти на питання щодо файлів, а не каталогів. Тим НЕ менше, зверніть увагу , що вище , буде по- , як і раніше показувати typechangeв git statusпротягом файлів , які на насправді символічні посилання , хоча мерзотник тепер всі вони не є.
Девід Фрейзер

1
Дякую за це; просто хотів знати, що таке process_links_to_nondir?
sdaau

@sdaau Це ім'я /, argv[0]яке використовується як команда-ім'я для shпроцесу. (Узяв мене трохи, щоб це зрозуміти, оскільки я не пам’ятав, що це було також ☺😃)
Аббафей

3
@Abbafei Чи можете ви змінити сценарій, щоб він працював на Ubuntu (14.04)? Це показує find: missing argument to -exec'. Може бути поетапне виконання команд, замість того, щоб констатувати та об'єднувати все в один рядок.
Хуршид Алам

1
@KhurshidAlam Для мене це працювало над видаленням коментованих рядків між командними рядками. Однак гак працює не так, як очікувалося (мені typechangeздається, як @DavidFraser, але пов'язаний файл, здається, більше не
ставиться

14

Увімкнено MacOS(у мене є Mojave / 10.14, gitверсія 2.7.1), використовувати bindfs.

brew install bindfs

cd /path/to/git_controlled_dir

mkdir local_copy_dir

bindfs </full/path/to/source_dir> </full/path/to/local_copy_dir>

На це натякали інші коментарі, але в інших відповідях це не було чітко. Сподіваємось, це економить когось деякий час.


здається чудовим для команд, які працюють на Mac OS, я думаю, що жорсткі посилання, викладені нижче, повинні працювати для Windows та Linux.
Девін Г Род

Це було корисно, і я думаю, що найкраще рішення для корисної, але відсутньої можливості в MacOS. Однак зауважте, що я отримував Failed to resolve... No such file or directoryпомилки, якщо я не використовував повні імена шляху за допомогою bindfsкоманди.
електромагніт

Дякуємо @electromaggot. Додано роз'яснення, що необхідні повні шляхи
ійосеф

1
Чудово справляється з макосом Каталіною!
Джеррі Грін

13

Я часто додавав файли поза символьними посиланнями вже досить давно. Це працювало просто чудово, без особливих домовленостей. Оскільки я оновив до Git 1.6.1, це більше не працює.

Можливо, ви зможете перейти на Git 1.6.0, щоб зробити цю роботу. Я сподіваюся, що в майбутній версії Git з'явиться прапор, який git-addдозволить йому знову переходити до посилань.


12

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

Він вписується у внутрішність Гіта, замінюючи "це симпосилання?" функція, що дозволяє розглядати символьні посилання як їхній вміст. За замовчуванням всі посилання на репо-репо є вкладеними; Детальніше дивіться за посиланням.


Дуже креативне рішення за допомогою LD_PRELOADперекриття функцій бібліотеки!
iBug

Так, але це слід було б детально розробити тут. Ви можете це зробити?
Пітер Мортенсен

Не впевнений, скільки допоможе розробка; якщо я не копіюю весь вихідний код, ця відповідь завжди покладається на це посилання, де також можна знайти readme. Але так, я здогадуюсь, я міг би відтворити важливі частини readme.
Алькаро

Це не компілюється в OS X (Mojave 10.14.2). Отримайте чотири помилки, нарікаючи на 'strchrnul' (ви мали на увазі «strchr»?) Та одну про «__xstat64» (ви мали на увазі «__lxstat64»?). Нарешті, я отримую помилку "членського члена в неповному типі" dirent64 "". Трапляється незалежно, якщо я використовую "make", "make OPT = 1" або "sh install.sh".
Ерік Веланд

@ErikVeland Я трохи спробував, але, схоже, OSX не підтримує LD_PRELOAD, ані щось подібне. Різні документи пропонують різні речі, але вони всі кілька років, і Apple любить зневажувати речі; Я не міг змусити жодного з них працювати. Вибачте.
Alcaro

6

Що стосується Git 2.3.2+ (Q1 2015), є ще один випадок, коли Git більше не перейде за символьним посиланням: див. Виконувати 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

Гмм, mount --bindздається, не працює на Дарвіна.

У когось є хитрість, яка це робить?

[відредаговано]

Гаразд, я знайшов відповідь на Mac OS X - це зробити жорстке посилання. За винятком того, що цей API не відкритий через ln, тому для цього вам потрібно використовувати власну крихітну програму. Ось посилання на цю програму:

Створення жорстких посилань на каталог у Mac OS X

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


1
Якщо каталог призначення цього жорсткого посилання є підкаталогом іншого git repo, це був би хаос. Виконання git-операцій на жорсткому посиланні буде застосовано до цього іншого git repo. Просто перевірте, що ви робите.
yegle

4
Це можна зробити за допомогою code.google.com/p/bindfs, який можна встановити за допомогою порту.
Кіт Сунде

0

Я використовую Git 1.5.4.3, і він слідкує за пропущеним символьним посиланням, якщо він має кінцеву косу рису. Напр

# Adds the symlink itself
$ git add symlink

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

5
принаймні, на OSX це призводить доfatal: 'src/' is beyond a symbolic link
Dan Rosenstark

2
Як пояснив @Mark Longair, це працювало лише до git 1.6.1
MestreLion

це було моїм питанням, спасибі!
Майк Q

0

Перетворення із символьних посилань може бути корисним. Посилання в папку Git замість символьної посилання сценарієм .


хочете додати більше деталей у відповідь?
Девін Г Род
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.