Як перетворити оголене сховище git у звичайне (на місці)?


81

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

Я припускаю, що міг би його клонувати:

git clone -l <path_to_bare_repo> <new_normal_repo>

Однак мій репозиторій розміром близько 20 Гб, і у мене немає місця для його копіювання. Чи є спосіб перетворити оголене сховище на місце, щоб у підсумку вийшла робоча копія?


5
Неперевірене, але якщо ви переміщуєте вміст оголеного сховища в .gitкаталог і встановлюєте bareпараметр у конфігурі на false, він повинен поводитися як звичайне сховище, де ви можете просто git checkoutотримати свої файли.
Ноуфал Ібрагім,

Залежно від того, що ви маєте на увазі під "переглядом його вмісту", ви, мабуть, можете робити все, що завгодно, в git showgit cat-file
чистому

Дякую за підказку, корисно. Мені потрібен більше файлового менеджера, такого як досвід (редагував питання).
nyi

Якщо ваша файлова система підтримує жорсткі посилання, і ви клонуєте в ту саму файлову систему, clone -l не займає більше місця на диску, оскільки жорстко пов'язує всі об'єкти. Однак вам знадобиться місце для оплати, як зазначали інші.
Ніл Мейхью,

1
Якщо ваше голе сховище займає 20 ГБ дискового простору, скільки ще потрібно робочому дереву? У вас справді так багато місця?
ADTC

Відповіді:


113

Примітка : Я протестував це на дуже простому сховищі з 1 комітом. Двічі перевірити це, читати сторінки людини , і завжди буде радий , що ви створили резервну копію , перш ніж слідувати порадам ви знайшли на StackOverflow. (Ви робите резервну копію, так?)

Щоб перетворити --bareсховище на непростий:

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

Ці кроки йдуть у протилежному напрямку від цього питання , "git-convert normal to gore repository" - зокрема, зверніть увагу на цю відповідь , в якій зазначено, що наведені вище кроки (у, я припускаю, будь-якому напрямку) відрізняються від виконання a git-clone. Не впевнений, що це стосується вас, однак, але ви згадали git cloneу питанні.


2
Я все написав, але все одно, коли я натискаю файли, вони не відображаються. Що це може бути (я також переключив denyCurrentBranch на ігнорування)?
Рої

Дякую! Одного разу я прийшов на роботу і виявив, що моє головне репо - з якого я мав кілька робочих дерев в іншому місці - повідомляло, що воно "оголене". Всі інші робочі дерева були в порядку. Не мав уявлення, як стати ненадійним, але знайшов цю відповідь, і вона спрацювала чудово.
davidbak

17

У мене був дещо інший сценарій:

Рішення:

  • клонувати оголене репо в цьому вмісті, в .gitпапці:
    git clone --bare https://github.com/user/project .git
  • Позначте це як не оголене репо:
    git config --local --bool core.bare false
  • скинути індекс (інакше він вважає, що все було видалено, оскільки .git оголене репо не включає файл ' index'.)
    git reset HEAD -- .
    Це відновлює файл .git/index.

Я фактично перетворив оголене репо в неоголене, зберігаючи вміст, який я отримав раніше. Повний сценарій я використовував в протягом багатьох років включає в себе наступні етапи:

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 ) простіше.


Також варто зазначити, що якщо оголене сховище було створено на машині з різними закінченнями рядків, ви все одно можете побачити змінені файли навіть після виконання цих кроків. Я вважаю, що це нормально; git намагається виправити лінійні канали. Не знаю, чому.
Джуно Вудс

Отже, ви в основному клонували репозиторій GitHub як голий, перемикалися на неоголений, вручну розміщували весь файл із вашого "не-репо" та скидали індекс? Чим це відрізняється від простого клонування репо як не оголеного спочатку? Процес не голого клонування все одно перевірить усі файли. І якщо ви дійсно хочете, ви можете просто замінити перевірені файли файлами з вашого "не репо".
ADTC

