Сделать «git export» (например, «svn export»)?

Мне было интересно, есть ли хорошее решение "git export", которое создает копию дерева без каталога репозитория .git. Я знаю как минимум три метода:

  1. git clone с последующим удалением каталога репозитория .git.
  2. git checkout-index намекает на эту функциональность, но начинается со слов «Просто прочтите желаемое дерево в индекс ...», что я не совсем уверен, как это сделать.
  3. git-export - это сторонний сценарий, который, по сути, переводит git clone во временное местоположение, а затем rsync --exclude='.git' в конечный пункт назначения.

Ни одно из этих решений не кажется мне удовлетворительным. Ближайшим к svn export может быть вариант 1, потому что оба требуют, чтобы целевой каталог был сначала пустым. Но вариант 2 кажется даже лучше, если предположить, что я могу понять, что значит читать дерево в индексе.

@rnrTom: См. ответ Сомова. (в tar-архиве ничего "сжатого" нет).

etarion 23.05.2012 19:59

@mrTom git archive --format zip --output "output.zip" master -0 предоставит вам несжатый архив (-0 - флаг для несжатого). git-scm.com/docs/git-archive.

user456814 05.09.2012 22:47

Я согласен с @mrTom и не думаю, что сжатый или несжатый архив является главной проблемой. С SVN я могу export подкаталог 250 КБ прямо из удаленного репозитория (который в противном случае мог бы иметь размер 200 МБ, без учета ревизий) - и я попаду в сеть только для передачи загрузки 250 КБ (или около того). С git, archive должен быть включен на сервере (поэтому я не могу его попробовать) - clone --depth 1 с сервера все еще может получить репо размером, скажем, 25 МБ, тогда как подпапка .git занимает 15 МБ. Поэтому я все равно отвечу «нет».

sdaau 28.01.2013 18:59

@mrTom ответ на самом деле ДА См. ответ OP - команда git checkout-index

nocache 20.11.2013 12:55

Вот хороший и простой способ: git archive -o latest.zip HEAD

Evgeni Sergeev 23.07.2018 21:43
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2 405
5
665 106
31
Перейти к ответу Данный вопрос помечен как решенный

Ответы 31

Из Руководство по Git:

Использование git-checkout-index для «экспорта всего дерева»

Возможность префикса в основном упрощает использование git-checkout-index в качестве функции «экспорта в виде дерева». Просто прочтите нужное дерево в индексе и выполните:

$ git checkout-index --prefix=git-export-dir/ -a

Думаю, путаница заключается в словосочетании «прочитать желаемое дерево в индексе».

davetron5000 02.10.2008 06:30

Если вы хотите экспортировать каталог foo в панели веток, тогда это будет git read-tree bar:foo, а затем git checkout-index --prefix=export_dir/ -a, после этого, возможно, вам следует сделать git update-index master

Pascal Rosin 08.06.2012 21:10

@JohnWeldon Требуется ли сначала клонировать репо? Если так, то я бы не принял это, так как весь смысл "svn export" подкаталога состоит в том, чтобы напрямую получить копию этого подкаталога; Если у кого-то есть репозиторий Git размером 1 ГБ, а все, что мне нужно, это подкаталог размером 10 КБ, безумие требовать от меня клонирования всего этого.

Jason S 31.05.2017 19:44

Также я бы повторил @ davetron5000 с комментарием «прочтите желаемое дерево в индекс», который я не понимаю, что это значит.

Jason S 31.05.2017 19:44

Выяснил, что означает вариант 2. Из репозитория вы можете:

git checkout-index -a -f --prefix=/destination/path/

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

Поскольку в нормальной ситуации индекс содержит содержимое репозитория, нет ничего особенного, чтобы «прочитать желаемое дерево в индекс». Это уже есть.

Флаг -a требуется для проверки всех файлов в индексе (я не уверен, что значит опустить этот флаг в этой ситуации, поскольку он не делает того, что я хочу). Флаг -f принудительно перезаписывает любые существующие файлы в выводе, чего эта команда обычно не делает.

Это похоже на то, что я искал.

... и НЕ ЗАБУДЬТЕ СЛЭШ В КОНЦЕ, иначе у вас не будет желаемого эффекта;)

conny 09.04.2009 00:48

Разве индекс не является просто названием «промежуточной» области? Как так получилось, что дерево уже там? Я думал, что вы можете добавлять в него только вручную с помощью git add

hasen 31.08.2009 10:12

Команда git add изменяет содержимое индекса, поэтому все, что git status показывает как «должно быть зафиксировано», является различия между HEAD и содержимым индекса.

Greg Hewgill 31.08.2009 10:30

похоже, что это эквивалент git archive HEAD

takeshin 06.05.2010 00:33

@conny: прочитайте ваш комментарий, забыл об этом и запустил команду без косой черты. совет: следуйте совету Конни -.-

Znarkus 24.06.2010 20:55

Я тоже люблю убирать другие [хлам] [1]. Например, я также удаляю файл .gitignore, поскольку он, вероятно, не будет иметь отношения к каким-либо будущим разработчикам программного обеспечения. [1]: en.wikipedia.org/wiki/Cruft

mkelley33 20.02.2011 17:59

И, по-видимому, я не правильно понял синтаксис в моем комментарии выше для ссылки на термин "крутой" в Википедии. Извиняюсь!

mkelley33 20.02.2011 18:07

+1 к совету Конни. Кроме того, не пытайтесь создать '~ / dest /', так как это создаст каталог с именем '~' в вашем рабочем каталоге, а не то, что вы действительно хотели. Угадайте, что происходит, когда вы бездумно набираете rm -rf ~

Kyle Heironimus 18.04.2011 20:38

Причина использования флага '-a' описана на странице руководства для git-checkout-index. Он утверждает, что git-checkout-index часто принимает аргументы, а иногда отсутствие аргументов означает, что ничего не делать. Если вы запустите man git-checkout-index и выполните поиск по запросу «Интуитивность здесь не цель». вы увидите то, о чем я говорю.

Daniel Kessler 26.07.2012 00:11

Этот метод не принимает тег или любую другую ссылку на ревизию. По общему признанию, необходимость указывать тег была более важной для CVS, поскольку кто-то другой мог изменить удаленный репозиторий. Еще одно предостережение: вышеуказанный метод будет экспортировать файлы из index. То есть, если что-то планируется зафиксировать, это будет экспортировано.

