Из 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. Ссылки



Конкурс статей от RUVDS.COM. Три денежные номинации. Главный приз — 100 000 рублей.

Комментарии (5)


  1. aamonster
    31.08.2022 16:27
    -1

    Кто не сразу понял, что "решение" – это solution, и перевёл текст обратно на английский – поднимите руки.


    1. atd
      31.08.2022 17:33

      оно так называется в русскоязычной версии VS начиная с доисторических времён (в 2005 точно уже было).

      звучит дико, но так перевели сами мелкомягкие...


  1. fedorro
    31.08.2022 16:55
    +1

    Какой-то бред, автор оригинала, видимо, не умеет ни гитом, ни студей пользоваться и пишет про это статью ... При старте студии выбираем "Open local folder", выбираем папку со всеми солюшенами и на панели Git-a "Create Git Repository".

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

    Рука-лицо.


    1. Karbofos42
      31.08.2022 17:22
      +1

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

      Там ещё в заключении весело про "рабочие пространства", гениальная идея у автора промелькнула, до которой никто не догадался.


  1. atd
    31.08.2022 17:29

    стыд и срам. спрячьте это скорее обратно в черновики (там и оставьте)