Як перетворити звичайне сховище Git в голое?


602

Як я можу перетворити "звичайний" сховище Git в голий?

Основна різниця, здається, полягає в:

  • у звичайному сховищі Git у вас є .gitпапка всередині сховища, що містить усі відповідні дані та всі інші файли, що складають вашу робочу копію

  • у голому сховищі Git немає робочої копії, а папка (назвемо її repo.git) містить фактичні дані сховища


16
Імовірно, це коротший метод:mv repo/.git repo.git; rm -rf repo
jameshfisher

Так, правда. Коли я писав запитання, це був лише фрагмент моєї історії, який я виконав іншу хвилину.
Болдевін

54
@eegg Використовуйте &&замість того, ;якщо mvне вдасться!

Відповіді:


609

Коротше кажучи: замініть вміст repoна вміст repo/.git, а потім скажіть сховищу, що він тепер є голим сховищем.

Для цього виконайте такі команди:

cd repo
mv .git ../repo.git # renaming just for clarity
cd ..
rm -fr repo
cd repo.git
git config --bool core.bare true

Зауважте, що це відрізняється від того, git clone --bareщоб робити нове місце (див. Нижче).


9
Дякую за підказку на core.bare. Тепер, погугливши цю опцію, я можу її підтвердити: kernel.org/pub/software/scm/git-core/docs/git-config.html
Boldewyn

14
Дякую! Мені це здається чистішим: mv repo / .git repo.git && rm -rf repo && cd repo.git && git config --bool core.bare true
JasonWoof

56
Це набагато складніше і тендітніше, ніж відповідь нижче ( git clone --bare /path/to/repo).
djd

7
Ця rmкоманда може знадобитися, * \.[!.]*а не *для видалення точкових файлів і точкових каталогів.
мінопрет

6
@Ciantic: Знову, як я вже пояснював у своєму коментарі вище, моя відповідь була дана 3 роки тому, але 5 місяців тому хтось змінив питання на щось зовсім інше. Жоден з відповідей на цій сторінці не буде мати ніякого сенсу більше. Ця послідовність команд була скопійована безпосередньо із запитання, я щойно додав два останні рядки.
Йорг W Міттаг

244

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

git clone --bare /path/to/repo

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


50
Неправильно, цей метод не є рівнозначним. Клон не зберігає параметри конфігурації, які можуть бути критично важливими для правильної роботи, наприклад, якщо ви використовуєте git-p4. Крім того, клон знищує віддалені дії. Знову ж таки, як git-p4, ви втрачаєте гілку p4 / master, коли клонуєте, тому вищенаведений підхід є кращим.
ноталієць

26
Але ви можете легко передати параметри конфігурації, скопіювавши відповідні частини конфігураційного файлу. Я б все-таки вважав цей метод більш чистим, ніж копіювання та перейменування файлів вручну.
Філіп

6
Це ідеально після міграції субверсії, оскільки у git-svn немає підтримки для --bare.
Кейо

11
Щоб уникнути конфлікту імен ---git clone --bare /path/to/repo.git /path/to/newbarerepo.git
raksja

Це працює до тих пір, поки ви не будете працювати git update-server-infoна голому репо після створення.
ACK_stoverflow

116

Я думаю, що наступне посилання було б корисним

GitFaq: Як я можу зробити наявне непрофільне сховище оголеним?

$ mv repo/.git repo.git
$ git --git-dir=repo.git config core.bare true
$ rm -rf repo

2
Так, саме це я шукав, дякую! Однак у їхній другій пропозиції ( git clone) є недоліки, про які згадував носаталій.
Болдевін

1
Документація, яку ви запропонували, продовжує говорити: "Більш безпечний метод - це дозволити Git обробляти всі внутрішні налаштування для вас, роблячи щось подібне ... git clone --bare -l <path_to_repos> <new_dir>"
dafunker

74

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

git clone --bare existing_repo_path bare_repo_path


6
Дивно, що найкраща відповідь далекого і далекого голосу має 0 голосів через> 4 місяці. "Не дуже-хороший, але небезпечний" прийнятий відповідь "- 200!
Stabledog

