Git Clone: ​​Только файлы, пожалуйста?

141

Я хочу клонировать репозиторий GIT и НЕ получить .gitкаталог. Другими словами, мне просто нужны файлы. Есть ли способ сделать это?

git clone --no-checkoutсделал прямо противоположное тому, что я хочу (дал мне только .gitкаталог).

Я пытаюсь сделать это для удаленного репо, а не для локального, что означает, что это не дубликат « Как сделать« экспорт git »(например,« svn export ») » (даже если решение может оказаться тем же).

Дэн Розенстарк
источник
5
возможный дубликат Как сделать «git export» (например, «svn export»)
Грег Хьюгилл
@Greg Hewgill Я пытаюсь сделать это из удаленного репо. Не уверен, что это делает этот вопрос уникальным.
Дэн Розенстарк,
1
Хотя это новый вопрос, но я думаю, что его стоит проверить: stackoverflow.com/questions/11497457/…
eonil
1
См. Мой ответ на обновление : git archiveтеперь (4 квартал 2017 г.) более точный и не будет включать пустые папки.
VonC
1
Добро пожаловать. Судя по всему, ваш комментарий был отмечен и удален ... chat.stackoverflow.com/transcript/134259?m=39402889#39402889
VonC

Ответы:

75

Команда git, которая будет наиболее близкой к тому, что вы ищете, будет git archive.
См. Проект резервного копирования, который использует git : он будет включать в архив все файлы (включая подмодули, если вы используете git-archive-allсценарий)

Затем вы можете использовать этот архив где угодно, возвращая вам только файлы, но не .gitкаталог.

git archive --remote=<repository URL> | tar -t

Если вам нужны папки и файлы только с первого уровня:

git archive --remote=<repository URL> | tar -t --exclude="*/*"

Чтобы перечислить только папки первого уровня удаленного репо:

git archive --remote=<repository URL> | tar -t --exclude="*/*" | grep "/"

Примечание: это не работает для GitHub (не поддерживается)

Поэтому вам нужно будет клонировать (неглубоко, чтобы ускорить шаг клонирования), а затем заархивировать локально :

git clone --depth=1 git@github.com:xxx/yyy.git
cd yyy
git archive --format=tar aTag -o aTag.tar

Другой вариант - сделать неглубокий клон (как указано ниже), но разместить папку .git в другом месте.

git --git-dir=/path/to/another/folder.git clone --depth=1 /url/to/repo

Папка репо будет включать только файл без .git.

Примечание: git --git-dir это вариант командыgit , а не git clone.


Обновление до Git 2.14.X / 2.15 (4 квартал 2017 г.): оно позволит избежать добавления пустых папок .

" git archive", особенно при использовании с pathspec, сохраняет пустой каталог в своем выводе, хотя сам Git никогда этого не делает.
Это было исправлено.

См. Коммит 4318094 (12 сентября 2017 г.) Рене Шарфе (``) .
Предложено: Джеффом Кингом ( peff) .
(Объединено Junio ​​C Hamano - gitster- в коммите 62b1cb7 , 25 сентября 2017 г.)

archive: не добавлять в архивы пустые каталоги

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

Поскольку пустые каталоги не поддерживаются git, их также не следует записывать в архивы.
Если действительно нужен пустой каталог, его можно отследить и заархивировать, поместив в него пустой .gitignoreфайл.

VonC
источник
4
Это сработало для меня. Я бы добавил еще кое-что. Если вас вообще не интересует папка .git, я бы использовал эту команду:git --git-dir=/dev/null clone --depth=1 /url/to/repo
HumanSky
Это не удаляет папку .git
aliasav
@VonC Я пробовал: git --git-dir = / dev / null clone --depth = 1 / url / to / repo
aliasav
1
Бегу git archive --remote=https://github.com/pornel/dssim.git @ | tar -tполучаю tar: This does not look like a tar archive. Разве это не работает с GitHub? Кроме того, что это @значит?
Андре Верланг
2
@ AndréWerlang, 7 лет спустя ... Я не совсем уверен @: я удалил его. Также GitHub не поддерживает удаленный доступ git archive: я отредактировал ответ, чтобы предложить альтернативу.
VonC
60
git archive --format=tar --remote=<repository URL> HEAD | tar xf -

взято отсюда

Джон Пенн
источник
2
--format=tarне нужно. "tar" - вывод по умолчанию, указывать не нужно.
VasiliNovikov
1
трубопроводов в tar xдостаточно
Jens Bannmann
43

вы можете создать неглубокий клон, чтобы получить только последние несколько ревизий:

 git clone --depth 1 git://url

затем либо просто удалите каталог .git, либо используйте его git archiveдля экспорта дерева.

вязать
источник
Как предотвратить эту ошибку, когда я обновляю ее, повторяя клон: «фатальный: путь назначения 'XYZ' уже существует и не является пустым каталогом».
Сохаил Си
1
@SohailSi: либо клонировать в новое место, либо удалить старый каталог. Возможно, вам лучше просто загрузить новые версии, если вы хотите обновить локальную копию.
knittl
3

Почему бы не выполнить клонирование, а затем удалить .gitкаталог, чтобы у вас была только пустая рабочая копия?