Мета @ADTC - отримати .gitпідпапку в робочому дереві (яке ви знаєте, що це ваше репо), спочатку зроблене з архіву (не git). Я не міг перевірити не оголене репо, оскільки папка, в якій я робив замовлення, не порожня. Виконання неоголеного git clone --no-checkoutв підпапці змусило б мене перейти на .gitодин рівень вгору. Голий клон дозволив мені створити безпосередньо .gitпідпапку там, де я цього хотів. Ви можете побачити сценарій тут: github.com/VonC/compileEverything/blob/…
VonC

"Я не міг перевірити непростий репо, оскільки папка, в якій я робив замовлення, не порожня." Ви маєте на увазі, що у вас є не-git робоче дерево, яке містить зміни, які ще не зафіксовані, і ви маєте намір зробити коміт після того, як перетворили його на робоче дерево із підтримкою Git? Так, я думаю, це працює для такого випадку використання. Особисто я б клонував порожню папку і спочатку порівнював їх (за допомогою зовнішнього інструменту). Але це лише я.
ADTC

@ADTC Немає: У мене НЕ є "не-ГИТ робоче дерево , яке містить зміни , які ще не були зафіксовані». Я ні хочу нічого робити. Те , що я дійсно є точна робоча дерево репо: все вистачає його .git. Я отримую .gitнаскрізний клон, я перетворюю цю .gitпапку на неоголену і роблю, git resetщоб git зрозумів, що робоче дерево вже є. Це саме те, що робить github.com/VonC/compileEverything/blob/… .
VonC

11

Щоб спростити та поєднати інформацію у відповідях:

Є три відмінності, за якими голий репо відрізняється від звичайної папки .git:

  • У файлі конфігурації core.bare встановлено значення true
  • індексного файлу та робочого дерева не існує
  • значення за замовчуванням для віддаленого "джерела" не створюється

Отже, ви можете просто перенести своє оголене репо в папку .git нової папки,

mkdir clone
mv bare.git clone/.git

Змінити core.bare:

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

Додайте refspec за замовчуванням, щоб зробити git fetchі git pushвибрати ті самі значення за замовчуванням:

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

І згенеруйте файл індексу та робоче дерево:

git checkout master

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


10

Питання оригінального плаката полягає в тому, що у вас недостатньо місця, щоб робити речі простими способами. Для тих, хто має достатньо місця, відповідь набагато простіша:

git clone foo.git foo

Причиною того, що я хочу цього уникнути, є те, що репо стає великим, клон git іноді гине. Я хочу виконати rsync оголеного репо, а потім перетворити його.
Шрідхар Сарнобат

@SridharSarnobat, тоді розгляньте завдання, описані у прийнятій відповіді: stackoverflow.com/a/10637882/377270 - Я помістив цю однорядкову відповідь тут, щоб люди з достатньою кількістю вільного місця могли робити речі простим способом.
sarnold

6

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


1
Ви маєте рацію, але мені потрібно переглядати це зручніше (у файловому менеджері через ssh). Таким чином, мені доведеться жити зі збільшеним дисковим простором.
nyi

1
Насправді це справжня проблема (+1). Робочі дерева часто споживають до половини дискового простору; почасти тому, що історії git агресивно стискаються.
jpaugh

4

cd в голі репо і робити

  1. Або:
git config core.bare false
git reset --hard
  1. Або
git clone X.git X

(дасть вам регулярне репозиторій git, який називається X)


Це найпростіше рішення, і я можу підтвердити в 2019 році, що воно працює (перший підхід).
Шрідхар Сарнобат

Лише одна маленька примітка, яку я забув (застосовується до всіх відповідей): вам потрібно буде відредагувати файл конфігурації, коли ви вперше натиснете, щоб встановити віддалену URL-адресу.
Шрідхар Сарнобат

2

Якщо ви не проти працювати над різним робочим деревом, тоді

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

Зверніть увагу, це не клон.


Це чудово, не впевнений, чому це не вище в списку
Микола

0

Push-to-Deploy

Замість того, щоб перетворювати пусте дистанційне управління в стандартне сховище, ви можете використовувати сценарій після отримання в каталозі хуків, щоб розширити сховище в каталог розгортання.

Ось хороший приклад налаштування Push-to-Deploy

Для зручності посилання це приклад вмісту сценарію з наведеного вище посилання. Він буде розгортати лише натискання з гілки "master" у каталог із назвою "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}'"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.