Сделайте "git export" (например, "svn export" )?

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

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

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

Ответ 1

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

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

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

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

Почтовый архив:

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

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


Примечание. Если вы заинтересованы в экспорте индекса, команда

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

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

Ответ 2

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

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

Черта в конце пути важна, иначе это приведет к тому, что файлы находятся в /destination с префиксом "пути".

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

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

Это выглядит как "git export", который я искал.

Ответ 3

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

Ответ 4

enter image description here

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

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

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

Например, чтобы экспортировать весь репозиторий, обратите внимание на то, что trunk в URL-адресе заменяет master (или что-то вроде jQuery JavaScript Library

Разветвление ветки HEAD или master будет доступно с помощью 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

Ответ 5

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

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

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

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

Ответ 6

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

git export ~/the/destination/dir

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

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

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

Ответ 7

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

Ответ 8

Эквивалент

svn export . otherpath

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

git archive branchname | (cd otherpath; tar x)

Эквивалент

svn export url otherpath

является

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

Ответ 9

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

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

Ответ 10

Если вы не исключаете файлы с .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
Избегайте подробных

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

UPDATE: Чтобы избежать обезглавленной проблемы или оставить неповрежденным рабочий репозиторий при использовании проверки для экспорта с тегами, ветвями или 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 -- ./

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

Ответ 11

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

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

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

Ответ 12

Я часто сталкивался с этой страницей при поиске способа экспорта репозитория 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.

Ответ 13

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

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

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

Ответ 14

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

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

Ответ 15

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

git archive --format=zip --output=archive.zip [email protected]:PROJECTNAME.git HASHOFGITCOMMIT

Ответ 16

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

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

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

Ответ 17

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

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

Добавление "пустых" файлов в пустые папки:... done.

Компонент индексирования индексирования:... done.

Сброс HEAD и Index:... done.

Очистка git -специальный компонент (ы):...

'/tmp/rel-1.0.0/{. buildpath}' файлы... done. '

'/tmp/rel-1.0.0/{. project}' файлы... done. '

'/tmp/rel-1.0.0/{.gitignore}' файлы... done. '

'/tmp/rel-1.0.0/{. git}' файлы... done. '

'/tmp/rel-1.0.0/{. gitattributes}' файлы... done. '

'/tmp/rel-1.0.0/{*. mno}' файлы... done. '

'/tmp/rel-1.0.0/{* ~}' файлы... done. '

'/tmp/rel-1.0.0/{.* ~}' файлы... done. '

'/tmp/rel-1.0.0/{*. swp}' файлы... done. '

'/tmp/rel-1.0.0/{*. swo}' файлы... done. '

'/tmp/rel-1.0.0/{. DS_Store}' файлы... done. '

'/tmp/rel-1.0.0/{. settings}' файлы... done. '

'/tmp/rel-1.0.0/{. empty}' файлы... done. '

сделано.

Архивирование Выбранный компонент (ы):... done.

-rw-r - r-- 1 admin wheel 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;
  }

Ответ 18

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

Примечание:

  • 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

Ответ 19

Это скопирует файлы в диапазоне коммитов (от 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 Manual Страница

-r → рекурсия в поддеревья

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

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

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

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

C ~ → Включить файлы из Commit C. Не только файлы с Commit C.

| xargs tar -rf myTarFile → выходы для tar

Ответ 20

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

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

Ответ 21

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

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

Ответ 22

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

#!/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

Ответ 23

Сделав это простым способом, это функция для .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, она ВСЕГДА переходит к базовому dir ранее как сказано здесь, пока это не исправлено, я лично предпочитаю функцию

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' -

Ответ 24

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

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

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

/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 среды, Обратите внимание, что с этим script; вы должны создать каталог DEST вручную, прежде чем запускать выше script.

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

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

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

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

Ответ 27

У меня есть следующая служебная функция в моем файле .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
}

Ответ 28

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

Сегодня я обнаружил, что пытаюсь это сделать, где клиент - малина 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, но с опцией исключения (как задано здесь).

Ответ 29

Это мое любимое решение:

git diff <old-commit> <new-commit> --name-only | xargs tar -zcvf myTarFile.tar.gz

Это будет сравнивать две разные коммиты и экспортировать измененные файлы в качестве файла tar.gz

Ура!

Ответ 30

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

GIT_WORK_TREE=outputdirectory git checkout -f

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