Я экспериментирую с приложением git, и прежде чем импортировать слишком много в приложение git, я бы хотел выяснить, как быстро удалить "присоединенный" репозиторий git, не теряя при этом содержимое моего вложенного файла и его структуру каталогов. Все "дополнительные" файлы на самом деле являются символическими ссылками на .git/annex/objects , например так:

$ git init
Initialised empty Git repository in /tmp/annex/.git/
$ git annex init
init  ok
(recording state in git...)
$ touch foo
$ git annex add foo
add foo ok
(recording state in git...)
$ git commit -a
[master (root-commit) 609a6df] Initial
1 file changed, 1 insertion(+)
create mode 120000 foo
$ ls -l foo
lrwxrwxrwx 1 me me 178 Jan  6 15:10 foo -> .git/annex/objects/pX/ZJ/SHA256E-s0--e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855/SHA256E-s0--e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

Поэтому простое удаление каталога .git также приведет к удалению всего содержимого файла!

Мне нужна команда, чтобы взять вложенный репозиторий, подобный приведенному выше, и создать новый каталог, содержащий только файлы (без ссылок): в данном случае только один файл foo . Для экономии места , пока не удалите исходный каталог приложения, я хочу файл foo быть жесткой ссылкой на .git/annex/objects/pX/ZJ/SHA256E-s0--e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855/SHA256E-s0--e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 (очевидно , в реалистичный пример, в хранилище будет много файлов).

Собственные команды git annex для "unannexing" (такие как git annex uninit) ограничены: в частности, они не очень хорошо поддерживают быстрое превращение репозитория git Annex в простой каталог файлов. Это мотивирует следующую проблему:

Как я могу скопировать каталог с файлами, не ссылаясь на символические ссылки, но жестко ссылаясь на ссылки на символические ссылки?

Я попробовал rsync --link-dest , вот так:

rsync -rLptgoD --safe-links --exclude='.git/' --link-dest=annex annex/ copy

Но это не приводит к жестким ссылкам, предположительно потому, что наличие символических ссылок означает, что rsync не знает, на какие файлы жестко ссылаться.

3 ответа3

0

Собственные команды git annex для "unannexing" (такие как git annex uninit) ограничены: в частности, они не очень хорошо поддерживают быстрое превращение репозитория git Annex в простой каталог файлов.

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

Но в репозитории git-annex формата v5 у вас есть еще один вариант: переключиться в "прямой" режим с помощью git annex direct . Это перемещает все файлы из хранилища объектов и предоставляет их напрямую, без ссылок. Эта команда преобразует все рабочее дерево одновременно.

Файлы по-прежнему отслеживаются git-annex; Прямой режим v5 просто меняет способ локальной проверки, поэтому он может быть самым быстрым методом, потому что он фактически не записывает новые данные в Git.

Поэтому, если вы хотите клонировать все дерево файлов, вы можете: 1) переключить репозиторий в "прямой" режим; 2) жестко связать все файлы с помощью rsync (исключая .git полностью); 3) при желании снова переключите исходный репозиторий в "косвенный" режим.

Кроме того, после перехода в прямой режим, просто удалите папку .git ...

0

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

cp -rLlp annex copy

Меня удивляет, что rsync не может воспроизвести это поведение, но, насколько я могу судить, не может.

Три проблемы с решением cp:

  1. Любые неопубликованные символические ссылки, которые либо не отслеживаются, либо регистрируются в git напрямую, будут заменены любыми файлами, на которые они указывают (но я подозреваю, что у меня их не будет). Прежде чем я понял, что могу просто использовать cp , я написал программу на Python, которая использует os.walk для копирования одного файла за раз: поскольку он знает о приложении git, он получает это правильно: он запускает rsync -ptgo --dirs для копирования каталогов и cp -Ll и cp -Pl для файлов, не входящих в каталог, и других файлов, не относящихся к каталогу, соответственно (программа немного запуталась с кодом утилиты и не была тщательно протестирована, поэтому я не буду публиковать ее здесь).

  2. Несмотря на то, что cp сохраняет разрешения, эти файлы могут быть "заблокированы", то есть они находятся в их символьном, недоступном для редактирования состоянии. По этой причине записываемые файлы будут недоступны для записи в копии. Использование git annex unlock . вместо cp вы избежите этой проблемы (это для git Annex Repo формата v6 / v7 - для более ранних форматов я считаю, что вы можете переключиться в прямой режим вместо разблокировки).

  3. В итоге вы получите копию каталога .git внутри copy каталога, содержащую больше жестко связанных копий тех же файлов. Опять же, это не занимает больше места из-за жестких ссылок, и вы можете просто sudo rm -rf .git чтобы избавиться от него.

0

Альтернативный ответ (запустите его в каталоге верхнего уровня хранилища):

git annex unlock .

Преимущества:

  • Разрешения сохранены (см. Мой другой ответ).
  • Неотслеженные и уже разблокированные символические ссылки сохраняются (опять же, см. Мой другой ответ).
  • Запуск strace показывает, что, по крайней мере, проблема медлительности, которую Джои Хесс замечает в комментарии здесь, поскольку она влияет на git annex uninit (что также относится к git annex unannex .), Не влияет на эту команду. Я не знаю, насколько это быстро для реалистичных репозиториев: я просто делаю упреждающее тестирование здесь.

Недостатки:

  • Если вы не используете файловую систему, такую как btrfs, для которой GNU cp поддерживает копирование при записи, git annex будет копировать каждый файл (в результате вы получите каждый вложенный файл в формате .git и как обычный файл в рабочей копии). , Я думаю, что это все равно не должно быть неоправданно медленным, но займет место на диске.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .