У меня появилась задача — я хотел опубликовать на 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 рублей.
Комментарии (5)
fedorro
31.08.2022 16:55+1Какой-то бред, автор оригинала, видимо, не умеет ни гитом, ни студей пользоваться и пишет про это статью ... При старте студии выбираем "Open local folder", выбираем папку со всеми солюшенами и на панели Git-a "Create Git Repository".
Проблема, которая возникла у меня сейчас, но, я уверен, возникнет многократно у меня и других людей, в том, что в конечном итоге у меня получились две ветки:
main
иmaster
. Веткуmain
по умолчанию создаёт GitHub, в ней находится файл readme. Веткуmaster
по умолчанию создаёт SourceTree, и в ней находится мой код (четыре решения VS).Рука-лицо.
Karbofos42
31.08.2022 17:22+1даже не знаю что больше пугает: что такие компетентные люди статьи пишут или что их потом ещё и переводят.
Там ещё в заключении весело про "рабочие пространства", гениальная идея у автора промелькнула, до которой никто не догадался.
aamonster
Кто не сразу понял, что "решение" – это solution, и перевёл текст обратно на английский – поднимите руки.
atd
оно так называется в русскоязычной версии VS начиная с доисторических времён (в 2005 точно уже было).
звучит дико, но так перевели сами мелкомягкие...