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


2356

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

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

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


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

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

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

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

Вот приятный и простой способ:git archive -o latest.zip HEAD
Евгений Сергеев

Ответы:


2397

Вероятно, самый простой способ достичь этого с 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/

(См . Ответ Грега для более подробной информации)


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

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

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

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

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

320

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

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

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

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

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

Похоже, это был тот «экспорт мерзавцев», который я искал.


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

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

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

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

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

254

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

6
Этот вариант мне нравится больше всего. Он имеет дополнительное преимущество, заключающееся в том, что он также работает с открытыми хранилищами
InnaM

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

7
Примечание : сервер должен включить эту функцию.
Якуб Наребски

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

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

63

введите описание изображения здесь

Ответ в особом случае, если хранилище размещено на 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

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

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

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

Любой способ использовать инструмент локального сервера, ведущий себя как GitHub, если я хочу сделать это в Git-репозиториях с внутренним размещением?
Крис

1
upvoted - совершенно странно, что у Git нет этой функции, и мы должны прибегнуть к svn
Jason S

40

Из руководства Git :

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

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

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


19
Я думаю, что путаница заключается в фразе "прочитать нужное дерево в указатель".
davetron5000

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

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

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

38

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

git export ~/the/destination/dir

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

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

Github хранилище для git-export


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

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

36

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


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

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

28

Эквивалент

svn export . otherpath

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

git archive branchname | (cd otherpath; tar x)

Эквивалент

svn export url otherpath

является

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

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

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

Обращаю внимание, что Cопцией tar является только GNU Tar.
Аредридель

22

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

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

-f
При проверке путей из индекса не допускайте сбоев при незаполненных записях; вместо этого необработанные записи игнорируются.

а также

-q
избегать многословия

Кроме того, вы можете получить любую ветку или тег или конкретную ревизию, как в 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 не будет удалять любой файл, но перезаписывает файлы с таким же именем без какого - либо предупреждения

ОБНОВЛЕНИЕ: чтобы избежать обезглавленной проблемы или оставить нетронутым рабочий репозиторий при использовании извлечения для экспорта с тегами, ветвями или 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

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

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

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

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

21

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

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

1
Разве это не пропустит файлы, имена которых начинаются с точки, например .htaccess?
Грег Хьюгилл,

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

18
--exclude-vcs, если вы собираетесь использовать этот такт
plod

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

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

19

Я часто заходил на эту страницу, когда искал способ экспортировать репозиторий git. Мой ответ на этот вопрос рассматривает три свойства, которые экспорт svn имеет по дизайну по сравнению с 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.


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

2
Единый верный ответ: он возникает из глубины. Этот git archive | tarподход неприменим к POSIX-несовместимым средам оболочки (например, CI AppVeyor на основе CMD или PowerShell), что не является идеальным. git checkoutПодход изменяет индекс основного рабочего дерева, которое ужасно. git checkout-indexПодход требует индекса основного рабочего дерева быть изменены заранее, что даже ужасно-эр. Традиционный git cloneподход клонирует всю историю репозитория перед удалением этой истории, что является расточительным. Это единственное вменяемое решение.
Сесил Карри

1
Чтобы выполнить локальный экспорт, обратите внимание, что абсолютный путь к рабочему дереву 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."созданию и выполнению стандартного, а не поверхностного клонирования, что побеждает всю цель этого ответа. Salud!
Сесил Карри

16

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

cp -R ./path-to-git-repo / путь / к / месту назначения /

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


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

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

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

14

Просто, как клон, удалите папку .git:

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


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

11

Для пользователей 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

11

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

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

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

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

10

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

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

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


9

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

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

8

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

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

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

Empty_file = "опустошить";

function create_empty () {
## Processing path (target-dir):
    TRG_PATH="${1}";
## 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="${1}";
    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="${1}";
    TRG_PATH="${2}";
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="${1}"; SRC_DIR="${2}";
    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;
  }