36
Зовсім не дивно - ця відповідь не відповідає тому, що було задано оригінальне запитання. Він не перетворює репо, він клонує, втрачаючи інформацію в процесі (наприклад, віддалені гілки).
GreenAsJade

15

Будь ласка, також розглянути можливість використання

git clone --mirror path_to_source_repository

З документації :

Налаштуйте дзеркало вихідного сховища. Звідси випливає - непогано. Порівняно з --bare, --mirror не тільки відображає локальні гілки джерела на локальні гілки цілі, він карта всіх реф (включаючи відділення віддаленого відстеження, примітки тощо) та встановлює конфігурацію refspec таким чином, що всі ці посилання перезаписані віддаленим оновленням git у цільовому сховищі.


Здається, що це найбільш стислий, повний і безпечний спосіб зробити те, що хоче ОП (проти справедливого clone). Я щось пропускаю? Було --mirrorвідносно недавнє доповнення?
Крейг Срібний

@CraigSilver: Ні, як я бачу в історії документації в такій формі --mirror, доступний з версії 1.7, тому вже досить довгий. Ви можете перевірити тут
Яцек Кравчик

7

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

git config --bool core.bare true

Не потрібно возитися з файлами, якщо ви не хочете залишати його в чистоті.


3
Це небезпечно, коли ви також хочете працювати над деревом роботи віддаленого репо. Можливо, ви рано чи пізно скасуєте зміни просто тому, що ваше віддалене робоче дерево та індекс не синхронізувались із сховищем. Я не рекомендую це рішення, якщо ви не точно знаєте , що ви робите.
Болдевін

Правда, не варто працювати на дереві віддаленого голого репо.
Slion

6

я прочитав відповіді, і я це зробив:

cd repos
mv .git repos.git
cd repos.git
git config --bool core.bare true # from another answer
cd ../
mv repos.git ../
cd ../
rm -rf repos/ # or delete using a file manager if you like

це залишить вміст repos/.gitголимrepos.git


4

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

(1) Backup, just in case.
    (a) > mkdir backup
    (b) > cd backup
    (c) > git clone ../repo
(2) Make it bare, then move it
    (a) > cd ../repo
    (b) > git config --bool core.bare true
    (c) > mv .git ../repo.git
(3) Confirm the bare repository works (optional, since we have a backup)
    (a) > cd ..
    (b) > mkdir test
    (c) > cd test
    (d) > git clone ../repo.git
(4) Clean up
    (a) > rm -Rf repo
    (b) (optional) > rm -Rf backup/repo
    (c) (optional) > rm -Rf test/repo

1
це насправді не набагато безпечніше, оскільки ви створили резервну копію за допомогою git clone. Резервне копіювання шляхом клонування призведе до втрати деяких конфігурацій, які в певних випадках можуть бути критичними для сховища.
Лежати Райан

Помічено. Єдині конфігурації, про які я коли-небудь піклувався, є глобальними для всіх моїх локальних сховищ.
sdesciencelover

4

Просто читайте

Pro Git Book: 4.2 Git на сервері - отримання Git на сервері

які зводяться до

$ git clone --bare my_project my_project.git
Cloning into bare repository 'my_project.git'...
done.

Потім поставте my_project.git на сервер

Що головним чином є, на яку відповідь намагався вказати відповідь №42 . Очевидно, можна було б винаходити колесо ;-)


Я не бачу, що додає ця відповідь, що не обговорювалося в довільній довжині в жодному з інших відповідей навколо (включаючи неприйнятий). Не могли б ви уточнити? (До речі: у книзі Pro Git сказано: «Це приблизно еквівалентно чомусь подібному ...» , і про цю точну грубу еквівалентність також вже йде мова.)
Boldewyn

3

Ось невелика функція BASH, яку ви можете додати до свого .bashrc або .profile в системі UNIX. Після додавання оболонки або перезавантажується або файл перезавантажується через виклик до source ~/.profileабо source ~/.bashrc.

function gitToBare() {
  if [ -d ".git" ]; then
    DIR="`pwd`"
    mv .git ..
    rm -fr *
    mv ../.git .
    mv .git/* .
    rmdir .git

    git config --bool core.bare true
    cd ..
    mv "${DIR}" "${DIR}.git"

    printf "[\x1b[32mSUCCESS\x1b[0m] Git repository converted to "
    printf "bare and renamed to\n  ${DIR}.git\n"
    cd "${DIR}.git"
  else
    printf "[\x1b[31mFAILURE\x1b[0m] Cannot find a .git directory\n"
  fi
}

Після виклику в каталозі, що містить каталог .git, він внесе відповідні зміни для перетворення сховища. Якщо під час виклику немає каталогу .git, з'явиться повідомлення про помилку, і зміни файлової системи не відбудуться.


1

Методи, які говорять про те, щоб видалити файли і змусити їх переміщувати каталог .git не є чистими і не використовують метод "git", щоб зробити щось, що повинно бути простим. Це найчистіший метод, який я знайшов для перетворення нормального репо в голий репо.

Перший клон / шлях / до / нормального / репо в голий репо під назвою repo.git

git clone --bare /path/to/normal/repo

Далі видаліть початок, який вказує на / шлях / до / нормальний / репо

cd repo.git
git remote rm origin

Нарешті ви можете видалити оригінал репо. Ви можете перейменувати repo.git на репо в цей момент, але стандартна умова для позначення сховища git - щось.git, тому я особисто залишу це так.

Після того, як ви все це зробите, ви можете клонувати нову голу репо (що фактично створює нормальне репо, а також те, як ви перетворили б його з голого в нормальне)

Звичайно, якщо у вас є інші вхідні потоки, ви захочете записати їх та оновити голий репо, щоб включити його. Але знову ж таки, все це можна зробити за допомогою команди git. Запам’ятайте сторінки чоловіка - ваш друг.


1
Ви турбувались читати інші відповіді? Особливо коментар @ jonescb та @ nosatalian до цього? Метод "git" такий: "Робіть якомога більше простих текстових файлів". Ви повинні почати досліджувати внутрішні .gitпапки. Дізнатися, як деталі поєднуються між собою, це дуже виграшно.
Boldewyn

1

У випадку, якщо у вас є сховище з кількома локальними відділеннями замовлення / refs / heads / * та кількома віддаленими відділеннями філій віддалене / походження / * І якщо ви хочете перетворити це у сховище BARE з усіма гілками в / refs / heads / *

Ви можете зробити наступне, щоб зберегти історію.

  1. створити оголене сховище
  2. CD в ​​локальне сховище, яке має місцеві відділення каси і віддалені відділення
  3. git push / шлях / до / голий / repo + refs / віддалений / походження / : refs / heads /

0

Я використовував наступний скрипт, щоб прочитати текстовий файл, у якому є список усіх моїх репостів SVN та перетворити їх у GIT, а пізніше використовувати git clone --bare для перетворення на голий git repo

#!/bin/bash
file="list.txt"
while IFS= read -r repo_name
do
 printf '%s\n' "$repo_name"
 sudo git svn clone --shared --preserve-empty-dirs --authors-file=users.txt file:///programs/svn/$repo_name 
 sudo git clone --bare /programs/git/$repo_name $repo_name.git
 sudo chown -R www-data:www-data $repo_name.git
 sudo rm -rf $repo_name
done <"$file"

list.txt має формат

repo1_name
repo2_name

а користувач.txt має формат

(no author) = Prince Rogers <prince.rogers.nelson@payesley.park.org>

www-data є користувачем веб-сервера Apache, необхідний дозвіл для перенесення змін через HTTP


0

Ось визначення голого сховища з gitglossary :

Оголене сховище зазвичай - це відповідний каталог з суфіксом .git, який не має локально перевіреної копії жодного з файлів під контролем редагування. Тобто, всі адміністративні та керуючі файли Git, які, як правило, присутні у прихованому .git підкаталозі, натомість є безпосередньо в каталозі repository.git, а інші файли відсутні та перевіряються. Зазвичай видавці загальнодоступних сховищ роблять доступними голі сховища.

Я приїхав сюди, тому що грав у "локальному сховищі" і хотів, щоб я міг робити все, що хотів, наче це було віддалене сховище. Я просто грав, намагаючись дізнатися про git. Я припускаю, що це ситуація для того, хто хоче прочитати цю відповідь.

Я хотів би отримати експертну думку чи деякі конкретні зустрічні приклади, однак, схоже, що (переглянувши якийсь вихідний код git, який я знайшов), просто перейдіть до файлу .git/configта встановіть атрибут core голим у true , git дозволить вам робити все, що завгодно ви хочете зробити віддалене сховище віддалено. Тобто такі рядки повинні існувати в .git/config:

[core]
    ...
    bare = true
...

(Це приблизно те, що git config --bool core.bare trueбуде робити команда , що, напевно, рекомендується вирішувати у більш складних ситуаціях)

Моє обгрунтування цього твердження полягає в тому, що у вихідному коді git, здається, є два різні способи тестування, чи репо-гола чи ні. Перший - перевірка глобальної змінної is_bare_repository_cfg. Це встановлюється під час виконання деякої фази налаштування та відображає значення, знайдені у .git/configфайлі. Інше - це функція is_bare_repository(). Ось визначення цієї функції:

int is_bare_repository(void)
{
    /* if core.bare is not 'false', let's see if there is a work tree */
    return is_bare_repository_cfg && !get_git_work_tree();
} 

