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

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

Основным отличием, кажется, является:

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

  • в голом репозитории Git нет рабочей копии и папки (назовем ее repo.git) содержит фактические данные хранилища

18 ответов

Решение

Короче говоря: заменить содержимое 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 на новое место (см. ниже).

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

git clone --bare /path/to/repo

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

Я думаю, что следующая ссылка будет полезна

GitFaq: Как мне сделать существующий не-пустой репозиторий голым?

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

Если вы специально не хотите или не хотите вертеть биты в файловой системе, действительно просто создать пустую версию не пустого хранилища (упомянутое здесь в нескольких других постах). Это часть основной функциональности git:

git clone --bare reponame bare_reponame

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

git clone --mirror path_to_source_repository

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

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

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

git config --bool core.bare true

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

Я прочитал ответы и сделал это:

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

Просто читать

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. Несомненно, можно было бы заново изобрести колесо;-)

Вот то, что я считаю самым безопасным и простым. Здесь ничего не указано выше. Я просто хочу увидеть ответ, который показывает безопасную пошаговую процедуру. Вы запускаете одну папку из репозитория (репо), который хотите обнажить. Я принял соглашение, подразумеваемое выше, что голые папки репозитория имеют расширение.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

Вот небольшая функция 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 и никаких изменений в файловой системе не произойдет.

Методы, которые говорят об удалении файлов и обмана с перемещением каталога.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. Помните, что страницы руководства - ваш друг.

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

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

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

Вот определение чистогорепозитория из gitglossary:

Чистый репозиторий обычно представляет собой каталог с соответствующим именем с суффиксом.git, в котором нет локально извлеченной копии любого из файлов, находящихся под контролем версий. То есть все административные и управляющие файлы Git, которые обычно присутствуют в скрытом подкаталоге.git, вместо этого находятся непосредственно в каталоге repository.git, и никакие другие файлы не присутствуют и не извлекаются. Обычно издатели публичных репозиториев делают доступными голые репозитории.

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

Я хотел бы получить экспертное мнение или некоторые конкретные контрпримеры, однако кажется, что (после рывка в некотором исходном коде git, который я нашел) просто переход к файлу .git/configи установив основной атрибут обнажить к истинному, мерзавец позволит вам делать все, что вы хотите сделать в хранилище удалено. Т.е. следующие строки должны существовать в.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 и разобраться в результатах).

Я использовал следующий скрипт, чтобы прочитать текстовый файл со списком всех моих репозиториев 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

Первый, backup ваш существующий репо:

(a)  mkdir backup

(b)  cd backup

(c)  git clone non_bare_repo

Во-вторых, запустите следующее:

git clone --bare -l non_bare_repo new_bare_repo

Добавлено 2:
после написания ответа понял, что принятый ответ, скорее всего, приведет к тому же результату на моем ПК, если за ним последует git add *.

У меня исчезли файлы из рабочей папки (только остались), опять красиво и компактно:

      git switch --orphan some_new_branch_name 

Затем конвертируйте в голый, если хотите:

      git config --bool core.bare true

Таким образом сохраняется конфигурация, включая удаленную ссылку:

      $ git config --list
core.repositoryformatversion=0
core.filemode=true
core.bare=true
remote.origin.url=https://github.com/vmatare/thinkfan.git
remote.origin.fetch=+refs/*:refs/*
remote.origin.mirror=true

Добавлено:
В комментариях упоминается, что он не будет удалять «любые файлы, игнорируемые git», в этом случае их необходимо дополнительно удалить вручную (или сам репозиторий, который .gitподпапку переместить в другое место).

Примечания:
до core.bare trueнекоторые действия привели к ошибкам:

      $ git fetch --all
Fetching origin
fatal: Refusing to fetch into current branch refs/heads/devel of non-bare repository
error: Could not fetch origin

не были перечислены в выводе после этого. Для дальнейшего тестирования я сделал git checkout masterЯ получил файлы обратно и снова нет some_new_branch_nameна выходе git branch, так что я думаю новый orphanветка не будет добавлена ​​в репозиторий, если там не будет выполнена какая-то работа (и/или выполнены коммиты).

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

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)

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

ЕДИНСТВЕННАЯ разница между голым и не голым репозиторием git заключается в том, что у не голой версии есть рабочая копия. Основная причина, по которой вам нужно пустое хранилище, заключается в том, что если вы хотите сделать его доступным для третьей стороны, вы не можете работать над ним напрямую, поэтому в какой-то момент вам придется его клонировать, и в этот момент вы Вернемся к обычной версии рабочей копии.

При этом, чтобы конвертировать в голое репо, все, что вам нужно сделать, это убедиться, что у вас нет ожидающих коммитов, а затем просто:

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

Вот и все, голое репо.

Другие вопросы по тегам