Вывод:

$ git-export /tmp/rel-1.0.0

Добавление файлов .empty в пустую папку (и): ... сделано.

Проверка компонентов индекса: ... выполнено.

Сброс HEAD и Index: ... сделано.

Чистка Git-специфических компонентов: ...

'/tmp/rel-1.0.0/ndom.buildpath}' файлы ... готово. '

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

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

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

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

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

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

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

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

'/tmp/rel-1.0.0/ndom*.swo}' файлы ... готово. "

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

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

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

сделанный.

Архивация извлеченных компонентов: ... выполнено.

-rw-r - r-- 1 колесо администратора 25445901 3 ноября, 12:57 /tmp/rel-1.0.0.tgz

Теперь я включил функциональность 'git archive' в единый процесс, который использует функцию 'create_empty' и другие функции.

function git-archive () {
    PREFIX="${1}"; ## sudo mkdir -p ${PREFIX}
    REPO_PATH="`echo "${2}"|awk -F: '{print $1}'`";
    RELEASE="`echo "${2}"|awk -F: '{print $2}'`";
    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 [[ "${3}" =~ [--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

8

Если вы хотите что-то, что работает с подмодулями, это может стоить того.

Замечания:

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

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

  • Вам нужно запустить это из родительского каталога MASTER_DIR (то есть из MASTER_DIR cd ..)
  • Предполагается, что 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


6

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

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


Проект, который я имел в виду, не является проектом кода; случается, что это больше похоже на проект веб-сайта.
Грег Хьюгилл

Не отвечает на вопрос.
Эндрю Ферье

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

6

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

Пример истории коммитов

A -> B -> 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 ~ -> Включить файлы из Commit C. Не только файлы с Commit C.

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


5

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

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

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не задан, что означает, что это, вероятно, имеет тот же эффект. Не уверен, хотя, какой-то эксперт может подтвердить?
Ондра Жижка

4

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

#!/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 "$2" && git --git-dir="$1" archive HEAD | tar -x -C "$2"но несколько длиннее.
CB Bailey

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

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

4

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

gitss() {
    URL=[url:path]

    TMPFILE="`/bin/tempfile`"
    if [ "$1" = "" ]; then
        echo -e "Use: gitss repo [tree/commit]\n"
        return
    fi
    if [ "$2" = "" ]; then
        TREEISH="HEAD"
    else
        TREEISH="$2"
    fi
    echo "Getting $1/$TREEISH..."
    git archive --format=zip --remote=$URL/$1 $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]/$1 $2 \ > $GIT_TMPFILE && unzip $GIT_TMPFILE && rm $GIT_TMPFILE' -

4

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

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

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


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

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

4

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

GIT_WORK_TREE=outputdirectory git checkout -f

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


3

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

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

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

  1. Экспортирует чистое дерево каталогов из рабочей копии, указанной в PATH1, при ревизии REV, если оно задано, в противном случае при РАБОТЕ, в PATH2. ... Если REV не указан, все локальные изменения будут сохранены. Файлы, не находящиеся под контролем версий, не будут скопированы.

Чтобы понять, что 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-архив ведет себя по-разному, когда ему присваивается идентификатор дерева, и когда ему присваивается идентификатор фиксации или идентификатор тега. В первом случае текущее время используется как время модификации каждого файла в архиве. В последнем случае вместо этого используется время фиксации, записанное в ссылочном объекте фиксации.

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

Итак, чтобы также сохранить временные метки, вот 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

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

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


3

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

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


1

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

function garchive()
{
  if [[ "x$1" == "x-h" || "x$1" == "x" ]]; then
    cat <<EOF
Usage: garchive <archive-name>
create zip archive of the current branch into <archive-name>
EOF
  else
    local oname=$1
    set -x
    local bname=$(git branch | grep -F "*" | sed -e 's#^*##')
    git archive --format zip --output ${oname} ${bname}
    set +x
  fi
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.