Есть ли "git export" (например, "svn export")? - PullRequest
2263 голосов
/ 02 октября 2008

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

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

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

Ответы [ 31 ]

19 голосов
/ 22 января 2012

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

16 голосов
/ 10 декабря 2010

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

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

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

12 голосов
/ 27 сентября 2013

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

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

11 голосов
/ 06 января 2015

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

git archive --format zip --output /full/path/to/zipfile.zip master 
10 голосов
/ 31 июля 2014

Для пользователей 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
10 голосов
/ 29 октября 2010

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

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

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

9 голосов
/ 09 октября 2012

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

git archive --format=zip --output=archive.zip --remote=USERNAME@HOSTNAME:PROJECTNAME.git HASHOFGITCOMMIT
8 голосов
/ 01 ноября 2011

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 / {. Buildpath}' files ... done. '

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

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

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

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

'/ tmp / rel-1.0.0 / {*. Mno}' файлы ... готово. '

'/ tmp / rel-1.0.0 / {* ~}' файлы ... готово. '

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

'/ tmp / rel-1.0.0 / {*. Swp}' файлы ... готово. '

'/ tmp / rel-1.0.0 / {*. Swo}' файлы ... готово. '

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

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

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

сделано.

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

-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;
  }
8 голосов
/ 28 февраля 2012

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

Примечание:

  • 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 голосов
/ 25 апреля 2014

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

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

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

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

C ~ -> Включить файлы из Commit C. Не только файлы, начиная с Commit C.

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

...