Git и жесткие ссылки

Учитывая, что Git не распознает символические ссылки, которые указывают за пределы репозитория, есть ли проблемы с использованием жестких ссылок?

Может ли Git сломать их? Не могли бы вы указать мне подробную информацию?


person Alfredo Palhares    schedule 16.09.2010    source источник
comment
Что вы пытаетесь сделать и почему? Жесткая ссылка ничем не отличается от обычного файла. Если бы вы когда-нибудь вытащили новую версию из другого репозитория, она перезаписала бы ту, которая у вас была — какой смысл ссылаться на что-то вне репо?   -  person Carl Norum    schedule 16.09.2010
comment
Git распознает символические ссылки, указывающие на путь за пределами репозитория.   -  person mipadi    schedule 17.09.2010
comment
Никакого мипади, единственный способ - махать файлами в репо и символическими ссылками в их реальном расположении   -  person Alfredo Palhares    schedule 17.09.2010
comment
В качестве примера использования у меня есть файлы на Google Диске, которые можно открыть в диаграмме.net, папка которого синхронизирована с моим компьютером, и было бы здорово, если бы эти файлы также были в моем репозитории git с проверками или изменения синхронизируются туда и обратно, но веб-приложение по-прежнему открывает их с Диска.   -  person endolith    schedule 24.07.2021


Ответы (4)


Объект «дерево», представляющий каталоги в Git, хранит имя файла и (подмножество) разрешений. Он не хранит номер инода (или другой идентификатор файла). Поэтому жесткие ссылки не могут быть представлены в git, по крайней мере без сторонних инструментов, таких как metastore или git-cache-meta ( и я не уверен, что это возможно даже с этими инструментами).

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


О символических ссылках, указывающих за пределы репозитория: у git нет проблем с ними, и он должен сохранять содержимое символических ссылок... но полезность таких ссылок для меня сомнительна, поскольку зависит, будут ли эти символические ссылки сломаны или нет. в макете файловой системы вне репозитория git и не под контролем git.

person Jakub Narębski    schedule 16.09.2010
comment
Симлинки на пути за пределами репозитория могут быть полезны. Я использовал их в веб-приложениях, чтобы указать на базу данных или мультимедийные файлы, не отслеживаемые репо. Таким образом, файл конфигурации веб-приложения может указывать на статический путь, но фактическое расположение этого пути может варьироваться в зависимости от локальной среды разработки и серверной среды. - person mipadi; 17.09.2010
comment
@mipadi: Кстати. Современный gitweb имеет особый случай для отображения симлинков, ведущих после нормализации вне репозитория. - person Jakub Narębski; 17.09.2010
comment
Да, символические ссылки вне репо в порядке. Я использовал их, чтобы указать на огромный каталог данных, который мне не нужен (или не нужен) для версии. Обычно я использую относительные ссылки. Так что в некоторых случаях репозиторий и каталог данных должны были располагаться рядом друг с другом в каком-то родительском каталоге. Вы можете делать удивительные трюки с символическими ссылками на ../foo. - person Adrian Ratnapala; 29.10.2011
comment
К сожалению, репозиторий Git для metastore (git://git.hardeman.nu/metastore.git) больше недоступен. - person Derek Mahar; 29.11.2017
comment
github.com/danny0838/git-store-meta является альтернативой git-кэш-мета. - person Derek Mahar; 29.11.2017

Выяснил, что с помощью хуков можно перехватывать событие git pull (когда есть что дергать...) записывая обработчик события скрипта в файл .git/hooks/post-merge.

Во-первых, вы должны chmod +x его.

Затем поместите в него команды ln, чтобы воссоздавать жесткие ссылки при каждом извлечении. Аккуратно ха!

Это работает, мне просто нужно было это для моего проекта, и ls -i показывает, что файлы были автоматически связаны после pull.


Мой пример .git/hooks/post-merge:

#!/bin/sh
ln -f $GIT_DIR/../apresentacao/apresentacao.pdf $GIT_DIR/../capa/apresentacao.pdf
ln -f $GIT_DIR/../avaliacoesMono/avaliacao_monografias_2011_Nilo.pdf $GIT_DIR/../capa/avaliacoes.pdf
ln -f $GIT_DIR/../posters/poster_Nilo_sci.pdf $GIT_DIR/../capa/poster.pdf
ln -f $GIT_DIR/../monografia/monografia_Nilo.pdf $GIT_DIR/../capa/monografia_Nilo.pdf

ВАЖНО: Как видите, путь к любому файлу в вашем репозитории должен начинаться с $GIT_DIR, затем добавьте частичный относительный путь к файлу.

Также важно: -f необходимо, потому что вы воссоздаете конечный файл.

РЕДАКТИРОВАТЬ

Современный клиент git, похоже, естественным образом поддерживает символические и жесткие ссылки внутри репозитория, даже при отправке в удаленное место и последующем клонировании из него. У меня никогда не было необходимости снова связываться за пределами репозитория git...

$ mkdir tmp
$ cd tmp
$ git --version
git version 2.24.3 (Apple Git-128)
$ git init .
Initialized empty Git repository in /Users/teixeira/tmp/.git/
$ mkdir x
$ cd x
$ echo 123 > original
$ cat original
123
$ cd ..
$ ln -s x/original symlink
$ cat symlink
123
$ ln x/original hardlink
$ cat hardlink
123
$ git add .
$ git commit -m 'Symlink and hardlink commit'
[master (root-commit) 8df3134] Symlink and hardlink commit
 3 files changed, 3 insertions(+)
 create mode 100644 hardlink
 create mode 120000 symlink
 create mode 100644 x/original

Клонирование из локального репозитория git

$ cd
$ git clone tmp/ teste_tmp
Cloning into 'teste_tmp'...
done.
$ cd teste_tmp/
$ ls
hardlink  symlink  x
$ cat symlink
123
$ cat hardlink
123

Клонирование из удаленного репозитория

$ cd ~/tmp
$ git remote add origin https://github.com/myUser/myRepo.git
$ git push origin master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (5/5), 361 bytes | 361.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To https://github.com/myUser/myRepo.git
 + 964dfce...8df3134 master -> master
$ cd ../
$ git clone https://github.com/myUser/myRepo.git
Cloning into 'myRepo'...
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 5 (delta 0), reused 5 (delta 0), pack-reused 0
Unpacking objects: 100% (5/5), done.
$ cd myRepo/
$ cat symlink
123
$ cat hardlink
123

https://github.com/mokacoding/symlinks также указывает на важную вещь: символические ссылки должны быть определены относительно .

person Niloct    schedule 17.02.2012
comment
Таким образом, похоже, что каждый раз, когда вы добавляете жесткую ссылку в свой репозиторий, вам также нужно вручную добавлять строку в свой скрипт ловушки после слияния. Было бы неплохо, если бы ваш хук перед коммитом сделал это полностью автоматическим — обнаружение жестких (и символических) ссылок в вашем коммите и запись соответствующих строк в ваш файл после слияния. Git не нужно будет хранить информацию об индексных дескрипторах в репозитории, он будет хранить ее фрагменты в хуках! Но какой беспорядок, если связанный файл отслеживался в другом репозитории git ... будет ли редактирование файла в одном месте плавно распространяться на другое репо? Вечные слияния с круговой петлей push/pull? - person hobs; 10.06.2013
comment
Умный подход, но жаль, что Git не отслеживает жесткие ссылки, даже потенциально представляя их как копии в файловых системах, которые не поддерживают жесткие ссылки. - person Derek Mahar; 16.11.2017
comment
@hobs извините за 7 лет, чтобы ответить :) Вы правы. Если бы файл вне репозитория был связан двумя разными репозиториями, я думаю, что изменение ссылки в одном репо просто не будет видно в другом. - person Niloct; 09.10.2020

