Чи є "експорт git" (наприклад, "SVN-експорт")?


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: Дивіться відповідь Сомова. (в архіві дьогтю нічого "не стискається").
етаріон

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
Євгеній Сергєєв

Відповіді:


2396

Напевно, найпростіший спосіб досягти цього 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
Архів поштових скриньок:git archive --format zip --output /full/path master
Вадим

221
Майте на увазі, що архів не буде містити каталог .git, але буде містити й інші приховані файли, пов’язані з git, як-от. .gitattributes файл і зробити це перед тим, як зробити свій архів. Дивіться feed.cloud.geek.nz/2010/02/…
mj1531

54
Для подальшої роботи над приміткою "Потоки": ви можете додати в команду рядок '--prefix = something /', щоб керувати іменем каталогу, яке буде запаковано всередині zip. Наприклад, якщо ви використовуєте git archive --format zip --output /path/to/file.zip --prefix=newdir/ masterвихід, він буде називатися "file.zip", але коли ви його розпакуйте, каталог верхнього рівня буде "newdir". (Якщо опустити атрибут --prefix, то найвищим рівнем буде "файл".)
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/

Нахил в кінці шляху є важливим, інакше це призведе до того, що файли знаходяться в / призначення з префіксом "шлях".

Оскільки в звичайній ситуації індекс містить вміст сховища, нічого особливого не потрібно робити, щоб "прочитати потрібне дерево в індекс". Це вже є.

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

Схоже, це був такий тип "експорту git", який я шукав.


73
... І НЕ ЗАБУДУЙТЕ СЛОШУ В КРАЇНІ, інакше у вас не буде бажаного ефекту;)
conny

1
git addКоманда змінює зміст в індексі, тому все , що git statusпоказує , як «бути абсолютно» є різниця між головою і вмістом індексу.
Грег Х'югілл

7
@conny: прочитав ваш коментар, забув про нього і запустив команду без останньої косої риски. порада: дотримуйтесь порад conny -.-
Znarkus

35
+1 до поради conny. Крім того, не намагайтеся створити '~ / dest /', оскільки це створює каталог, який називається '~' у вашому робочому каталозі, а не те, що ви дійсно хотіли. Здогадайтесь, що станеться, коли ви бездумно набираєте rm -rf ~
Kyle Heironimus

5
@KyleHeironimus - ваше попередження про використання '~ / dest / `є істинним, якщо ви використовуєте лапки навколо шляху вашого префікса, який повідомляє оболонці не виконувати розширення tilde. Дір з назвою ~(не '~'!) Буде створений у вашому робочому режимі. У 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 -per docs
єпископ

62

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

Особлива відповідь у випадку, якщо сховище розміщене на GitHub.

Просто використовуйте svn export.

Наскільки я знаю, Github не дозволяє archive --remote. Хоча GitHub сумісний з svn і вони мають доступ до всіх git repos, 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.
Ентоні Хацопулос

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

Будь-який спосіб використовувати локальний серверний інструмент, який веде себе як github, якщо я хочу це зробити у внутрішніх сховищах git?
kriss

1
прихильне - абсолютно химерно, що у 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
Паскаль Росін

1
@JohnWeldon Чи вимагає від вас першої клонування репо? Якщо так, то я б не прийняв це, оскільки вся суть "svn експорту" підкаталогу полягає в тому, щоб безпосередньо отримати копію цього підкаталогу; якщо у когось є репо-гіт 1 Гбіт, і все, що я хочу, - це 10-кБ підкаталогію, божевільно вимагати від мене клонувати всю справу.
Jason S

3
Також я відлунював @ davetron5000 з коментарем "прочитати потрібне дерево в індекс", що я не маю поняття, що це означає.
Jason S

38

Я написав просту обгортку навколо, git-checkout-indexяку ви можете використовувати так:

git export ~/the/destination/dir

Якщо каталог призначення вже існує, вам потрібно буде додати -fабо --force.

Установка проста; просто киньте скрипт десь у своєму PATHі переконайтесь, що він виконується.

Сховище github для git-export


15
Ця обгортка не є платформою-агностиком; вона покладається на / бін / ш. Тому якщо ви працюєте в Windows, це рішення, ймовірно , не буде працювати для вас.
шовавник

18
Е, цей скрипт - це 57 рядків документації, пробіл, налаштування, розбір аргументів і лише один рядок, який насправді щось робить ...
Володимир Пантелеев

36

Здається, це менше проблеми з Git, ніж SVN. Git містить лише папку .git у корінь сховища, тоді як SVN додає папку .svn у кожен підкаталог. Отже, "SVN-експорт" дозволяє уникнути рекурсивної магії командного рядка, тоді як при Git рекурсія не є необхідною.


26
Станом на SVN 1.7, є також лише одна папка .svn: subversion.apache.org/docs/release-notes/1.7.html#single-db
kostmo

Це не дозволить позбутися будь-яких додаткових файлів збірки, які видаляє svn експорт. Тож це точно не відповідь.
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 для дьогтю замість субоболочкі, як це: git archive branchname | tar xC otherpath
Джеймс Мур

