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

98

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

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

Альфредо Пальхарес
источник
2
Что ты пытаешься сделать и почему? Жесткая ссылка ничем не отличается от обычного файла. Если бы вам когда-нибудь пришлось вытащить новую версию из другого репозитория, она бы перезаписала ту, что у вас была - какой смысл связывать что-то вне репозитория?
Карл Норум,
2
Git распознает символические ссылки, указывающие на путь за пределами репозитория.
mipadi
Нет mipadi, единственный способ - это размахивать файлами в репо и символическими ссылками в их «реальном» месте
Альфредо Палхарес

Ответы:

89

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

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


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

Якуб Наребски
источник
4
Могут быть полезны символические ссылки на пути вне репозитория. Я использовал их в веб-приложениях, чтобы указать на базу данных или медиа-файлы, не отслеживаемые репозиторием. Таким образом, файл конфигурации веб-приложения может указывать на статический путь, но фактическое расположение этого пути может варьироваться в зависимости от локальной среды разработки и серверной среды.
mipadi
@mipadi: Кстати. Современный gitweb имеет особый случай для отображения символических ссылок, ведущих после нормализации вне репозитория.
Якуб Наребски
6
Да, символические ссылки вне репо в порядке. Я использовал их, чтобы указать на огромный каталог данных, который мне не нужен (или не хочу) версионировать. Обычно я использую относительные ссылки. Таким образом, в некоторых случаях репо и каталог данных должны располагаться рядом друг с другом в каком-то родительском каталоге. Вы можете делать удивительные трюки, используя символические ссылки на ../foo.
Адриан Ратнапала,
К сожалению, репозиторий Git для metastore (git: //git.hardeman.nu/metastore.git) больше не доступен.
Дерек Махар
1
github.com/danny0838/git-store-meta - альтернатива git-cache-meta .
Дерек Махар
22

Я выяснил, что с помощью хуков вы можете зафиксировать 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 также указывает на важную вещь: символические ссылки должны определяться относительно.

Niloct
источник
11
Таким образом, похоже, что каждый раз, когда вы добавляете жесткую ссылку в свое репо, вам также нужно вручную добавлять строку в свой сценарий ловушки после слияния. Было бы хорошо, если бы ваш хук перед фиксацией делал это полностью автоматическим - обнаруживая жесткие (и символические) ссылки в вашем коммите и записывая соответствующие строки в ваш файл после слияния. Git не будет хранить информацию об индексах в репозитории, он будет хранить ее биты в хуках! Но что за беспорядок, если связанный файл был отслежен в другом репозитории git ... будет ли изменение файла в одном месте плавно распространяться на другое репо? Perpetual сливается с круговой петлей push / pull?
hobs
Умный подход, но, к сожалению, Git не отслеживает жесткие ссылки, даже потенциально представляя их как копии в файловых системах, которые не поддерживают жесткие ссылки.
Дерек Махар
1
@hobs, извините, что ответил на 7 лет :) Вы правы. Если бы файл вне репозитория был связан с двумя разными репозиториями, я думаю, что изменение ссылки в одном репозитории просто не было бы замечено в другом.
Niloct,
8

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

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

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

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

VonC
источник
2

Google 'git preserve hard links' показывает, что 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 для каждой жесткой ссылки.

xce_git
источник
7
Вы должны реализовать какую-то маршрутизацию в своем веб-приложении. Жесткие ссылки - это странно.
Nowaker 02
5
Да, хотя бы используйте символические ссылки. :)
Андрес Риофрио
2
На самом деле это то, что я хочу, я не хочу, чтобы git сохранял жесткие ссылки. У меня есть каталог Jenkins с множеством каталогов рабочей области, и из-за многоотраслевых конвейеров существует много дублирования. Так что у меня есть работа , которая каждую ночь работает hardlink --ignore-timeна /var/lib/jenkins, чтобы вернуть часть дискового пространства. В течение дня некоторые файлы снова теряют жесткую связь после git pullили, mvn compileно это нормально, я ожидаю, что это произойдет. Если бы git сохранял жесткие ссылки, моя стратегия утилизации дискового пространства не сработала бы.
Амеди Ван Гассе