Такие сайты, как GitHub и GitLab, предоставляют способы объединения ветвей непосредственно в своем веб-интерфейсе. Учитывая, что на этих сайтах хранятся только голые репозитории, как они выполняют эти слияния? Можно ли то же самое сделать в командной строке в голом клоне? Я нашел это как возможный ответ, используя команды сантехники.
Поскольку GitHub является закрытым исходным кодом, мы не можем точно сказать, как их серверная часть обрабатывает операции слияния. Однако GitLab имеет открытый исходный код, и мы можем ознакомиться с деталями реализации, которые со временем изменились.
Как это делает GitLab
Сегодня большинство функций, связанных с git, которые отображаются в пользовательском интерфейсе, включая слияния git в GitLab, обрабатываются компонентом gitaly GitLab, который взаимодействует с физическим хранилищем репозиториев git. Он в основном использует свою зависимую библиотеку git2go для выполнения реальных операций git.
Присмотревшись повнимательнее к исходному коду для gitaly
, лучшая оценка, которую я могу сделать, заключается в том, что gitaly действительно широко использует рабочие деревья для операций git, в том числе для слияний. Репозитории и рабочие деревья обычно открываются и клонируются в каталоги "карантина", которые являются просто временными каталогами, созданными на лету, а рабочее дерево репозитория клонируется во временный каталог. (см. карантин.go#L40-58, вызванный из merge.go#L53).
как они выполняют эти слияния?
Итак, чтобы ответить на ваш вопрос: по крайней мере, в GitLab рабочие деревья используются для слияний (среди других операций) и не выполняются в пустых репозиториях. Вы просто не видите их, потому что временные каталоги используются до того, как они будут привязаны к фактическому пути к хранилищу.
Возможно, мы можем предположить, что GitHub делает что-то подобное, но это невозможно знать наверняка.
Можно ли это сделать?
Можно ли то же самое сделать в командной строке в голом клоне?
Вы указали на один пример, который, кажется, работает без проверки рабочего дерева? Но это работает, выписывая дерево (используя git write-tree
), который на практическом уровне, похоже, не имеет никаких преимуществ, скажем, перед клонированием из простого репо, проверкой рабочего дерева и использованием git
работает нормально. Для повышения производительности (предвидя возможные возражения) вы можете использовать временные файлы или какое-либо другое место, сопоставленное с памятью.
Я также не уверен, что связанного ответа будет достаточно для реализации различных стратегий слияния, используемых git merge
.
Так, может быть, по формальности? Ответ, который вы связали, кажется, хорошо отвечает на этот вопрос. На практическом уровне это было бы полезно, нет, мне так не кажется.
relativePath
в данном случае это временный каталог, который создается относительно репо на диске. Похоже, что он клонирует репозиторий, а затем переопределяет путь к объекту (quarantinedRepo.GitObjectDirectory = relativePath
) в quarantineRepo
объект, указывающий на tempdir (в отличие от того, что я предполагаю, является значением по умолчанию для местоположения объектов фактического репозитория, возвращенного методом клонирования).
git clone --shared
.