Git — несколько решений Visual Studio в одном репозитории

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

У меня появилась задача — я хотел опубликовать на GitHub исходный код из одной своей статьи, чтобы пользователи могли его скачивать. Проблема заключалась в том, что исходный код для одной статьи состоял из четырёх решений Visual Studio на C#. Я не хотел мерджить решения в одно, к тому же это было бы глупо, ведь эти решения VS содержали проект с одинаковым названием, который являлся эволюцией кода, объясняемого мной в статье. Я хотел, чтобы пользователь смог получить весь исходный код из статьи в одном клоне. Структура папок выглядит так:


Я открыл VS2022 и оказался в тупике. В VS2022 один репозиторий Git должен соответствовать одному решению VS. А у меня было несколько решений VS на C#, которые мне нужно было упаковать в один репозиторий. И что теперь делать?


1. Проверяем технологию: Git Submodule или Git Subtree


Я подумал, что мне поможет часть технологии Git, например, Submodule или Subtree. Однако после их тщательного изучения оказалось, что они не предназначены для этой задачи. Я не хотел делиться кодом библиотеки и получать всё с GitHub за один раз. Мне не удалось найти, как в Git создать «рабочее пространство», содержащее несколько репозиториев и обрабатываемое как один с точки зрения «git clone».

2. Решение — создание единого репозитория в SourceTree


Я решил, что лучше всего будет создать репозиторий Git в папке более высокого уровня, содержащей все четыре решения. Таким образом мне удастся хранить четыре решения в одном репозитории Git. Я сразу понял, что у меня будут ветки для репозитория, а не для каждого решения VS.

▍ 2.1. Создание репозитория


Я изучил опции Git в VS2022 и понял, что они ограничены, поэтому мне придётся использовать другой инструмент Git. Для создания репозитория папки высокого уровня я решил воспользоваться Sourcetree.


Пока коммиты выполнять нельзя! Сначала нам нужно настроить файл .gitignore. Если не настроить .gitignore, то в репозиторий будут сохраняться все файлы проекта, в том числе двоичные файлы и промежуточные файлы сборок, а нам этого не нужно.

▍ 2.2. Настраиваем .gitignore


Для эмуляции работы VS2022 я скопировал в корень моего репозитория два файла, сгенерированных VS2022: файлы .gitignore и .gitattributes, которые были созданы в другом проекте на C#, а затем закоммитил их.


Мы делаем это вручную, поскольку не используем VS2022 для создания репозитория Git; в противном случае VS2022 автоматически создал бы файл .gitignore, соответствующий выбранному типу проекта. Так как мы взяли на себя ответственность по ручному созданию репозитория в SourceTree, именно мы должны создать правильный файл .gitignore.

▍ 2.3. Коммиты файлов решений VS на C#


Затем я закоммитил все файлы решений Visual Studio в репозиторий. Так как .gitignore настроен, коммит будет игнорировать двоичные файлы и тому подобное.



▍ 2.4. Создание репозитория GitHub


Далее я создал удалённый аккаунт репозитория на GitHub и запушил файлы.


Можно просмотреть репозиторий на удалённой стороне и убедиться, что в него не выполнен коммит двоичных файлов или других файлов проекта. Если это произошло, значит, что-то не так с файлом .gitignore.

▍ 2.5. Мерджинг веток, которые невозможно смерджить


Проблема, которая возникла у меня сейчас, но, я уверен, возникнет многократно у меня и других людей, в том, что в конечном итоге у меня получились две ветки: main и master. Ветку main по умолчанию создаёт GitHub, в ней находится файл readme. Ветку master по умолчанию создаёт SourceTree, и в ней находится мой код (четыре решения VS).


Нам не нужны здесь две ветки, поэтому давайте смерджим их и избавимся от одной. Сохраним стандартную ветку main GitHub и удалим master.

Но при попытке слияния этих двух веток возникает проблема:


Это приводит к ошибке: fatal: refusing to merge unrelated histories.

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

В [1] написано, что эту проблему нельзя решить через GUI SourceTree. Значит, нам нужно выполнить команды командной строки Git в GitBash. Объяснение проблемы и инструкции приведены в [2].

Нужно выполнить git merge <branch-name> --allow-unrelated-histories.

Итак, можно открыть GitBash из SourceTree (кнопка Terminal), и исполнить команду. Вам будет предложено ввести комментарий к коммиту в отдельном текстовом редакторе. Затем продолжится мерджинг.


И вот как будут выглядеть слитые ветки:


Далее запушим изменения в GitHub и проверим, что в ветке main теперь находятся все наши файлы:


▍ 2.6. Удаление ненужной ветки


Теперь можно удалить ветку master локально в SourceTree и удалённо в GitHub. Вот как всё выглядит. История веток сохранилась, но в ней нет ветки master:




3. Проверка решения в VS2022


Далее нужно проверить, как всё выглядит на стороне VS2022. Сначала получим URL клонирования:


Затем клонируем репозиторий в VS2022.


И вот что мы получили: все четыре решения одновременно.


Нажав на одно из решений, мы перейдём к нему:


Нажав на кнопку выше, мы можем перейти к просмотру всех четырёх решений.


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

4. Заключение


Большинство моих проектов ведётся в TFS, поэтому я был поражён, насколько просто победить VS2022 простой идеей о помещении нескольких решений в один репозиторий Git. Без внешнего инструмента наподобие SourceTree или командной строки GitBash было бы невозможно это сделать.

Насчёт Git я подумал следующее: разве это не опенсорсный проект? Нельзя ли дополнить его концепцией «рабочего пространства», которое сможет содержать несколько репозиториев Git? Это позволило бы избежать неприятной ситуации, в которой все четыре решения находятся в одной ветке. Если у вас есть время изучить этот вопрос, то рекомендую посмотреть ссылки на сообщество Git [3] и [4].

5. Ссылки


  • [1] https://community.atlassian.com/t5/Sourcetree-questions/Sourcetree-error-when-trying-to-pull-from-repository/qaq-p/766163
  • [2] https://stackoverflow.com/questions/37937984/git-refusing-to-merge-unrelated-histories-on-rebase
  • [3] https://git.wiki.kernel.org/index.php/GitCommunity
  • [4] https://github.blog/2022-04-18-highlights-from-git-2-36/
  • Git — сравнение Visual Studio 2022 с MeGit/EGit и SourceTree

Конкурс статей от RUVDS.COM. Три денежные номинации. Главный приз — 100 000 рублей.
Источник: https://habr.com/ru/company/ruvds/blog/685300/


Интересные статьи

Интересные статьи

Orleans – кроссплатформенный фреймворк для создания масштабируемых облачных приложений. Это ПО разработано компанией Microsoft, проекты которой не раз проверялись анализатором PVS-Studio. Посмотрим, с...
Привет! Меня зовут Ренат Алимбеков, я занимаюсь задачами, связанными с Computer Vision в Beeline Казахстан. Сейчас моя работа направлена на Anti-spoofing. Моя основная задача сейчас — заменить ве...
Привет, меня зовут Сергей и я разработчик в команде мобильного бэкенда в компании ATI.SU. Не так давно в мою жизнь пришла задача. В ней нужно было принять координаты от приложения на Android и отобраз...
Достаточно ли одного индикатора для отображения времени и создания часов? Думаю, да. Нужно лишь последовательно показать все разряды, за счёт пауз разной длительности разделяя показания. ...
После появления переводной статьи про Статический анализ в GCC 10, и ожидаемой реакции присутствующих здесь представителей разработчика коммерческого статического анализатора PVS-Studio, у меня в...