Из этой проблемы msysgit

Точки соединения не являются символическими ссылками; поэтому символические ссылки просто не поддерживаются в msysGit.

Кроме того, Git никогда не отслеживал жесткие ссылки.

Проблема была ориентирована на Windows (поскольку речь идет о msysgit) и спорах о потенциальной поддержке символической ссылки.
Но комментарий о жесткой ссылке касается Git в целом.

person VonC    schedule 16.09.2010

Google «git сохраняет жесткие ссылки», и это показывает, что git не знает, как сохранить структуру жестких ссылок, AFAIK, возможно, по замыслу.

Мои веб-проекты используют жесткие ссылки следующим образом:

www/products/index.php
www/products/dell_latitude_id577/index.php #(hard linked to above)
www/products/dell_inspiron_id323/index.php #(hard linked again to above)

me@server:www/products$ ls -l index.php
-rwxr-xr-x 3 me me 1958 Aug 22 22:10 index.php*

Если я хотел внести изменения в index.php, я меняю его в одном месте, и жесткие ссылки (страницы сведений о продукте) указывают на изменения, за исключением того, что git не сохраняет эту связь во время клонирования и загрузки на другие компьютеры.

me@server:www$ git pull

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

person xce_git    schedule 23.08.2011
comment
Вы должны реализовать какую-то маршрутизацию в своем веб-приложении. Жесткие ссылки — это странно. - person Nowaker; 03.07.2012
comment
Да, хотя бы используйте симлинки. :) - person Andres Riofrio; 26.07.2012
comment
На самом деле это то, что я хочу, я не хочу, чтобы git сохранял жесткие ссылки. У меня есть каталог Jenkins с множеством каталогов рабочей области, и из-за многоветвевых конвейеров много дублирования. Итак, у меня есть ночная работа, которая запускается hardlink --ignore-time на /var/lib/jenkins, чтобы освободить место на диске. В течение дня некоторые файлы снова отключаются после git pull или mvn compile, но это нормально, я ожидаю, что это произойдет. Если бы git сохранял жесткие ссылки, моя стратегия утилизации дискового пространства не сработала бы. - person Amedee Van Gasse; 11.03.2019