Изменить: Или на самом деле зачем вообще использовать клон? Это немного сбивает с толку, когда вы говорите, что хотите репозиторий git, но без .gitкаталога. Если вы имеете в виду, что вам просто нужна копия некоторого состояния дерева, почему бы не сделать это cp -Rв оболочке вместо клона git, а затем удалить его .git.

Андрей
источник
Спасибо за это. Файлы находятся в репозитории git. Я надеялся, что смогу направить пользователей Mac, чтобы получить копию репо в одной строке, не превращаясь в репозиторий GIT.
Дэн Розенстарк,
У вас не должно быть людей, напрямую получающих код из репозитория, если они не могут его использовать (т.е. не имеют репозитория Git).
альтернатива
@Amoss Выпустить тарбол, чтобы люди не хватали постоянно последний код?
альтернатива
1
@mathepic: а чтобы выпустить tarball, вам нужен способ получить чистую рабочую копию из репозитория - это именно тот вопрос, который был задан.
Эндрю
1
Прочитав ответ ниже, а затем немного погуглил, возник другой вопрос: stackoverflow.com/questions/160608/ ... Если вы посмотрите на использование git archive --remote, то он сделает именно то, что вы (и исходный плакат ) ищем. Изменить: это то, что Джон ответил ниже.
Эндрю
2

Похоже, вам просто нужна копия исходного кода. Если да, то почему бы просто не скопировать каталог и исключить каталог .git из копии?

ДжаредПар
источник
5
Вот что я спрашиваю: как это сделать с помощью git ... Я уже могу сказать, что нет встроенного способа сделать это из ответов, которые я получаю. Спасибо, в любом случае!
Дэн Розенстарк,
2

git checkout -f

Есть другой способ сделать это, отделив репо от рабочего дерева.

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

Мы сделаем две папки, одну для git и одну для рабочих файлов:

mkdir workingfiles
mkdir barerepo.git

инициализировать чистый репозиторий git:

cd barerepo.git
git --bare init 

Затем создайте перехватчик post-receive:

touch hooks/post-receive
chmod ug+x hooks/post-receive

Отредактируйте пост-прием в своем любимом редакторе:

GIT_WORK_TREE=/path/to/workingfiles git checkout -f
# optional stuff:
cd down/to/some/directory
[do some stuff]

Добавьте это как пульт:

git remote add myserver ssh://user@host:/path/to/barerepo.git

Теперь каждый раз, когда вы нажимаете на это голое репо, он проверяет рабочее дерево /workingfiles/. Но /workingfiles/сам по себе не находится под контролем версий; работает git statusв /workingfiles/выдаст ошибку fatal: Not a git repository (or any parent up to mount point /data). Это просто файлы.

В отличие от других решений, rm -r .gitкоманда не нужна, поэтому, если /workingfiles/есть другое репозиторий git, вам не нужно беспокоиться о том, что команда, используемая для удаления других файлов git репо.

Удар
источник
1
Согласовано. Здесь возможен перехват пост-получения на голом репо. +1
VonC
много работы, если вы просто пытаетесь получить файлы
Рейнб
Если вам нужны только файлы на регулярной основе, это не так уж и сложно.
Slam,
0

Нет необходимости использовать git в att, просто добавьте "/ zipball / master /" к URL-адресу ( источнику ).

Скачивание

Это решение наиболее близко к кнопке "Загрузить ZIP" на странице github. Одно из преимуществ - отсутствие каталога .git. Другой - он загружает один ZIP-файл вместо каждого файла по одному, и это может иметь огромное значение. Это можно сделать из командной строки Wget: wget -O "$(basename $REPO_URL)".zip "$REPO_URL"/zipball/master/. Единственная проблема в том, что в некоторых репозиториях может вообще не быть основной ветки. В этом случае «master» в URL следует заменить соответствующей веткой.

Распаковка

После того, как ZIP-файл существует, окончательное имя распакованного каталога все еще может быть довольно странным и неожиданным. Чтобы исправить это, этот скрипт может извлечь имя и mvдобавить к basenameURL-адресу. Финал script.shможет выглядеть примерно так (оценка за работу с пробелами):

#Script for downloading from github. If no BRANCH_NAME is given, default is "master".
#usage: script.sh URL [BRANCH_NAME]
__repo_name__='basename "$1"'
__repo_name__="$(eval $__repo_name__)"
__branch__="${2:-master}"
#downloading
if [ ! -e ./"$__repo_name__"".zip" ] ; then
wget -O "$__repo_name__"".zip" "$1""/zipball/$__branch__/"
fi
#unpacking and renaming
if [ ! -e ./"$__repo_name__" ] ; then
unzip "$__repo_name__"".zip" && 
__dir_name__="$(unzip -qql $__repo_name__.zip | sed -r '1 {s/([ ]+[^ ]+){3}\s+//;q}')" &&
rm "$__repo_name__"".zip" &&
mv "$__dir_name__" "$__repo_name__"
fi

Поддержание

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

Однако. Если исходный код довольно большой, и единственная возможность обновить - это загрузить и перестроить все, то (насколько мне известно) нет возможности обновить .gitкаталог без обновления , поэтому полное репо нужно загрузить снова. Тогда лучшее решение - как уже объяснил VonC - придерживаться неглубокой копии git clone --depth 1 $REPO_URL. Но что дальше? Чтобы «проверить наличие обновлений» см. Ссылку , а для обновления см. Отличный ответ в стиле вики .

Przemek
источник