proski 11.06.2015 03:54

@KyleHeironimus - ваше предупреждение об использовании '~ / dest / `истинно, если вы используете кавычки вокруг вашего префиксного пути, которые говорят оболочке не выполнять раскрытие тильды. В вашем рабочем каталоге будет создан каталог с именем ~ (не '~'!). В этом отношении в git checkout-index нет ничего особенного: то же самое и с mkdir '~/dest' (не делай этого!). Еще одна веская причина избегать имен файлов, которые нужно цитировать (например, в которых есть пробел) :-)

Matt Wallis 02.09.2015 12:18

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

Rich 31.03.2016 03:03

@MattWallis: использование этого подхода в Windows с «Git Bash», включенным в клиент, доступный на git-scm.com, расширение тильды не работает, хотя bash использует тильду как часть приглашения. Это не связано с использованием кавычек в имени пути. в Rich: В этом же самом сценарии любая выходная папка создавалась по запросу.

Thomas Urban 06.04.2016 15:01

@takeshin Это не совсем то же самое, что git archive HEAD: git checkout-index ... копирует все файлы из индекса, а archive архивирует файлы из локального репозитория. Они случайно сделают то же самое, если индекс пуст.

Alberto 02.06.2016 11:34

Будет ли git checkout-index пытаться повторно использовать существующие файлы аналогично тому, как это делает обычный checkout (например, избегать копирования файлов с ожидаемой меткой времени и размером)?

ceztko 06.12.2019 01:54

На самом деле я бы предпочел иметь цель расстояние в вашем Makefile (или другой системе сборки), которая экспортирует распространяемый архив вашего кода (.tar.bz2, .zip, .jar или любой другой подходящий). Если вы используете GNU autotools или системы MakeMaker Perl, я думаю, что это существует для вас автоматически. Если нет, настоятельно рекомендую добавить его.

ETA (06.09.2012): Ого, резкие отрицательные голоса. Я по-прежнему считаю, что лучше создавать свои дистрибутивы с помощью инструментов сборки, а не инструмента управления исходным кодом. Я верю в создание артефактов с помощью инструментов сборки. В моей нынешней работе наш основной продукт построен на мишени-муравьях. Мы находимся в самом разгаре переключения систем управления исходным кодом, и наличие этой цели-муравья означает меньше хлопот при миграции.

Я имел в виду не проект кода; это больше похоже на проект веб-сайта.

Greg Hewgill 02.10.2008 21:53

Не отвечает на вопрос.

Andrew Ferrier 18.09.2012 21:07

Да, такой ответ может не удовлетворить потребности всех, но отрицательные голоса очень странны. Это является полностью верный ответ и действительно во многих сценариях единственно правильный ответ. Это очень убедительно свидетельствует о том, что думать об этой проблеме как о «проблеме с инструментом vc» часто ведет совершенно неверный путь.

snogglethorpe 10.09.2013 03:37
Ответ принят как подходящий

Вероятно, самый простой способ добиться этого - использовать git archive. Если вам действительно нужно только развернутое дерево, вы можете сделать что-то вроде этого.

git archive master | tar -x -C /somewhere/else

В большинстве случаев, когда мне нужно «экспортировать» что-то из git, мне в любом случае нужен сжатый архив, поэтому я делаю что-то вроде этого.

git archive master | bzip2 >source-tree.tar.bz2

ZIP-архив:

git archive --format zip --output /full/path/to/zipfile.zip master 

git help archive для более подробной информации, он довольно гибкий.


Имейте в виду, что даже если архив не будет содержать каталог .git, он, тем не менее, будет содержать другие скрытые файлы, специфичные для git, такие как .gitignore, .gitattributes и т. д. Если вы не хотите, чтобы они были в архиве, убедитесь, что вы используйте атрибут export-ignore в файле .gitattributes и зафиксируйте его перед созданием архива. Подробнее...


Примечание. Если вас интересует экспорт индекса, используйте следующую команду:

git checkout-index -a -f --prefix=/destination/path/

(Подробнее см. Ответ Грега)

ZIP-архив: git archive --format zip --output /full/path master

Vadim 23.04.2010 13:19

Имейте в виду, что архив не будет содержать каталог .git, но будет содержать другие скрытые файлы, специфичные для git, такие как .gitignore, .gitattributes и т. д. Поэтому, если они вам не нужны, убедитесь, что вы используете атрибут export-ignore в файл .gitattributes и зафиксируйте его перед созданием архива. См. Feed.cloud.geek.nz/2010/02/…

mj1531 06.07.2010 18:55

Чтобы продолжить примечание Streams: вы можете добавить строку '--prefix = something /' в команду для управления именем каталога, который будет упакован внутри zip. Например, если вы используете git archive --format zip --output /path/to/file.zip --prefix=newdir/ master, вывод будет называться «file.zip», но когда вы распаковываете его, каталог верхнего уровня будет «newdir». (Если вы опустите атрибут --prefix, каталог верхнего уровня будет 'file'.)

Alan W. Smith 30.09.2010 07:31

и в продолжение примечания @ anotherAlan: префикс - также работает для архивов tar - и в любом случае обязательно включите завершающий /, если вы ожидаете каталог!

lindes 06.02.2011 12:27

Самый простой способ: git archive -o latest.zip HEAD. Он создает Zip-архив, содержащий содержимое последней фиксации в текущей ветке. Обратите внимание, что выходной формат определяется расширением выходного файла.

nacho4d 01.06.2011 14:47

