Как клонировать репозиторий git с определенной ревизией / набором изменений?
Как я могу клонировать git-репозиторий с определенной ревизией, как я обычно делаю в Mercurial:
hg clone -r 3 /path/to/repository
21 ответ
ОБНОВЛЕНИЕ 2 Начиная с Git 2.5.0, описанная ниже функция может быть включена на стороне сервера с помощью переменной конфигурации uploadpack.allowReachableSHA1InWant
здесь запрос функции GitHub и фиксация GitHub, включающая эту функцию. Обратите внимание, что некоторые серверы Git активируют эту опцию по умолчанию, например, Bitbucket Server включил ее с версии 5.5+. Посмотрите этот ответ на Stackexchange, чтобы узнать, как активировать опцию конфигурации.
ОБНОВЛЕНИЕ 1 Для версий Git 1.7 < v < 2.5
используйте git clone и git reset, как описано в ответе Вайбхава Баджпаи
Если вы не хотите получать полный репозиторий, вам, вероятно, не следует использовать clone
, Вы всегда можете просто использовать выборку, чтобы выбрать ветку, которую хотите получить. Я не эксперт по рт, поэтому я не знаю деталей -r
но в Git вы можете сделать что-то вроде этого.
# make a new blank repository in the current directory
git init
# add a remote
git remote add origin url://to/source/repository
# fetch a commit (or branch or tag) of interest
# Note: the full history up to this commit will be retrieved unless
# you limit it with '--depth=...' or '--shallow-since=...'
git fetch origin <sha1-of-commit-of-interest>
# reset this repository's master branch to the commit of interest
git reset --hard FETCH_HEAD
$ git clone $URL
$ cd $PROJECT_NAME
$ git reset --hard $SHA1
Чтобы снова вернуться к самой последней фиксации
$ git pull
Для клонирования только одного отдельного коммита в определенной ветви или теге используйте:
git clone --depth=1 --branch NAME https://github.com/your/repo.git
К несчастью, NAME
может быть только именем ветви или именем тега (но не коммитом SHA).
Опустить --depth
Отметить, чтобы загрузить всю историю, а затем оформить эту ветку или тег:
git clone --branch NAME https://github.com/your/repo.git
Это работает с последней версией Git (я сделал это с версией 2.18.0
).
Клонирование репозитория git удачно клонирует весь репозиторий: не существует способа выбрать только одну ревизию для клонирования. Однако, как только вы выполните git clone
, вы можете оформить заказ, выполнив checkout <rev>
,
Вы можете использовать просто git checkout <commit hash>
в этой последовательности
bash
git clone [URLTORepository]
git checkout [commithash]
Хеш коммита выглядит следующим образом: "45ef55ac20ce2389c9180658fdba35f4a663d204"
Если вы имеете в виду, что хотите получить все от начала до определенного момента, ответ Чарльза Бейли идеален. Если вы хотите сделать обратное и получить подмножество истории, начиная с текущей даты, вы можете использовать git clone --depth [N]
где N - это количество оборотов истории, которые вы хотите. Тем не мение:
--depth
Создайте неглубокий клон с историей, усеченной до указанного количества ревизий. Мелкий репозиторий имеет ряд ограничений (вы не можете клонировать или извлекать из него, ни выдвигать из него, ни в него), но он подходит, если вас интересует только недавняя история большого проекта с длинной историей, и вы хотите отправить исправления в виде исправлений.
Просто подвести итог (git v. 1.7.2.1):
- регулярно
git clone
где вы хотите репо (получает все на сегодняшний день - я знаю, не то, что нужно, мы добираемся туда) git checkout <sha1 rev>
вы хотитеgit reset --hard
git checkout -b master
TL;DR - Просто создайте тег в исходном репозитории против коммита, который вы хотите клонировать, и используйте тег в команде fetch. Вы можете удалить метку из исходного репо позже, чтобы очистить.
Ну, это 2014 год, и похоже, что принятый ответ Чарльза Бэйли от 2010 года к настоящему времени действительно устарел, и большинство (все?) Других ответов связаны с клонированием, которого многие люди надеются избежать.
Следующее решение позволяет достичь того, что ищет OP и многие другие, - это способ создать копию репозитория, включая историю, но только до определенного коммита.
Вот команды, которые я использовал с git версии 2.1.2 для клонирования локального репо (то есть репозитория в другом каталоге) до определенного момента:
# in the source repository, create a tag against the commit you want to check out
git tag -m "Temporary tag" tmptag <sha1>
# create a new directory and change into that directory
cd somewhere_else;mkdir newdir;cd newdir
# ...and create a new repository
git init
# add the source repository as a remote (this can be a URL or a directory)
git remote add origin /path/to/original/repo
# fetch the tag, which will include the entire repo and history up to that point
git fetch origin refs/tags/tmptag
# reset the head of the repository
git reset --hard FETCH_HEAD
# you can now change back to the original repository and remove the temporary tag
cd original_repo
git tag -d tmptag
Надеемся, что это решение будет работать еще несколько лет!:-)
Не нужно скачивать всю историю, и не нужно звонить
git init
:
git clone --depth=1 URL
git fetch --depth=1 origin SHA1
git checkout SHA1
git branch -D @{-1} # if you want to tidy up the fetched branch
Недостаток этого, на ответ CB Baileys, заключается в том , что вы все равно загрузите 1 ненужную версию. Но технически это
git clone
(чего хочет ОП), и это не заставляет вас загружать всю историю какой-то ветки.
Мне удалось сделать это с помощью параметра git clone --config, о котором я узнал из этого ответа: /questions/19945097/pochemu-git-clone-ne-prinimaet-refspec/19945101#19945101
В моем сценарии используется разреженная проверка в конвейере Azure DevOps, где мне нужно клонировать репо, используя хеш фиксации, а не имя ветки. Команда clone не принимает хеш фиксации в качестве параметра. Обходной путь - установить переменную конфигурации (-c), содержащую refspec, потому что эта refspec может использовать хэш фиксации вместо имени ветки:
git clone -c remote.origin.fetch=+<commit hash>:refs/remotes/origin/<commit hash> <repo_url> --no-checkout --progress --depth 1
git sparse-checkout init --cone
git sparse-checkout set <file list>
git checkout <commit hash>
Использование 2 из приведенных выше ответов (" Как клонировать git-репозиторий с определенной ревизией / набором изменений?" И " Как клонировать git-репозиторий с определенной ревизией / changeset-кодом ?") Помогло мне найти определитель. Если вы хотите клонировать до какой-либо точки, то эта точка должна быть тегом / ветвью, а не просто SHA или FETCH_HEAD запутывается. Следуя набору git fetch, если вы используете имя ветви или тега, вы получите ответ, если вы просто используете SHA-1, вы не получите ответ.
Вот что я сделал:- создать полноценный рабочий клон полного репо из фактического источника
cd <path to create repo>
git clone git@<our gitlab server>:ui-developers/ui.git
Затем создайте местную ветку, в точке, которая интересна
git checkout 2050c8829c67f04b0db81e6247bb589c950afb14
git checkout -b origin_point
Затем создайте мое новое пустое хранилище с моей локальной копией в качестве источника
cd <path to create repo>
mkdir reduced-repo
cd reduced-repo
git init
git remote add local_copy <path to create repo>/ui
git fetch local_copy origin_point
В этот момент я получил этот ответ. Я отмечаю это, потому что если вы используете SHA-1 вместо ветки выше, ничего не происходит, поэтому ответ означает, что он работал
/ var/www/html/ui-hacking$ git fetch local_copy origin_point Удаленный: Подсчет объектов: 45493, сделано. Удаленный: Сжатие объектов: 100% (15928/15928), сделано. удаленный: всего 45493 (дельта 27508), повторно используется 45387 (дельта 27463) Получающие объекты: 100% (45493/45493), 53,64 МиБ | 50,59 МБ / с, готово. Разрешение дельт: 100% (27508/27508), сделано. От /var/www/html/ui * точка отправления ветви -> FETCH_HEAD * [новая ветвь] origin_point -> origin/origin_point
Теперь в моем случае мне нужно было вернуть это обратно на gitlab, как свежий репо, поэтому я сделал
git remote add origin git@<our gitlab server>:ui-developers/new-ui.git
Это означало, что я мог восстановить свое хранилище с origin_point, используя git --git-dir=../ui/.git format-patch -k -1 --stdout <sha1> | git am -3 -k
чтобы вишня забрать, а затем использовать git push origin
загрузить всю партию обратно в ее новый дом.
Надеюсь, что это помогает кому-то
Лично мой любимый способ клонирования одного коммита.
mkdir repo && cd repo && git init
git remote add origin <url>
git fetch --depth 1 --no-tags --no-write-fetch-head origin tag <tag>
git branch master <tag>
git checkout
Чтобы избежать состояния отсоединенного заголовка, мы устанавливаем нашу ветку по умолчанию (в данном случае master) так, чтобы она указывала на наш тег/commit.
Что делает этот метод лучше, на мой взгляд, так это то, что он действительно извлекает только один тег. Мы также избегаем создания бесполезного FETCH_HEAD в качестве
Альтернатива
git config --add remote.origin.fetch 'refs/tags/*:refs/tags/*'
Теперь наша операция выборки становится
git fetch --depth 1 --no-write-fetch-head origin <tag>
Другие перечисленные методы, по моему опыту, загружают один коммит, а также все теги, связанные с этим конкретным коммитом. Например, проверьте любой из исходных репозиториев Google с помощью
Моя версия была комбинацией принятых и наиболее одобренных ответов. Но это немного отличается, потому что все используют SHA1, но никто не говорит вам, как его получить
$ git init
$ git remote add <remote_url>
$ git fetch --all
теперь вы можете видеть все ветки и коммиты
$ git branch -a
$ git log remotes/origin/master <-- or any other branch
Наконец вы знаете SHA1 желаемого коммита
git reset --hard <sha1>
# clone special tag/branch without history
git clone --branch=<tag/branch> --depth=1 <repository>
# clone special revision with minimal histories
git clone --branch <branch> <repository> --shallow-since=yyyy-MM-ddTHH:mm:ss # get the commit time
cd <dir>
git reset --hard <revision>
вы не можете получить ревизию без истории, если не установлен uploadpack.allowReachableSHA1InWant=true
на стороне сервера, в то время как вы можете создать для него тег и вместо этого клонировать специальный тег.
git clone https://github.com/ORGANIZATION/repository.git
(клонировать хранилище)
cd repository (navigate to the repository)
git fetch origin 2600f4f928773d79164964137d514b85400b09b2
git checkout FETCH_HEAD
Я бы предложил, как описано ниже.
Следующее дано в других ответах.
- Клонируйте весь репозиторий, затем
git reset --hard $SHA1
чтобы перейти к конкретному коммиту, заданному этим хэшем. (Вайбхав Баджпай) - чтобы получить только последний коммит в конкретной ветке и ничего больше (ни истории, ни других веток) (Питер Ковач)
- чтобы получить всю историю (желаемой ветки И других веток) и указать последний коммит нужной ветки (Питер Ковач)
Однако они, похоже, не совсем соответствуют тому, о чем задается вопрос, по следующим причинам (соответствующим 3 предложениям выше):
- Клонирует весь репозиторий, а не только нужную ветку; Чтобы полный сброс работал, предполагается, что желаемый коммит находится в ветке default/master.
- Получается только последний коммит в нужной ветке. История нужной ветки не получена.
- Получена структура/история фиксации всего дерева (включая другие ветки), что может быть больше, чем требует вопрос.
Я бы предложил этоgit clone --single-branch --branch NAME https://github.com/your/repo.git
обеспечивает наиболее подходящий ответ: получена только вся история одной ветки, а указатель HEAD указывает на последний коммит (мы видим его как прямую линию с HEAD, указывающим на коммит вверху/на кончике), тогда как:
- с
git clone --depth=1 --branch NAME https://github.com/your/repo.git
затем показывает только кончик ветки - с
git clone --branch NAME https://github.com/your/repo.git
затемgit log --all --graph
показывает древовидную структуру с желаемой ветвью и другими ветвями, ответвляющимися в разное время от других коммитов.
Все вышеперечисленное было протестировано с помощью git версии 2.24.3; я это читал--single-branch
был добавлен в git версии 1.7.10.
Это просто. Вы просто должны установить восходящий поток для текущей ветви
$ git clone repo
$ git checkout -b newbranch
$ git branch --set-upstream-to=origin/branch newbranch
$ git pull
Это все
Я использую этот фрагмент с GNU make, чтобы закрыть любой тег ревизии, ветку или хэш
он был протестирован на git версии 2.17.1
${dir}:
mkdir -p ${@D}
git clone --recursive --depth 1 --branch ${revison} ${url} ${@} \
|| git clone --recursive --branch ${revison} ${url} ${@} \
|| git clone ${url} ${@}
cd ${@} && git reset --hard ${revison}
ls $@
mkdir linux-4.3.20151106
cd linux-4.3.20151106/
git init
git fetch git@github.com:torvalds/linux.git 9154301a47b33bdc273d8254c407792524367558
error: unknown option `no-write-fetch-head'
usage: git fetch [<options>] [<repository> [<refspec>...]] or: git fetch [<options>] <group>
or: git fetch --multiple [<options>] [(<repository> | <group>)...] or: git fetch --all [<options>]
git --version
git version 2.17.1
export https_proxy=http://192.168.1.3:1080;export http_proxy=http://192.168.1.3:1080
add-apt-repository ppa:git-core/ppa
apt update
apt-get install --only-upgrade git
git --version
git version 2.38.0
git fetch git@github.com:torvalds/linux.git 9154301a47b33bdc273d8254c407792524367558 --no-write-fetch-head --depth=1
remote: Enumerating objects: 54692, done.
remote: Counting objects: 100% (54692/54692), done.
remote: Compressing objects: 100% (50960/50960), done.
remote: Total 54692 (delta 3828), reused 29210 (delta 2966), pack-reused 0
Receiving objects: 100% (54692/54692), 147.35 MiB | 2.85 MiB/s, done.
Resolving deltas: 100% (3828/3828), done.
git branch master 9154301a47b33bdc273d8254c407792524367558
git checkout
Для отдельных файлов и когда известен номер фиксации, можно использовать wget onliner:
wget https://raw.githubusercontent.com/torvalds/linux/896066ee1cf4d653057dac4e952f49c96ad16fa7/README
git clone -o <sha1-of-the-commit> <repository-url> <local-dir-name>
git
использует слово origin
вместо общеизвестных revision
Ниже приведен фрагмент из руководства $ git help clone
--origin <name>, -o <name>
Instead of using the remote name origin to keep track of the upstream repository, use <name>.