Як перетворити оголене сховище 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.