Звертається до уваги, що Cопція для націлювання - лише GNU Tar.
aredridel

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 -- ./

Зауважте, що ./це відносно кореня сховища


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

1
Зауважте, що замовлення SHA1 створить проблему "обезголовлення" у сховищі
user5286776117878

фактично @ITGabs, ця папка ".git" не завантажується. Отже, завантажена папка не є сховищем git, тому технічно вона не "обезголовлена"
Фабіо Марреко

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

3
Це спрацювало для мене чудово. Але спочатку я отримав повідомлення про помилки "Not git repository". Тоді я виявив, що "/ path / to / repo /" повинен вказувати на папку .git. Так це спрацювало: --git-dir = / шлях / до / repo / .git
philburk

21

Я широко використовую git-підмодулі. Цей для мене працює:

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

1
Чи не пропустили б файли, імена яких починаються з крапки, наприклад .htaccess?
Грег Хьюгілл

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

18
--exclude-vcs, якщо ви збиралися скористатися цим тактом
плануйте

Чи може ./FROM/ бути віддаленим репо?
Опір дизайну

2
Як FYI, моя копія 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підхід не застосовується до несумісних з оболонками середовищ оболонки (наприклад, на CMD- або на основі PowerShell CMI AppVeyor), що не ідеально. 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."та виконувати стандартний, а не дрібний клон, перемагаючи всю мету цієї відповіді. Салюд!
Сесіль Карі

16

Це скопіює весь вміст за вирахуванням файлів .dot. Я використовую це, щоб експортувати клоновані проекти git в git repo мого веб-додатка без речей .git.

cp -R ./path-to-git-repo / шлях / до / призначення /

Звичайний старий баш працює чудово :)


Чому б просто не натиснути на віддалений? Навіть простіше, ніж баш.
Нуреттін

2
як щодо файлів, що входять до веб-додатків, а його ім’я починається з крапки? :) подумайте про .htaccess
Artur

3
Іноді також хочеться ігнорувати те, що є .gitignore, це не буде.
fregante

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.

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

Це чудово, просто потрібно видалити gitignore після того, як це зроблено і готове ділитися.
Sogger

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

10

Я просто хочу зазначити, що у випадку, що ви є

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

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


9

Ви можете архівувати віддалений репо-файл на будь-якій комісії, як поштовий файл.

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

8

Баш-реалізація git-експорту.

Я сегментував процеси створення і видалення порожніх файлів. На їх власній функції з метою повторного використання їх у реалізації '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/{.buildpath}' файли ... зроблено. '

'/tmp/rel-1.0.0/{.project}' файли ... зроблено. '

'/tmp/rel-1.0.0/{.gitignore}' файли ... зроблено. '

'/tmp/rel-1.0.0/{.git}' файли ... зроблено. '

'/tmp/rel-1.0.0/{.gitattributes}' файли ... зроблено. '

'/tmp/rel-1.0.0/{*.mno}' файли ... зроблено. '

'/tmp/rel-1.0.0/{*~}' файли ... зроблено. '

'/tmp/rel-1.0.0/{.*~}' файли ... зроблено. '

'/tmp/rel-1.0.0/{*.swp}' файли ... зроблено. '

'/tmp/rel-1.0.0/{*.swo}' файли ... зроблено. '

'/tmp/rel-1.0.0/{.DS_Store}' файли ... зроблено. '

'/tmp/rel-1.0.0/{.settings}' файли ... зроблено. '

'/tmp/rel-1.0.0/{.empty}' файли ... зроблено. '

зроблено.

Архівація перевірених компонентів (-ів): ... виконано.

-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

Моїм перевагою було б мати мету dist у вашому Makefile (або іншій системі збирання), яка експортує дистрибутивний архів вашого коду (.tar.bz2, .zip, .jar або будь-який інший варіант). Якщо ви випадково використовуєте автоінструменти GNU або системи Perl's 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-дерева

-r -> повторюється в під деревах

--no-commit-id -> git diff-дерево видає рядок з ідентифікатором читання, коли це застосовано. Цей прапор придушив вихід ID ID.

- тільки для імені -> Показати лише імена змінених файлів.

--diff-filter = ACMRT -> Вибрати лише ці файли. Дивіться тут повний список файлів

C..G -> Файли в цьому діапазоні комітів

C ~ -> Включіть файли з фіксування комітету C. Не лише файли, починаючи з "Комітету".

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


5

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

Це можна зробити так:

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

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' ... помилка, і у мене немає опції config core.gitProxy та набір змінної середовища
GIT_PROXY_COMMAND

4

Це простий спосіб, це функція для .bash_profile, він безпосередньо розпаковує архів на поточному місці, конфігурує спочатку звичайний [url: path]. ПРИМІТКА: За допомогою цієї функції ви уникаєте операції клонування, вона надходить безпосередньо з віддаленого репо.

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, така ж конфігурація потрібна (TAKE CARE виконання команди всередині .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.