Как конвертировать голый репозиторий git в обычный (на месте)?

У меня есть голый репозиторий git, но вам нужно получить доступ и просмотреть его содержимое поверх ssh (в файловом менеджере, например, в пользовательском режиме).

Я предполагаю, что могу клонировать его:

git clone -l <path_to_bare_repo> <new_normal_repo>

Однако мой репозиторий имеет размер около 20 ГБ, и у меня нет места для его дублирования. Есть ли способ конвертировать голый репозиторий на месте, чтобы в итоге получить рабочую копию?

Ответ 1

Примечание: я проверил это в очень простом репозитории с 1 коммитом. Дважды проверьте это, прочитайте справочные страницы и всегда будьте рады, что вы сделали резервную копию, прежде чем следовать советам, которые вы нашли в StackOverflow. (Вы делаете резервную копию, верно?)

Чтобы преобразовать репозиторий --bare в не-пустой:

  1. Создайте папку .git на верхнем уровне вашего хранилища.
  2. Переместите элементы управления хранилищем (HEAD branches config description hooks info objects refs и т.д.) В только что созданный .git.
  3. Запустите git config --local --bool core.bare false чтобы преобразовать локальный git-репозиторий в non-bare.
  4. (через комментарий Tamás Pap) После шага № 3 вы увидите, что вы находитесь на master филиале (или в зависимости от того, какая у вас основная ветвь), и все ваши файлы будут удалены, и удаление будет подготовлено. Это нормально. Просто вручную проверьте master или выполните git reset --hard, и все готово.
  5. (чтобы решить проблему, о которой сообщил Ройи) Отредактируйте файл .git/config добавив строку fetch = +refs/heads/*:refs/remotes/origin/* после url = <...> в разделе [remote "origin"]. В противном случае git fetch не увидит origin/master и другие ветки origin.

Эти шаги направлены в противоположном направлении от этого вопроса, "git-convert normal to bare repository" - в частности, обратите внимание на этот ответ, в котором говорится, что вышеуказанные шаги (я полагаю, в любом направлении) отличаются от выполнения git-clone, Не уверен, что это имеет отношение к вам, но вы упомянули git clone в этом вопросе.

Ответ 2

У меня был несколько иной сценарий:

Решение:

  • клонировать голый репо в этом контенте в директории .git:
    git clone --bare https://github.com/user/project .git
  • Отметьте его как не-обнаженное репо:
    git config --local --bool core.bare false
  • reset индекс (в противном случае он считает, что все было удалено, так как .git bare repo не включает файл 'index'.)
    git reset HEAD -- .
    Это восстанавливает .git/index.

Я фактически трансформировал голый репо в не-голый, сохраняя контент, который я ранее получил.
full script, который я использую в течение многих лет, включает в себя следующие шаги:

cd /path/to/current/worktree

# That creates a .git directly at the right place
git clone --bare /url/of/repo .git

# restore the link between the local repo and its upstream remote repo
git config --local --bool core.bare false
git config --local remote.origin.fetch +refs/heads/*:refs/remotes/origin/*
git fetch origin
git branch -u origin/master master

# reset the index (not the working tree)
git reset HEAD -- .

Но я верю принятое решение (с добавленным полезным git reset шагом ADTC) проще.

Ответ 3

Чтобы упростить и объединить информацию в ответах:

Есть три отличия, которые отличают репо от обычной папки .git:

  • core.bare имеет значение true в конфигурационном файле
  • индексный файл и рабочее дерево не существует
  • по умолчанию refspec для "источника" удаленного не генерируется

Таким образом, вы можете просто переместить ваш репозиторий в подпапку .git новой папки,

mkdir clone
mv bare.git clone/.git

Изменить core.bare:

cd clone
git config --local --bool core.bare false

Добавьте исходную ссылку по умолчанию, чтобы git fetch и git push выбирали те же значения по умолчанию, что и обычно:

git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'

И сгенерируйте индексный файл и рабочее дерево:

git checkout master

Я рекомендую git checkout а не git reset для генерации файлов, на случай, если они случайно набраны в неправильном месте.

Ответ 4

Если у вас мало дискового пространства, расширение рабочего дерева путем преобразования в обычный репозиторий будет проблемой, но вы можете просматривать содержимое голого репо без его преобразования. Используйте git cat-file -p <commit-sha> для любой фиксации, чтобы увидеть дерево, к которому оно относится. Используйте git cat-file -p <blob-sha>, чтобы увидеть содержимое файла, на которое ссылается blob. Используйте git show <sha>:path, где sha является либо фиксацией, либо деревом, чтобы увидеть содержимое blob по пути.

Ответ 5

Оригинальный вопрос о постели состоит в том, что у него недостаточно места, чтобы сделать что-то просто. Для тех, у кого достаточно места, ответ намного проще:

git clone foo.git foo

Ответ 6

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

git worktree add ../repo2
cd ..
git status # now works fine

Обратите внимание: это не клон.

Ответ 7

cd в голый репо и сделай

  1. Или:
git config core.bare false
git reset --hard
  1. или же
git clone X.git X

(даст вам регулярное Git-репо с именем X)

Ответ 8

Нажимай-Deploy

Вместо того, чтобы конвертировать пустой пульт дистанционного управления в стандартный репозиторий, вы можете использовать сценарий post-receive в каталоге hooks, чтобы развернуть репозиторий в каталог развертывания.

Вот хороший пример настройки Push-to-Deploy

Для простоты, это пример содержания скрипта из ссылки выше. Он будет развертывать только толчки из "главной" ветки в каталог с именем "deploy", который находится на том же уровне, что и родительский каталог репозитория:

#!/usr/bin/env ruby
# post-receive

# 1. Read STDIN (Format: "from_commit to_commit branch_name")
from, to, branch = ARGF.read.split " "

# 2. Only deploy if master branch was pushed
if (branch =~ /master$/) == nil
    puts "Received branch #{branch}, not deploying."
    exit
end

# 3. Copy files to deploy directory
deploy_to_dir = File.expand_path('../deploy')
'GIT_WORK_TREE="#{deploy_to_dir}" git checkout -f master'
puts "DEPLOY: master(#{to}) copied to '#{deploy_to_dir}'"