Он не поддерживает подмодули git :(

umpirsky 21.07.2011 11:59

Вы можете получить tar, выполнив "--format = tar --output = foo.tar", вам не нужно передавать его через tar. Фактически, согласно архиву справки git, формат tar используется по умолчанию, поэтому вам даже не нужно его указывать.

Liam 30.10.2011 19:43

@Liam: Да, формат по умолчанию - tar, поэтому вы может перенаправляете вывод прямо на tar -x.

CB Bailey 31.10.2011 12:11

Для отдельных файлов может быть полезно перенаправить на стандартный вывод. например: git archive master some/file/name | tar -xO (заглавная O, а не ноль).

phils 07.02.2012 08:36

@ Чарльз Бейли: Интересно, почему вы выбрали это решение вместо клонирования + удаления git-папок. Есть ли у этого обратная сторона?

Raffael 23.03.2012 17:22

@ Яaffael1984: одна из причин сделать это с помощью метода clone & remove git-folder - это если вы хотите экспортировать репозиторий git в / поверх существующего каталога. git clone не устраивает клонирование в непустой каталог.

Michael Burr 05.05.2012 00:44

Хотя это действительно работает и очень просто, есть большой недостаток, с которым я только что столкнулся. Это экспортирует все файлы из дерева и установит их метку времени на время последней фиксации git, вместо того, чтобы каждый файл сохранял свою собственную метку времени, она будет перезаписана меткой последнего зафиксированного файла. Затем это вызовет проблему для чего-то вроде rsync, если вы отправляете свои файлы на удаленный сервер, все файлы будут перенесены.

jmoz 03.07.2012 04:30

@jmoz: Это не лучший вариант использования git archive. Если вас интересуют временные метки файлов в рабочем дереве, то более подходящим вариантом будет простой tar, cp -pr или локальный rsync.

CB Bailey 03.07.2012 09:35

git archive --format zip --output "output.zip" master -0 предоставит вам несжатый архив (-0 - флаг для несжатого). git-scm.com/docs/git-archive

user456814 27.08.2012 20:50

Хорошо, я добавил опцию zip в качестве псевдонима в ~/.gitconfig[alias] zip = archive --format zip --output. Использование: git zip ~/Desktop/app.zip master

schmunk 03.04.2013 21:33

Можно ли что-то подобное сделать? git archive -o ../{$GIT_DIR}.zip HEAD Я хочу динамически сгенерировать имя zip-файла на основе имени репо или имени каталога.

Evan Mattson 19.02.2014 18:36

Параметр --remote позволяет создавать архив без предварительного клонирования.

onionjake 12.08.2014 19:27

Есть ли способ заархивировать только одну папку проекта?

Jcao02 13.10.2014 17:36

Обратите внимание, что .tar = без сжатия (меньше накладных расходов) .tar.gz или bz2 означает файлы меньшего размера, но большую загрузку ЦП.

takeshin 03.08.2015 16:15

"хозяин" меня оттолкнул. Вы действительно имели в виду название папки для экспорта, верно? Я заменил это точкой.

Jonny 04.08.2016 04:29

Обратите внимание, что git archive не является решением, если вы используете git-lfs.

Paulo Moura 08.04.2017 02:25

git archive не забирает файлы, которые не зафиксированы. Я пытался использовать его для резервного копирования всех файлов, включая файлы, которые я редактировал, но он не собирал последние (отредактированные) файлы. Я уверен, что это так, как задумано. Теперь мне нужно найти способ получить список всех файлов в HEAD и использовать cpio для копирования файлов, чтобы я взял файлы, которые редактируются. Мне нужна команда git ls-tree -r master --name-only | cpio -pdmv / некоторые / dest

PatS 03.03.2018 08:11

Я написал простую оболочку для git-checkout-index, которую вы можете использовать следующим образом:

git export ~/the/destination/dir

Если целевой каталог уже существует, вам нужно добавить -f или --force.

Установка проста; просто перетащите скрипт где-нибудь в PATH и убедитесь, что он исполняемый.

Репозиторий github для git-export

Эта оболочка не зависит от платформы; он полагается на / bin / sh. Так что, если вы используете Windows, это решение наверное вам не подойдет.

shovavnik 19.07.2013 01:14

Ухх, этот скрипт состоит из 57 строк документации, пробелов, настроек, синтаксического анализа аргументов и только одной строки, которая действительно что-то делает ...

Vladimir Panteleev 13.05.2015 19:23

git archive также работает с удаленным репозиторием.

git archive --format=tar \
--remote=ssh://remote_server/remote_repository master | tar -xf -

Чтобы экспортировать конкретный путь внутри репо, добавьте столько путей, сколько хотите, в качестве последнего аргумента в git, например:

git archive --format=tar \
--remote=ssh://remote_server/remote_repository master path1/ path2/ | tar -xv

Этот вариант мне нравится больше всего. Дополнительным преимуществом является то, что он также работает с голыми репозиториями.

innaM 31.08.2009 18:34

Улучшенная версия: git archive --format=tar --prefix=PROJECT_NAME/ --remote=USER@SERVER:PROJECT_NAME.git master | tar -xf - (гарантирует, что ваш архив находится в папке)

Nick 15.12.2011 19:57

По какой-то причине это не работает для меня на github. Итак, я написал небольшую обертку в zsh: gist.github.com/1895274

Sebastian Stumpf 24.02.2012 01:59

это сработало для меня +1. Как указать целевую папку на основе этого примера?

Robbo_UK 06.06.2012 14:09

Удалось ответить на свой вопрос экспорт в указанный каталог git archive --format=tar --remote=ssh://remote_server/remote_repository master | (cd /path/to/dir/ && tar -xf -)

Robbo_UK 06.06.2012 14:50
Примечание: server must enable this feature.
Jakub Narębski 13.12.2012 15:19

если вы привыкли к svn export repository.com/etc, это самый близкий вариант.

jsd 21.02.2013 02:58

Я попробовал: git archive --format=zip --output foo.zip --remote=https://github.com/xxx.git master и получил фатальный результат: операция не поддерживается протоколом. Неожиданный конец потока команд.

andyf 19.07.2013 12:04

@andyf поддерживает только git и протокол smart http. Если простой http на сервере, то он этого не сделает. stackoverflow.com/a/11258694/520567

akostadinov 22.07.2013 20:56

@andyf GitHub работает по-своему: curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | tar xzf - на документы

bishop 31.07.2014 17:51

@bishop GitHub также поддерживает (но не рекламирует) протокол git. Просто замените https: // на git: // в URL-адресе.

Neil Mayhew 13.01.2016 21:43

@NeilMayhew У меня не работает, я получаю fatal: The remote end hung up unexpectedly. Пробовал на двух разных серверах с репозиторием github jQuery.

Anthony Hatzopoulos 24.01.2016 02:54

Похоже, что это меньшая проблема с Git, чем с SVN. Git помещает только папку .git в корень репозитория, тогда как SVN помещает папку .svn в каждый подкаталог. Таким образом, "svn export" избегает рекурсивной магии командной строки, тогда как с Git в рекурсии нет необходимости.

Начиная с SVN 1.7, есть только одна папка .svn: subversion.apache.org/docs/release-notes/1.7.html#single-db

kostmo 26.07.2011 01:10

Это не избавит от каких-либо дополнительных файлов сборки, которые удаляет svn export. Так что это точно не ответ.

ygoe 16.04.2014 12:32

Мне это было нужно для сценария развертывания, и я не мог использовать ни один из вышеупомянутых подходов. Вместо этого я нашел другое решение:

#!/bin/sh
[ $# -eq 2 ] || echo "USAGE $0 REPOSITORY DESTINATION" && exit 1
REPOSITORY=$1
DESTINATION=$2
TMPNAME = "/tmp/$(basename $REPOSITORY).$$"
git clone $REPOSITORY $TMPNAME
rm -rf $TMPNAME/.git
mkdir -p $DESTINATION
cp -r $TMPNAME/* $DESTINATION
rm -rf $TMPNAME

В чем заключалась проблема с решением для дерева чтения / проверки-индекса или архивирования? Насколько я могу судить, вы сделали эквивалент чего-то вроде mkdir -p "" && git --git-dir = "" archive HEAD | tar -x -C "", но несколько длиннее.

CB Bailey 17.07.2009 14:16

Мне не удалось заставить работать дерево чтения из удаленного репозитория, а решение для архивирования не работает с github.

troelskn 17.07.2009 18:34

Да, с архивом получить недопустимую команду: 'git-upload-archive' ... ошибка, и у меня нет параметра конфигурации core.gitProxy и установленной переменной среды GIT_PROXY_COMMAND

tgkprog 26.11.2014 15:05

Делая это простым способом, это функция для .bash_profile, она напрямую распаковывает архив в текущее место, сначала настройте свой обычный [url: path]. ПРИМЕЧАНИЕ: с помощью этой функции вы избегаете операции клонирования, она получает напрямую из удаленного репо.

gitss() {
    URL=[url:path]

    TMPFILE = "`/bin/tempfile`"
    if [ "" = "" ]; then
        echo -e "Use: gitss repo [tree/commit]\n"
        return
    fi
    if [ "" = "" ]; then
        TREEISH = "HEAD"
    else
        TREEISH = ""
    fi
    echo "Getting /$TREEISH..."
    git archive --format=zip --remote=$URL/ $TREEISH > $TMPFILE && unzip $TMPFILE && echo -e "\nDone\n"
    rm $TMPFILE
}

Псевдоним для .gitconfig, требуется такая же конфигурация (ОБЯЗАТЕЛЬНО выполняя команду внутри проектов .git, она ВСЕГДА переходит в базовый каталог ранее как сказано здесь, пока это не будет исправлено, я лично предпочитаю функцию

ss = !env GIT_TMPFILE = "`/bin/tempfile`" sh -c 'git archive --format=zip --remote=[url:path]/  \ > $GIT_TMPFILE && unzip $GIT_TMPFILE && rm $GIT_TMPFILE' -

Я просто хочу отметить, что в случае, если вы

  1. экспорт подпапки репозитория (так я использовал функцию экспорта SVN)
  2. согласны с копированием всего из этой папки в место развертывания
  3. и поскольку у вас уже есть копия всего репозитория.

Тогда вы можете просто использовать cp foo [destination] вместо упомянутого git-archive master foo | -x -C [destination].

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

cp -R ./path-to-git-repo /path/to/destination/

Обычный старый bash отлично работает :)

Почему бы просто не нажать на пульт? Даже проще, чем bash.

nurettin 20.03.2012 15:26

как насчет файлов, которые являются частью веб-приложений и их имя начинается с точки? :) подумайте о .htaccess

Artur 08.09.2013 01:38

Иногда вы также хотите игнорировать то, что находится в .gitignore, этого не будет.

fregante 22.04.2015 14:13

Я широко использую git-submodules. Это работает для меня:

rsync -a ./FROM/ ./TO --exclude='.*'

Не будут ли пропущены файлы, имена которых начинаются с точки, например .htaccess?

Greg Hewgill 16.09.2011 23:45

Хорошее решение, я бы заменил --exclude = '. *' На --exclude = '. Git *'

schmunk 12.10.2011 12:00

--exclude-vcs, если вы собираетесь поступить так

plod 07.11.2011 21:05

Может ли ./FROM/ быть удаленным репо?

Resist Design 31.01.2013 06:14

Я бы заменил --exclude = '. *' На --exclude = '. Git *'

haknick 29.10.2013 17:39

К вашему сведению, моя копия rsync перечисляет аргумент как --cvs-exclude. Кроме того, он по-прежнему копирует .gitattributes и .gitignore.

Ryan Ransford 21.02.2014 18:12

Bash-реализация git-export.

Я сегментировал процессы создания и удаления файлов .empty по их собственной функции с целью их повторного использования в реализации «git-archive» (будет опубликовано позже).

Я также добавил в процесс файл .gitattributes, чтобы удалить ненужные файлы из целевой папки экспорта. Включено подробное описание процесса, что сделало функцию «git-export» более эффективной.

EMPTY_FILE = ". Пустой";

function create_empty () {
## Processing path (target-dir):
    TRG_PATH = "";
## Component(s):
    EXCLUDE_DIR = ".git";
echo -en "\nAdding '${EMPTY_FILE}' files to empty folder(s): ...";
    find ${TRG_PATH} -not -path "*/${EXCLUDE_DIR}/*" -type d -empty -exec touch {}/${EMPTY_FILE} \;
#echo "done.";
## Purging SRC/TRG_DIRs variable(s):
    unset TRG_PATH EMPTY_FILE EXCLUDE_DIR;
    return 0;
  }

declare -a GIT_EXCLUDE;
function load_exclude () {
    SRC_PATH = "";
    ITEMS=0; while read LINE; do
#      echo -e "Line [${ITEMS}]: '${LINE%%\ *}'";
      GIT_EXCLUDE[((ITEMS++))]=${LINE%%\ *};
    done < ${SRC_PATH}/.gitattributes;
    GIT_EXCLUDE[${ITEMS}] = "${EMPTY_FILE}";
## Purging variable(s):
    unset SRC_PATH ITEMS;
    return 0;
  }

function purge_empty () {
## Processing path (Source/Target-dir):
    SRC_PATH = "";
    TRG_PATH = "";
echo -e "\nPurging Git-Specific component(s): ... ";
    find ${SRC_PATH} -type f -name ${EMPTY_FILE} -exec /bin/rm '{}' \;
    for xRULE in ${GIT_EXCLUDE[@]}; do
echo -en "    '${TRG_PATH}/{${xRULE}}' files ... ";
      find ${TRG_PATH} -type f -name "${xRULE}" -exec /bin/rm -rf '{}' \;
echo "done.'";
    done;
echo -e "done.\n"
## Purging SRC/TRG_PATHs variable(s):
    unset SRC_PATH; unset TRG_PATH;
    return 0;
  }

function git-export () {
    TRG_DIR = ""; SRC_DIR = "";
    if [ -z "${SRC_DIR}" ]; then SRC_DIR = "${PWD}"; fi
    load_exclude "${SRC_DIR}";
## Dynamically added '.empty' files to the Git-Structure:
    create_empty "${SRC_DIR}";
    GIT_COMMIT = "Including '${EMPTY_FILE}' files into Git-Index container."; #echo -e "\n${GIT_COMMIT}";
    git add .; git commit --quiet --all --verbose --message "${GIT_COMMIT}";
    if [ "${?}" -eq 0 ]; then echo " done."; fi
    /bin/rm -rf ${TRG_DIR} && mkdir -p "${TRG_DIR}";
echo -en "\nChecking-Out Index component(s): ... ";
    git checkout-index --prefix=${TRG_DIR}/ -q -f -a
## Reset: --mixed = reset HEAD and index:
    if [ "${?}" -eq 0 ]; then
echo "done."; echo -en "Resetting HEAD and Index: ... ";
        git reset --soft HEAD^;
        if [ "${?}" -eq 0 ]; then
echo "done.";
## Purging Git-specific components and '.empty' files from Target-Dir:
            purge_empty "${SRC_DIR}" "${TRG_DIR}"
          else echo "failed.";
        fi
## Archiving exported-content:
echo -en "Archiving Checked-Out component(s): ... ";
        if [ -f "${TRG_DIR}.tgz" ]; then /bin/rm ${TRG_DIR}.tgz; fi
        cd ${TRG_DIR} && tar -czf ${TRG_DIR}.tgz ./; cd ${SRC_DIR}
echo "done.";
## Listing *.tgz file attributes:
## Warning: Un-TAR this file to a specific directory:
        ls -al ${TRG_DIR}.tgz
      else echo "failed.";
    fi
## Purgin all references to Un-Staged File(s):
   git reset HEAD;
## Purging SRC/TRG_DIRs variable(s):
    unset SRC_DIR; unset TRG_DIR;
    echo "";
    return 0;
  }

Output:

$ git-export /tmp/rel-1.0.0

Adding '.empty' files to empty folder(s): ... done.

Checking-Out Index component(s): ... done.

Resetting HEAD and Index: ... done.

Purging Git-Specific component(s): ...

'/tmp/rel-1.0.0/{.buildpath}' files ... done.'

'/tmp/rel-1.0.0/{.project}' files ... done.'

'/tmp/rel-1.0.0/{.gitignore}' files ... done.'

'/tmp/rel-1.0.0/{.git}' files ... done.'

'/tmp/rel-1.0.0/{.gitattributes}' files ... done.'

'/tmp/rel-1.0.0/{*.mno}' files ... done.'

'/tmp/rel-1.0.0/{*~}' files ... done.'

'/tmp/rel-1.0.0/{.*~}' files ... done.'

'/tmp/rel-1.0.0/{*.swp}' files ... done.'

'/tmp/rel-1.0.0/{*.swo}' files ... done.'

'/tmp/rel-1.0.0/{.DS_Store}' files ... done.'

'/tmp/rel-1.0.0/{.settings}' files ... done.'

'/tmp/rel-1.0.0/{.empty}' files ... done.'

done.

Archiving Checked-Out component(s): ... done.

-rw-r--r-- 1 admin wheel 25445901 3 Nov 12:57 /tmp/rel-1.0.0.tgz

I have now incorporated the 'git archive' functionality into a single process that makes use of 'create_empty' function and other features.

function git-archive () {
    PREFIX = ""; ## sudo mkdir -p ${PREFIX}
    REPO_PATH = "`echo ""|awk -F: '{print }'`";
    RELEASE = "`echo ""|awk -F: '{print }'`";
    USER_PATH = "${PWD}";
echo "$PREFIX $REPO_PATH $RELEASE $USER_PATH";
## Dynamically added '.empty' files to the Git-Structure:
    cd "${REPO_PATH}"; populate_empty .; echo -en "\n";
#    git archive --prefix=git-1.4.0/ -o git-1.4.0.tar.gz v1.4.0
# e.g.: git-archive /var/www/htdocs /repos/domain.name/website:rel-1.0.0 --explode
    OUTPUT_FILE = "${USER_PATH}/${RELEASE}.tar.gz";
    git archive --verbose --prefix=${PREFIX}/ -o ${OUTPUT_FILE} ${RELEASE}
    cd "${USER_PATH}";
    if [[ "" =~ [--explode] ]]; then
      if [ -d "./${RELEASE}" ]; then /bin/rm -rf "./${RELEASE}"; fi
      mkdir -p ./${RELEASE}; tar -xzf "${OUTPUT_FILE}" -C ./${RELEASE}
    fi
## Purging SRC/TRG_DIRs variable(s):
    unset PREFIX REPO_PATH RELEASE USER_PATH OUTPUT_FILE;
    return 0;
  }

Использование: git-archive [/ var / www / htdocs] /repos/web.domain/website:rel-1.0.0

tocororo 04.11.2011 08:04

Я часто заходил на эту страницу, когда искал способ экспортировать репозиторий git. В моем ответе на этот вопрос рассматриваются три свойства, которые svn export изначально имеет по сравнению с git, поскольку svn следует подходу централизованного репозитория:

  • Он минимизирует трафик к удаленному репозиторию, не экспортируя все версии.
  • Он не включает метаинформацию в каталог экспорта
  • Экспорт определенной ветки с помощью svn осуществляется путем указания соответствующего пути

    git clone --depth 1 --branch master git://git.somewhere destination_path
    rm -rf destination_path/.git
    

При сборке определенного выпуска полезно клонировать стабильную ветку, например, --branch stable или --branch release/0.9.

Это не работает, если место назначения существует и не является пустым.

Eponymous 13.01.2015 21:20
Единственный верный ответ:он возникает из глубины. The git archive | tar approach is inapplicable to POSIX-incompatible shell environments (e.g., AppVeyor's CMD- or PowerShell-based CI), which is non-ideal. The git checkout approach modifies the index of the main working tree, which is awful. The git checkout-index approach requires the index of the main working tree to be modified beforehand, which is even awful-er. The traditional git clone approach clones the entirety of the repository's history before deleting that history, which is wasteful. This is the only sane solution left.
Cecil Curry 10.08.2017 10:17

Для локального экспорта обратите внимание, что абсолютный путь к рабочему дереву Git, из которого нужно клонировать, должен иметь префикс протокола file:// (например, git clone --depth 1 --branch v3.14.15 file:///home/me/src_repo trg_repo). В противном случае будет выдан "warning: --depth is ignored in local clones; use file:// instead." и будет выполнен стандартный, а не неглубокий клон, что приведет к поражению всей цели этого ответа. Салуд!

Cecil Curry 10.08.2017 10:24

Эквивалент

svn export . otherpath

внутри существующего репо

git archive branchname | (cd otherpath; tar x)

Эквивалент

svn export url otherpath

является

git archive --remote=url branchname | (cd otherpath; tar x)

спасибо, это было то, чего мне не хватало ... также, чтобы проверить временные метки экспорта (они не будут сохранены, как в файлах), используйте git archive --format=tar --prefix=junk/ HEAD | (tar -t -v --full-time -f -) ... Однако архивирование с временными метками не совсем тривиально, поэтому я опубликовал пример ниже.

sdaau 15.07.2014 18:18

Вы можете использовать опцию C для tar вместо подоболочки, например: git archive branchname | tar xC otherpath

James Moore 11.11.2016 22:34

Обратите внимание, что опция C для tar - это только GNU Tar.

aredridel 18.10.2017 17:30

Если вам нужно что-то, что работает с подмодулями, возможно, стоит попробовать.

Примечание:

  • MASTER_DIR = проверка с вашими подмодулями, также проверенными
  • DEST_DIR = где этот экспорт закончится
  • Если у вас есть rsync, я думаю, вы сможете сделать то же самое, но с еще меньшей болью.

Предположения:

  • Вам нужно запустить это из родительского каталога MASTER_DIR (то есть из компакт-диска MASTER_DIR ..)
  • Предполагается, что DEST_DIR был создан. Это довольно легко изменить, включив создание DEST_DIR, если вы хотите

cd MASTER_DIR && tar -zcvf ../DEST_DIR/export.tar.gz --exclude='.git*' . && cd ../DEST_DIR/ && tar xvfz export.tar.gz && rm export.tar.gz

Если вам также нужны подмодули, это должно помочь: https://github.com/meitar/git-archive-all.sh/wiki

На самом деле, похоже, что у него есть несколько небольших проблем, поэтому он, возможно, еще не готов к прайм-тайму.

Brandon 23.08.2012 19:27

Вы можете заархивировать удаленное репо в любой фиксации в виде zip-файла.

git archive --format=zip --output=archive.zip --remote=USERNAME@HOSTNAME:PROJECTNAME.git HASHOFGITCOMMIT

Так же просто, как клонирование, затем удалите папку .git:

git clone url_of_your_repo path_to_export && rm -rf path_to_export/.git

Честно говоря, этот ответ, который также является №1 в вопросе, - это то, чем вы собираетесь заниматься в 99% случаев. Большинство этих ответов безумно сложны.

Geoff Nixon 07.03.2014 18:28

−1. Во-первых, этот способ уже упоминается в вопросе как не удовлетворяющий автора вопроса. Во-вторых, таким образом будет загружена вся история, которая может быть намного больше полезной части. Пожалуйста, включите хотя бы --depth 1. В-третьих, даже если этот ответ улучшен, он ничего не добавляет к ответ Ларса Шиллингмана.

Sasha 25.02.2021 14:36

Ответ в частном случае, если репозиторий размещен на GitHub.

Просто используйте svn export.

Насколько я знаю, Github не поддерживает archive --remote. Хотя GitHub - это svn совместимый, и у них есть все доступные репозитории git svn, поэтому вы можете просто использовать svn export, как обычно, с небольшими изменениями URL-адреса GitHub.

Например, чтобы экспортировать весь репозиторий, обратите внимание, как trunk в URL-адресе заменяет master (или любой другой ветка HEAD проекта установлена ​​на):

svn export https://github.com/username/repo-name/trunk/

И вы можете экспортировать отдельный файл или даже определенный путь или папку:

svn export https://github.com/username/repo-name/trunk/src/lib/folder

Пример с Библиотека jQuery JavaScript

Ветвь HEAD или ветвь мастер будет доступна при использовании trunk:

svn ls https://github.com/jquery/jquery/trunk

Не-HEADветви будет доступен под /branches/:

svn ls https://github.com/jquery/jquery/branches/2.1-stable

Все теги под /tags/ одинаково:

svn ls https://github.com/jquery/jquery/tags/2.1.3

git archive отлично работает с GitHub, если вы используете протокол git. Просто замените https:// на git:// в URL-адресе. Я не знаю, почему GitHub не рекламирует эту скрытую функцию.

Neil Mayhew 13.01.2016 21:48

@NeilMayhew У меня не работает, я получаю fatal: The remote end hung up unexpectedly. Пробовал на двух разных серверах с репозиторием github jQuery.

Anthony Hatzopoulos 24.01.2016 02:55

Ты прав. Я забыл, что использовал git config url.<base>.insteadOf для кеширования удаленного репозитория. Поэтому на самом деле я использовал URL-адрес file://. Я сомневаюсь, что git archive когда-либо сможет работать с URL-адресами git://, поскольку он должен иметь возможность запускать git-upload-archive на удаленном конце. Это должно быть возможно с использованием протокола ssh, за исключением того, что github не позволяет это (Invalid command: 'git-upload-archive').

Neil Mayhew 25.01.2016 17:49

Любой способ использовать локальный серверный инструмент, который ведет себя как github, если я хочу сделать это во внутренних репозиториях git?

kriss 14.11.2016 17:47

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

Jason S 31.05.2017 19:23

Интересно, как использовать svn export с 2FA или с токеном API на github.

Ondrej Burkert 13.03.2018 12:02

Другой вариант загрузки с GitHub - использовать REST API, см. Этот скрипт Python: gist.github.com/LewisGaul/65aa7d4ff5a20abb1c8ea02cd0948486

Siwel 02.12.2020 00:40

Если вы не исключаете файлы с .gitattributesexport-ignore, попробуйте git checkout

mkdir /path/to/checkout/
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout -f -q

-f
When checking out paths from the index, do not fail upon unmerged entries; instead, unmerged entries are ignored.

и

-q
Avoid verbose

Кроме того, вы можете получить любую ветку или тег или из определенной версии фиксации, как в SVN, просто добавив SHA1 (SHA1 в Git эквивалентен номеру версии в SVN)

mkdir /path/to/checkout/
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout 2ef2e1f2de5f3d4f5e87df7d8 -f -q -- ./

/path/to/checkout/ должен быть пустым, Git не удалит файлы, но перезапишет файлы с тем же именем без предупреждения.

ОБНОВИТЬ: Чтобы избежать проблемы с обезглавливанием или оставить нетронутым рабочий репозиторий при использовании checkout для экспорта с тегами, ветвями или SHA1, вам нужно добавить -- ./ в конце

Двойное тире -- сообщает git, что все после тире - это пути или файлы, а также в этом случае указывает git checkout не изменять HEAD.

Примеры:

Эта команда получит только каталог libs, а также файл readme.txt именно из этого коммита.

git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout fef2e1f2de5f3d4f5e87df7d8 -f -q -- ./libs ./docs/readme.txt

Это создаст (перезапишет) my_file_2_behind_HEAD.txt с двумя коммитами за головой HEAD^2.

git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout HEAD^2 -f -q -- ./my_file_2_behind_HEAD.txt

Получить экспорт другой ветки

git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout myotherbranch -f -q -- ./

Обратите внимание, что ./ относится к корню репозитория.

На самом деле, среди множества других и положительных отзывов, это сработало для меня лучше всего, без каких-либо сжатий, отлично работало с голыми репозиториями (gitolite).

takeshin 03.10.2014 18:00

Обратите внимание, что проверка SHA1 создаст проблему «обезглавливания» в репозитории.

user5286776117878 04.10.2014 21:26

на самом деле @ITGabs, это не загружает папку ".git". Таким образом, загруженная папка не является репозиторием git, поэтому технически она не «обезглавлена»

Fabio Marreco 03.05.2016 22:22

@FabioMarreco Проблема с обезглавливанием находится в репозитории, а не в экспортированных / загруженных файлах, я обновляю ответ для получения более подробной информации

user5286776117878 07.05.2016 10:04

Это отлично сработало для меня. Но сначала я получал сообщения об ошибке «Не репозиторий git». Затем я обнаружил, что «/ path / to / repo /» должен указывать на папку .git. Итак, это сработало: --git-dir = / path / to / repo / .git

philburk 10.05.2016 18:05

Что, если я хочу экспортировать более раннюю фиксацию? Во-первых, сделайте заказ на более раннюю фиксацию с помощью git checkout <sha1>, затем свою команду git --git-dir=/path/to/repo/ --work-tree=/path/to/checkout/ checkout -f -q?

horse 11.03.2017 09:19

Это скопирует файлы из диапазона коммитов (от C до G) в файл tar. Примечание: при этом будут зафиксированы только файлы. Не весь репозиторий. Немного изменено от Здесь

Пример истории фиксации

А -> В -> C -> D -> E -> F -> G -> H -> I

git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT C~..G | xargs tar -rf myTarFile.tar

Страница руководства git-diff-tree

-r -> рекурсировать в поддеревья

--no-commit-id -> git diff-tree выводит строку с идентификатором фиксации, если применимо. Этот флаг подавляет вывод идентификатора фиксации.

--name-only -> Показывать только имена измененных файлов.

--diff-filter = ACMRT -> Выбрать только эти файлы. Смотрите здесь полный список файлов

C..G -> Файлы в этом диапазоне коммитов

C ~ -> Включить файлы из коммита C. Не только файлы после коммита C.

| xargs tar -rf myTarFile -> выводит в tar

В моем файле .bashrc есть следующая служебная функция: она создает архив текущей ветки в репозитории git.

function garchive()
{
  if [[ "x" == "x-h" || "x" == "x" ]]; then
    cat <<EOF
Usage: garchive <archive-name>
create zip archive of the current branch into <archive-name>
EOF
  else
    local oname=
    set -x
    local bname=$(git branch | grep -F "*" | sed -e 's#^*##')
    git archive --format zip --output ${oname} ${bname}
    set +x
  fi
}

Я думаю, что сообщение @Aredridel было самым близким, но есть кое-что еще - поэтому я добавлю это здесь; дело в том, что в svn, если вы находитесь в подпапке репо, и вы делаете:

/media/disk/repo_svn/subdir$ svn export . /media/disk2/repo_svn_B/subdir

тогда svn экспортирует все файлы, которые находятся под контролем версий (они также могли быть недавно добавлены; или измененный статус) - и если у вас есть другой «мусор» в этом каталоге (и я не считаю здесь вложенные папки .svn, но видим такие вещи, как Файлы .o) будет экспортирован нет; будут экспортированы только те файлы, которые зарегистрированы репозиторием SVN. Для меня приятно то, что этот экспорт также включает файлы с локальными изменениями, для которых нет еще был зафиксирован; и еще одна приятная вещь заключается в том, что временные метки экспортируемых файлов такие же, как и у исходных. Или, как говорит svn help export:

  1. Exports a clean directory tree from the working copy specified by PATH1, at revision REV if it is given, otherwise at WORKING, into PATH2. ... If REV is not specified, all local changes will be preserved. Files not under version control will not be copied.

Чтобы понять, что git не сохранит отметки времени, сравните вывод этих команд (в подпапке репозитория git по вашему выбору):

/media/disk/git_svn/subdir$ ls -la .

... и:

/media/disk/git_svn/subdir$ git archive --format=tar --prefix=junk/ HEAD | (tar -t -v --full-time -f -)

... и я, в любом случае, замечаю, что git archive приводит к тому, что все временные метки заархивированного файла совпадают! git help archive говорит:

git archive behaves differently when given a tree ID versus when given a commit ID or tag ID. In the first case the current time is used as the modification time of each file in the archive. In the latter case the commit time as recorded in the referenced commit object is used instead.

... но, видимо, оба случая устанавливают "время модификации файла каждый"; тем самым нет сохраняет фактические временные метки этих файлов!

Итак, чтобы также сохранить временные метки, вот сценарий bash, который на самом деле является однострочным, хотя и несколько сложным, поэтому ниже он размещен в нескольких строках:

/media/disk/git_svn/subdir$ git archive --format=tar master | (tar tf -) | (\
  DEST = "/media/diskC/tmp/subdirB"; \
  CWD = "$PWD"; \
  while read line; do \
    DN=$(dirname "$line"); BN=$(basename "$line"); \
    SRD = "$CWD"; TGD = "$DEST"; \
    if [ "$DN" != "." ]; then \
      SRD = "$SRD/$DN" ; TGD = "$TGD/$DN" ; \
      if [ ! -d "$TGD" ] ; then \
        CMD = "mkdir \"$TGD\"; touch -r \"$SRD\" \"$TGD\""; \
        echo "$CMD"; \
        eval "$CMD"; \
      fi; \
    fi; \
    CMD = "cp -a \"$SRD/$BN\" \"$TGD/\""; \
    echo "$CMD"; \
    eval "$CMD"; \
    done \
)

Обратите внимание, что предполагается, что вы экспортируете содержимое в «текущий» каталог (выше, /media/disk/git_svn/subdir) - и место назначения, в которое вы экспортируете, размещено несколько неудобно, но оно находится в переменной среды DEST. Обратите внимание, что с этим скриптом; вы должны вручную создать каталог DEST перед запуском вышеуказанного сценария.

После запуска скрипта вы сможете сравнить:

ls -la /media/disk/git_svn/subdir
ls -la /media/diskC/tmp/subdirB   # DEST

... и, надеюсь, увидите те же отметки времени (для тех файлов, которые находились под контролем версий).

Надеюсь, это кому-то поможет,
Ваше здоровье!

Для пользователей GitHub метод git archive --remote не будет работать напрямую, как URL экспорта недолговечен. Вы должны попросить GitHub указать URL-адрес, а затем загрузить этот URL-адрес. curl упрощает это:

curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | tar xzf -

Это даст вам экспортированный код в локальном каталоге. Пример:

$ curl -L https://api.github.com/repos/jpic/bashworks/tarball | tar xzf -
$ ls jpic-bashworks-34f4441/
break  conf  docs  hack  LICENSE  mlog  module  mpd  mtests  os  README.rst  remote  todo  vcs  vps  wepcrack

Редактировать
Если вы хотите, чтобы код помещался в конкретный каталог существующий (а не в случайный каталог из github):

curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | \
tar xzC /path/you/want --strip 1

Да, это - это чистая и аккуратная команда для архивирования вашего кода без включения git в архив, и ее можно передавать, не беспокоясь о истории коммитов git.

git archive --format zip --output /full/path/to/zipfile.zip master 

Это здорово, просто нужно удалить gitignore после, и он готов и готов к публикации.

Sogger 29.01.2016 02:53

Удаление .gitgnore и т. д. Упоминается в принятых комментариях к ответу: используйте файл .gitattributes, см. Feed.cloud.geek.nz/posts/excluding-files-from-git-archive

Sogger 29.01.2016 02:59

Безусловно, самый простой способ, который я видел (и также работает с Windows), - это git bundle:

git bundle create /some/bundle/path.bundle --all

Подробнее см. В этом ответе: Как я могу скопировать репозиторий git с моей машины Windows на машину Linux через USB-накопитель?

git bundle включает папку .git, чего OP не хочет; git archive кажется более подходящим способом

ssc 06.02.2016 16:45

Где документация на коммутатор --all?

Garret Wilson 05.11.2017 17:30

@GarretWilson, это странно. --all здесь не вариант для создания пакета git, даже если он действительно выглядит так. --all - допустимое значение для передачи как git-rev-list, см. git-scm.com/docs/git-rev-list.

James Moore 02.12.2020 19:14

Вариант 1 звучит не слишком эффективно. Что делать, если в клиенте нет места для клонирования и потом удаляет папку .git?

Сегодня я обнаружил, что пытаюсь сделать это, где клиентом является Raspberry Pi, на котором почти не осталось места. Кроме того, я также хочу исключить из репозитория какую-то тяжелую папку.

Вариант 2 и другие ответы здесь не помогают в этом сценарии. Ни git archive (потому что требуется зафиксировать файл .gitattributes, и я не хочу сохранять это исключение в репозитории).

Здесь я делюсь своим решением, аналогичным варианту 3, но без использования git clone:

tmp=`mktemp`
git ls-tree --name-only -r HEAD > $tmp
rsync -avz --files-from=$tmp --exclude='fonts/*' . raspberry:

Замена строки rsync на эквивалентную строку для сжатия также будет работать как git archive, но с своего рода опцией исключения (как задается здесь).

У меня есть другое решение, которое отлично работает, если у вас есть локальная копия репозитория на машине, на которой вы хотите создать экспорт. В этом случае перейдите в этот каталог репозитория и введите эту команду:

GIT_WORK_TREE=outputdirectory git checkout -f

Это особенно полезно, если вы управляете веб-сайтом с помощью репозитория git и хотите проверить чистую версию в /var/www/. В этом случае добавьте эту команду в сценарий .git/hooks/post-receive (hooks/post-receive в голом репозитории, что больше подходит в этой ситуации)

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

Это можно сделать так:

git clone -b someBranch --depth 1 --single-branch git://somewhere.com/repo.git \
&& rm -rf repo/.git/
  • --single-branch доступен с Git 1.7.10 (апрель 2012 г.).
  • --depth является (был?) Неисправным по сообщениям, но в случае экспорта упомянутые проблемы не должны иметь значения.

Примечание: я только что заметил, что есть 2 страницы анонсеров, я просмотрел только одну перед публикацией. Есть один аналогичный ответ только с --depth, который подразумевает --single-branch, если не указан --no-single-branch, что означает, что это, вероятно, имеет тот же эффект. Хотя не уверены, может подтвердить какой-нибудь эксперт?

Ondra Žižka 12.03.2018 17:56

экспорт git в zip-архив с добавлением префикса (например, имени каталога):

git archive master --prefix=directoryWithinZip/  --format=zip -o out.zip

Другие вопросы по теме