Как преобразовать обычный Git-репозиторий в пустой?

603

Как я могу преобразовать «нормальный» Git-репозиторий в пустой?

Основное отличие, кажется, заключается в следующем:

  • в обычном Git-репозитории у вас есть .gitпапка внутри репозитория, содержащая все соответствующие данные и все другие файлы, составляющие вашу рабочую копию

  • в пустом Git-репозитории нет рабочей копии, а папка (назовем ее repo.git) содержит фактические данные репозитория

Boldewyn
источник
16
Предположительно это более короткий метод:mv repo/.git repo.git; rm -rf repo
jameshfisher
Да, верно. Когда я писал вопрос, это был просто фрагмент моей истории, который я выполнил на другой минуте.
Болдевин
54
@eegg Использовать &&вместо ;в случае mvнеудачи!

Ответы:

610

Короче говоря: замените содержимое 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).
DJ
7
Эта rmкоманда может потребоваться, * \.[!.]*а не *для удаления точечных файлов и точечных каталогов.
minopret
6
@Ciantic: Опять же, как я уже объяснил в своем комментарии выше, мой ответ был дан 3 года назад, но 5 месяцев назад кто-то отредактировал вопрос в нечто совершенно иное. Ни один из ответов на этой странице больше не будет иметь никакого смысла. Эта последовательность команд была непосредственно скопирована из вопроса, я только добавил последние две строки.
Jörg W Mittag
244

Ваш метод выглядит так, как будто он будет работать; Файловая структура чистого репозитория - это то, что находится внутри каталога .git. Но я не знаю, действительно ли какие-либо файлы были изменены, поэтому, если это не сработает, вы можете просто сделать

git clone --bare /path/to/repo

Вам, вероятно, придется сделать это в другом каталоге, чтобы избежать конфликта имен, а затем вы можете просто переместить его туда, куда вам нужно. И вам может понадобиться изменить файл конфигурации так, чтобы он указывал, где находится исходное хранилище.

jonescb
источник
50
Неправильно, этот метод не эквивалентен. Выполнение клона не сохраняет параметры конфигурации, которые могут иметь решающее значение для правильной работы, например, если вы используете git-p4. Кроме того, клон уничтожает пульты, опять же с чем-то вроде git-p4 вы теряете ветвь p4 / master при клонировании, поэтому предпочтительнее описанный выше подход.
Носаталян
26
Но вы можете легко перенести параметры конфигурации, скопировав соответствующие части файла конфигурации. Я бы по-прежнему считал этот метод более чистым, чем копирование и переименование файлов вручную.
Филипп
6
Это прекрасно после миграции subversion, так как git-svn не поддерживает --bare.
Keyo
11
Чтобы избежать конфликта имен ---git clone --bare /path/to/repo.git /path/to/newbarerepo.git
Ракся
Это работает до тех пор, пока вы запускаете 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
xhh
источник
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!
Конюшня
36
Совсем не удивительно - этот ответ не соответствует первоначальному вопросу. Он не конвертирует репо, он клонирует один, теряя информацию в процессе (например, удаленные филиалы).
GreenAsJade
15

Пожалуйста, также подумайте об использовании

git clone --mirror path_to_source_repository

Из документации :

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

Яцек Кравчик
источник
Похоже, что это самый лаконичный, полный и безопасный способ сделать то, что хочет ОП (а не просто clone). Я что-то пропустил? Было --mirrorотносительно недавнее дополнение?
Крейг Сильвер
@CraigSilver: Нет, как я вижу в истории документации, такая форма --mirrorдоступна с версии 1.7, так что уже довольно долго. Вы можете проверить здесь
Яцек Кравчик
7

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

git config --bool core.bare true

Не нужно возиться с файлами, если вы не хотите держать его в чистоте.

Slion
источник
3
Это опасно, когда вы также хотите работать с деревом работы удаленного репо. Скорее всего, рано или поздно вы отмените изменение просто потому, что ваше удаленное рабочее дерево и индекс не были синхронизированы с хранилищем. Я не рекомендую это решение, если вы не точно знаете , что вы делаете.
Болдевин
Правда, вы не должны работать на дереве удаленного репо.
Слион
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
sdesciencelover
источник
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 . Несомненно, можно было бы заново изобрести колесо ;-)

APOS
источник
Я не вижу, что добавляет этот ответ, который не обсуждался в произвольной форме ни в одном из других ответов (в том числе об отрицательных). Не могли бы вы уточнить? (Кстати: Pro Git Book говорит: «Это примерно эквивалентно чему-то вроде…» , и эта точная грубая эквивалентность также уже обсуждалась здесь.)
Болдевин
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, появится сообщение FAILURE и никаких изменений в файловой системе не произойдет.

nyteshade
источник
1

Методы, которые говорят об удалении файлов и обмана с перемещением каталога .git, не чисты и не используют метод "git" для выполнения чего-то, что должно быть простым. Это самый чистый метод, который я нашел для преобразования обычного репо в голое репо.

Первый клон / путь / к / нормальному / репо в голое репо с именем repo.git

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

Затем удалите источник, который указывает на / path / to / normal / repo

cd repo.git
git remote rm origin

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

После того, как вы все это сделали, вы можете клонировать свое новое голое репо (которое фактически создает нормальное репо, а также то, как вы бы конвертировали его из голого в обычное)

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

Krux
источник
1
Вы удосужились прочитать другие ответы? Особенно комментарии @ jonescb и @ nosatalian к нему? Метод «git» таков: «Делайте как можно больше с простыми текстовыми файлами». Вы должны начать исследовать внутреннюю часть .gitпапки. Очень полезно учиться тому, как части сочетаются друг с другом.
Болдевин
1

Если у вас есть хранилище с несколькими локальными извлеченными ветвями / refs /head / * и несколькими удаленными ветками удаленных веток / origin / * И если вы хотите преобразовать это в хранилище BARE со всеми ветками в / refs /head / *

Вы можете сделать следующее, чтобы сохранить историю.

  1. создать голое хранилище
  2. Перейдите в локальный репозиторий, в котором есть локальные извлеченные ветви и удаленные ветви.
  3. git push / path / to / bare / repo + refs / remotes / origin / : refs / heads /
Сентил А Кумар
источник
0

Я использовал следующий скрипт, чтобы прочитать текстовый файл со списком всех моих репозиториев SVN и преобразовать их в GIT, а затем использовать git clone --bare для конвертации в голое репозиторий git.

#!/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

и users.txt имеет формат

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

www-data - пользователь веб-сервера Apache, необходимо разрешение для изменения HTTP

Педро Висенте
источник
0

Вот определение пустого хранилища из gitglossary :

Пустой репозиторий обычно представляет собой каталог с соответствующим именем и суффиксом .git, который не имеет локально извлеченной копии ни одного из файлов, находящихся под контролем ревизии. То есть все административные и управляющие файлы Git, которые обычно присутствуют в скрытом подкаталоге .git, вместо этого непосредственно присутствуют в каталоге repository.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атрибут truein .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
Шакс
источник
Для чего нужен промежуточный клон?
Конюшня
-4

Онелинер для выполнения всех вышеперечисленных операций:

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так же.
Энтони Хэтчкинс
Я не понизил голос, но я просто хотел отметить, что первая часть этого ответа, которая объясняет, почему вы хотели бы, чтобы репо было голым, а не голым, была в порядке , хотя она не содержит достаточно технических деталей, и может быть немного неточным. Однако , для 2-й части вашего ответа, хотя эти команды настраивают репо, чтобы быть пустым, Энтони прав , вам все равно нужно установить git config core.bare true, как в этом ответе .