В чем заключается практическая разница между хранилищем Bare и Non-Bare?

213

Я читал о репозиториях «голые» и «не голые / по умолчанию» в Git. Я не смог понять (теоретически) достаточно хорошо о различиях между ними и о том, почему я должен «подтолкнуть» к пустому хранилищу. Вот сделка:

В настоящее время я единственный, кто работает над проектом на 3 разных компьютерах, но позже в него будет вовлечено больше людей, поэтому я использую Git для контроля версий. Я клонирую голое репо на всех компьютерах, и когда я заканчиваю свои модификации на одном из них, я фиксирую и помещаю изменения в голое репо. Из того, что я прочитал, пустой репозиторий НЕ имеет «рабочего дерева», поэтому, если я клонирую пустой репозиторий, у меня не будет «рабочего дерева».

Я предполагаю, что рабочее дерево хранит информацию о коммите, ветвях и т. Д. Из проекта. Это не появится в голом репо. Так что, мне кажется, лучше «протолкнуть» коммиты в репо с рабочим деревом.

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

Какие у вас методы для такой работы? Предложения?

AeroCross
источник
4
AeroCross, вы можете клонировать пустой репозиторий, чтобы создать не пустой репозиторий (то есть тот, который имеет рабочее пространство). Таким образом, используя git cloneвы можете свободно конвертировать между открытыми и открытыми хранилищами.
Дерек Махар
13
@AeroCross: дело не в конвертации; Неважно, что на другом конце. Если вы побежите, git clone --bareвы получите голое репо, а если вы побежите git clone, вы получите не голое. Каждый общедоступный проект, который вы когда-либо клонировали (например, на github), представляет собой пустой репозиторий на другом конце.
Каскабель
1
Джефроми, я исправлял точку зрения AeroCross: «Если я клонирую голое хранилище, у меня не будет« рабочего дерева »», так что это своего рода преобразование. И не каждый публичный проект должен быть голым хранилищем. Это просто типичный выбор, потому что пустой репозиторий более компактен, так как у него нет рабочего дерева (хотя он такой же компактный, как и любой репозиторий, у которого нет рабочего дерева).
Дерек Махар
2
@Derek: Но дело в том, что, как только он находит каталог .git, выборка совершенно не знает, свободен ли пульт или нет. Это не конвертируется. Он просто получает то, что ему нужно от пульта, и помещает его туда, куда он должен идти. Там нет ничего, чтобы преобразовать. Это то, что я пытался подчеркнуть в ОП. И я хорошо знаю, что публичные проекты не обязательно должны быть голыми, но поскольку люди не глупы, они по сути все. Я думаю, что я сделал приемлемое обобщение.
Каскабель
2
См. Push to non-bare-репозиторий, в котором приведено еще одно превосходное объяснение использования репозитория голой
Крейг МакКуин

Ответы:

95

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

~/Projects$ git clone --bare test bare
Initialized empty Git repository in /home/derek/Projects/bare/
~/Projects$ cd bare
~/Projects/bare$ git branch -a
* master
~/Projects/bare$ cd ..
~/Projects$ git clone test non-bare
Initialized empty Git repository in /home/derek/Projects/non-bare/.git/
~/Projects$ cd non-bare
~/Projects/non-bare$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

Со страницы руководства для git clone --bare:

Кроме того, заголовки веток на удаленном устройстве копируются непосредственно в соответствующие локальные заголовки ветвей, без сопоставления их с refs / remotes / origin /. При использовании этой опции не создаются ни ветви удаленного отслеживания, ни связанные переменные конфигурации.

Предположительно, когда он создает пустой репозиторий, Git предполагает, что пустой репозиторий будет служить репозиторием источника для нескольких удаленных пользователей, поэтому он не создает удаленный источник по умолчанию. Это означает, что basic git pullи git pushоперации не будут работать, поскольку Git предполагает, что без рабочей области вы не собираетесь вносить какие-либо изменения в пустой репозиторий:

~/Projects/bare$ git push
fatal: No destination configured to push to.
~/Projects/bare$ git pull
fatal: /usr/lib/git-core/git-pull cannot be used without a working tree.
~/Projects/bare$ 
Дерек Махар
источник
1
Да, я согласен с тем, что это, пожалуй, самое существенное различие между голыми и не голыми репозиториями Git. Тот факт, что в не-пустом хранилище есть рабочее пространство, а в пустом хранилище нет, является важным отличием, но git clone --no-checkoutможет также создать и не-пустое хранилище без файлов рабочей области.
Дерек Махар
10
Неполное хранилище также не обязательно имеет удаленное «происхождение» по умолчанию.
Mipadi
2
Вы можете создать Git-репозиторий просто с помощью git init, что создаст непроявленное хранилище без указания удаленного.
Mipadi
1
мипади, это правда, но это тоже не клон.
Дерек Махар
1
Это неверно Репозиторий будет иметь источник по умолчанию, если он был cloneотредактирован. Если оно было initотредактировано локально, оно не будет иметь такого происхождения. Это не имеет никакого отношения к тому, является ли это голым или нет.
Нуфал Ибрагим
62

Различие между «пустым» и «не пустым» Git-репозиториями является искусственным и вводящим в заблуждение, поскольку рабочая область не является частью репозитория, а для репозитория не требуется рабочая область. Строго говоря, репозиторий Git включает в себя те объекты, которые описывают состояние репозитория. Эти объекты могут существовать в любом каталоге, но обычно существуют в .gitкаталоге в каталоге верхнего уровня рабочей области. Рабочая область - это дерево каталогов, которое представляет определенный коммит в хранилище, но оно может существовать в любом каталоге или не существовать вообще. Переменная окружения $GIT_DIRсвязывает рабочее пространство с хранилищем, из которого оно происходит.

Команды Git git cloneи git initобе имеют опции, --bareкоторые создают репозитории без начальной рабочей области. К сожалению, Git объединяет две отдельные, но взаимосвязанные концепции рабочего пространства и хранилища, а затем использует запутанный термин « голый» для разделения двух идей.

Дерек Махар
источник
61

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

  • Используйте пустой репозиторий на удаленном сервере, чтобы несколько участников могли продвигать свою работу.
  • Non-bare - тот, у которого есть рабочее дерево, имеет смысл на локальной машине каждого участника вашего проекта.
Дипак Шарма
источник
60

5 лет опоздал, я знаю, но на самом деле никто не ответил на вопрос:

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

Какие у вас методы для такой работы? Предложения?

Цитировать прямо из книги Loeliger / MCullough (978-1-449-31638-9, p196 / 7):

Может показаться, что пустой репозиторий бесполезен, но его роль имеет решающее значение: служить авторитетным координационным центром для совместной разработки. Другие разработчики cloneи fetchиз чистого репозитория и pushобновлений к нему ... если вы создали репозиторий, в который вносятся pushизменения, разработчики должны быть пустыми. По сути, это частный случай более общей передовой практики, согласно которой опубликованное хранилище должно быть пустым.

EML
источник
19

Неполное хранилище просто имеет проверенное рабочее дерево. Рабочее дерево не хранит никакой информации о состоянии хранилища (ветви, теги и т. Д.); скорее, рабочее дерево - это просто представление реальных файлов в репо, которое позволяет вам работать (редактировать и т. д.) с файлами.

mipadi
источник
Так что это означает, что я могу добавить ветки, теги и т. Д. В пустой репозиторий, а затем вытащить его из чистого в рабочий репозиторий?
AeroCross
2
mipadi, в непокрытом хранилище может отсутствовать извлеченное дерево. Это тот случай, если вы создаете не-голое хранилище с git clone --no-checkout. В этом случае в репозитории non-bare есть место для рабочей области, но Git не извлекает файлы в эту рабочую область.
Дерек Махар
17

Чистое хранилище имеет преимущества в

  • уменьшенное использование диска
  • меньше проблем, связанных с удаленной передачей (поскольку нет рабочего дерева, которое могло бы быть синхронизировано или иметь конфликтующие изменения)
sehe
источник
3
Таким образом, пустой репозиторий - лучший / рекомендуемый способ работы с несколькими людьми, не имеющими доступа к своим репозиториям? (Вроде как SVN?)
AeroCross
2
АэроКросс, я бы сказал, что для этого сценария неплохой репозиторий.
Дерек Махар
12

Репозиторий Non голый позволяет (в ваше рабочее дерево) записывать изменения, создавая новые коммиты.

Голые репозитории изменяются только путем переноса изменений из других репозиториев.

Нитин
источник
10

Я, конечно, не Git "эксперт". Я какое-то время пользовался TortoiseGit и удивлялся, о чем идет речь, когда меня спрашивали, хочу ли я делать «голое» репо всякий раз, когда я его создаю. Я читал этот учебник: https://www.atlassian.com/git/tutorials/setting-up-a-repository/git-init, и в нем рассматривается проблема, но я все еще не совсем понял концепцию. Это очень помогло: http://bitflop.com/tutorials/git-bare-vs-non-bare-repositories.html . Теперь первый тоже имеет смысл!

Согласно этим источникам, в двух словах, «голое» репо используется на сервере, где вы хотите настроить точку распространения. Он не предназначен для использования на вашей локальной машине. Обычно вы отправляете коммиты с вашего локального компьютера в пустое хранилище на удаленном сервере, а вы и / или другие извлекаете из этого пустого хранилища на локальный компьютер. Таким образом, ваш репозиторий GitHub, Assembla и т. Д. Представляет собой пример, где создается «голое» репо. Вы бы сделали его самостоятельно, если бы настраивали собственный аналогичный «центр обмена».

BuvinJ
источник
ооооо теперь я
понял
9

Репозиторий Git по умолчанию / не пустой содержит два состояния:

  1. Снимок всех файлов в хранилище (это то , что «работает дерево» означает в Git жаргоне)
  2. История всех изменений , внесенных во все файлы , которые когда - либо были в хранилище (там , кажется, не быть кратким кусок Гит жаргоне , который включает в себя все это)

Снимок является то , что вы , вероятно , думаете , как ваш проект: ваш код файлы, файлы сборка, вспомогательные скрипты, и все , что вы версия с Git.

История является состоянием , которое позволяет проверить различные фиксации и получить полную картину того , что файлы в вашем хранилище выглядят, когда, выделяющая было добавлено. Он состоит из набора структур данных, которые являются внутренними для Git, с которыми вы, вероятно, никогда не взаимодействовали напрямую. Важно отметить, что история не просто хранит метаданные (например, «Пользователь U добавил столько строк в файл F в момент времени T как часть фиксации C»), но также хранит данные (например, «Пользователь U добавил эти точные строки в файл F»). ).

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

Голое хранилище представляет собой хранилище Git , который не имеет снимка. Это просто хранит историю.

Зачем тебе это? Что ж, если вы собираетесь взаимодействовать со своими файлами только с помощью Git (то есть вы не собираетесь редактировать свои файлы напрямую или использовать их для создания исполняемого файла), вы можете сэкономить место, не сохраняя снимок. В частности, если вы поддерживаете централизованную версию своего репо на каком-либо сервере (то есть вы в основном размещаете свой собственный GitHub), этот сервер, вероятно, должен иметь голое репо (вы все равно будете использовать неполное репо на своем сервере). локальный компьютер, хотя, так как вы, вероятно, захотите отредактировать ваш снимок).

Если вы хотите получить более подробное объяснение простых репозиториев и другого примера использования, я написал сообщение в блоге здесь: https://stegosaurusdormant.com/bare-git-repo/

Грег Оуэн
источник
4

Это не новый ответ, но он помог мне понять различные аспекты ответов выше (и это слишком много для комментария).

Используя Git Bash, просто попробуйте:

me@pc MINGW64 /c/Test
$ ls -al
total 16
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:35 ./
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:11 ../

me@pc MINGW64 /c/Test
$ git init
Initialized empty Git repository in C:/Test/.git/

me@pc MINGW64 /c/Test (master)
$ ls -al
total 20
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:35 ./
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:11 ../
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:35 .git/

me@pc MINGW64 /c/Test (master)
$ cd .git

me@pc MINGW64 /c/Test/.git (GIT_DIR!)
$ ls -al
total 15
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 ./
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 ../
-rw-r--r-- 1 myid 1049089 130 Apr  1 11:35 config
-rw-r--r-- 1 myid 1049089  73 Apr  1 11:35 description
-rw-r--r-- 1 myid 1049089  23 Apr  1 11:35 HEAD
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 hooks/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 info/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 objects/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 refs/

То же самое с git --bare:

me@pc MINGW64 /c/Test
$ ls -al
total 16
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:36 ./
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:11 ../

me@pc MINGW64 /c/Test
$ git init --bare
Initialized empty Git repository in C:/Test/

me@pc MINGW64 /c/Test (BARE:master)
$ ls -al
total 23
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 ./
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:11 ../
-rw-r--r-- 1 myid 1049089 104 Apr  1 11:36 config
-rw-r--r-- 1 myid 1049089  73 Apr  1 11:36 description
-rw-r--r-- 1 myid 1049089  23 Apr  1 11:36 HEAD
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 hooks/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 info/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 objects/
Christoph
источник
2

$ git help repository-layout

Git-репозиторий поставляется в двух вариантах:

  • каталог .git в корне рабочего дерева;
  • каталог .git, представляющий собой пустой репозиторий (то есть без собственного рабочего дерева), который обычно используется для обмена историями с другими пользователями путем загрузки в него и извлечения из него.
MichK
источник