Я не раз і не досвід , щоб сказати це з повною впевненістю, але, наскільки я міг би сказати , якщо у вас є bareнабір атрибутів для trueв .git/config, це завжди має повернутися 1. Решта функції, ймовірно, призначена для наступної ситуації:

  1. core.bare не визначено (тобто ні істинно, ні хибно)
  2. Немає робочого дерева (тобто підкаталог .git - це головний каталог)

Я буду експериментувати з цим, коли можу пізніше, але це, мабуть, вказує на те, що встановлення core.bare = true еквівалентно видаленню core.bare з конфігураційного файлу та правильному налаштуванню каталогів.

У будь-якому випадку, встановлення core.bare = true, безумовно, дозволить вам наштовхнутись на це, але я не впевнений, чи наявність файлів проекту призведе до того, що деякі інші операції зіпсуються. Це цікаво, і я вважаю, що повчальним є зайти до сховища та подивитися, що сталося на локальному рівні (тобто запустити git statusта мати сенс для результатів).


-1

По-перше, backupваше існуюче репо:

(a)  mkdir backup

(b)  cd backup

(c)  git clone non_bare_repo

По-друге, запустіть наступне:

git clone --bare -l non_bare_repo new_bare_repo

Для чого проміжний клон?
Stabledog

-4

Oneliner для виконання всіх перерахованих вище операцій:

for i in `ls -A .`; do if [ $i != ".git" ]; then rm -rf $i; fi; done; mv .git/* .; rm -rf .git; git config --bool core.bare true

(не звинувачуйте мене, якщо щось вибухає, і у вас не було резервного копіювання: P)


-9

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

ТІЛЬКИ різниця між голими та не голими сховищами git полягає в тому, що у неоголеної версії є робоча копія. Основна причина, коли вам знадобиться гола репо - це якщо ви хочете зробити це доступним для третьої сторони, ви не можете насправді працювати над цим безпосередньо, тому в якийсь момент вам доведеться клонувати її, в який момент ви знаходитесь повернутися до звичайної версії робочої копії.

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

rm -R * && mv .git/* . && rm -R .git

Там ви йдете, голі репо.


11
Це не зробить його досить голим. Спробуйте натиснути на нього. Вам також потрібно зробити git config core.bare trueце.
Antony Hatchkins

Я не спростував, але я просто хотів зазначити, що перша частина цієї відповіді, яка пояснює, чому ви хочете, щоб голе репо проти проти неоголеного було нормальним , хоча воно не містить достатньо технічних деталей, і, можливо, бути трохи неточним. Однак , для другої частини вашої відповіді, хоча ці команди налаштовують ваше репо бути голим, Ентоні має рацію , вам все одно потрібно встановити git config core.bare true, як у цій відповіді .
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.