Какая польза от репозиториев git bare?

На удаленной машине я создаю пустой репозиторий с помощью следующей команды:

git init --bare $HOME/bare/My-Repo

На моей локальной машине я клонирую репо (но не тот, который я создал на удаленной машине):

git clone ssh://something.com/My-Repo

На моем локальном компьютере в репозитории, который я только что клонировал, я создаю "ссылку" на вышеупомянутый пустой репозиторий, расположенный на удаленном компьютере:

git remote add my_remote ssh://remote.com/${USER}/bare/My-Repo

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

git config remote.my_remote /some/path/git-receive-pack
git config remote.my_remote /some/path/git-upload-pack

Теперь я могу перейти из локального репозитория в пустой репозиторий на удаленной машине:

git push my_remote master

Теперь идея заключается в том, что мы создадим еще один репозиторий на удаленной машине, который должен извлечь некоторый контент из чистого репозитория. Я создаю этот репозиторий, выполняя что-то вроде этого на удаленной машине:

some_script.sh $HOME/bare/My-Repo $HOME/My-Repo

Теперь я делаю некоторые изменения в $HOME/My-Repo на удаленной машине (обратите внимание, что это не пустой репозиторий), то я git add а также git commit и после этого я нажимаю:

git push origin my-dev-branch

В результате я нажимаю на пустой репозиторий (который находится на той же удаленной машине). После этого я иду на свою локальную машину и "беру" изменения с удаленной машины (из чистого репозитория):

git fetch my_remote
git checkout -b my-dev-branch my_remote/my-dev-branch
git fetch origin
git rebase origin/master

Итак, мои вопросы: зачем нам этот голый репозиторий? Почему мы не можем просто иметь один удаленный репозиторий и напрямую обмениваться контентом между локальным и удаленным репозиториями? Или, альтернативно, почему мы не можем просто rsync (или же scp) локальный репозиторий на и с удаленной машины?

ADDED

Вот почему я задаю вопрос, а не гуглю. Я погуглил свой вопрос, и первая ссылка здесь: http://www.saintsjd.com/2011/01/what-is-a-bare-git-repository/

Я прочитал там:

Репозитории, созданные с помощью команды git init, называются рабочими каталогами. В папке верхнего уровня репозитория вы найдете две вещи: подпапку.git со всей историей ревизий репозитория, связанной с git, рабочим деревом или извлеченными копиями файлов вашего проекта. Репозитории, созданные с помощью git init --bare, называются открытыми репозиториями. Они структурированы немного иначе, чем рабочие каталоги. Во-первых, они не содержат рабочей или извлеченной копии ваших исходных файлов. И, во-вторых, голые репозитории хранят историю изменений git вашего репозитория в корневой папке вашего репозитория, а не в подпапке.git. Обратите внимание... голые репозитории обычно получают расширение.git.

Итак, теперь, чтобы понять, что мне нужно знать:

  1. Что такое "история изменений"?
  2. Что такое "рабочее дерево"?
  3. Что такое "проверенные копии"?

И это только первый раздел. Я знаю, что ответом будет: пойди и прочитай учебник или введение в git. Ну, я сделал это. Первая проблема с этим состоит в том, что использование терминов является "круглым". Термин A выражается через термин B, а термин B - через термин A . Во-вторых, у меня нет времени читать книгу, чтобы найти ответ на свой вопрос. В-третьих, я на 100% уверен, что ответ на мой вопрос можно выразить простыми словами. Это на самом деле тривиально.

1 ответ

Решение

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

В вашем конкретном примере у вас есть локальный репозиторий Git, назовем его X, и два удаленных репозитория, пустой, назовем его B, и не голый, назовем его Y.

На данный момент, я надеюсь, вы видите, что X и Y могут быть где угодно. Оба они могут быть локальными или оба могут быть удаленными, на одном сервере с B. Не важно, где они находятся, важно то, что вы хотите синхронизировать между ними, и для этого вам нужен B, где-нибудь, где угодно, А твой вопрос почему?

Прежде всего, вам не нужен B в середине. Рекомендуется, и поведение по умолчанию поможет вам в этом направлении.

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

Чтобы демистифицировать голые репозитории, попробуйте это, чтобы увидеть разницу между голым и не голым репо:

$ cd /tmp/
$ git init --bare bare.git
Initialized empty Git repository in /private/tmp/bare.git/
$ git init regular
Initialized empty Git repository in /private/tmp/regular/.git/
$ diff -r bare.git/ regular/.git/
diff -r bare.git/config regular/.git/config
4c4,5
<   bare = true
---
>   bare = false
>   logallrefupdates = true

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

Вернемся к вопросу: почему рекомендуется иметь пустой репозиторий между двумя не голыми репозиториями, которые хотят синхронизировать друг с другом? По умолчанию Git запрещает отправку в не-пустое хранилище. Что если это не так? Если git push обновит содержание .git удаленного, что должно произойти с соответствующим рабочим деревом? Многие вопросы будут следовать:

  • Какова текущая ветвь рабочего дерева? Если толчок не изменил эту ветку, то все в порядке.
  • Что должно произойти, если толчок затронул текущую ветвь рабочего дерева? Должен ли Git обновить рабочее дерево?
    • Если рабочее дерево не является чистым, его нельзя безопасно обновить. Незавершенные изменения могут быть потеряны.
    • Даже если рабочее дерево чистое, могут возникнуть конфликты, если есть изменения в .gitignoreили если история ветки была переписана с принудительным нажатием.
    • Если мы не обновим рабочее дерево, оно будет не синхронизировано с репозиторием, поэтому git status сообщит об изменениях, которые не должны быть зафиксированы.

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

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