-
Notifications
You must be signed in to change notification settings - Fork 6
[DEV RU] Основы Git для разработчиков Sons of Mobius
Git — система управления версиями. С её помощью разработчики могут вести совместную разработку программного обеспечения. Сам по себе Git представляет собой набор программ для организации работы множества людей с общим репозиторием. GitHub является git-хостингом: он предоставляет возможности создания и ведения репозиториев.
Поскольку разработка мода Sons of Mobius ведётся множеством людей, то каждому из них необходимо владеть Git, дабы преимущества этого инструмента не превратились в недостатки. С одной стороны, Git имеет возможность автоматического слияния кода, в т.ч. в одном файле. С другой стороны, пренебрежение базовыми правилами ведения репозитория может приводить к серьёзным проблемам. В процессе разработки Sons of Mobius даже был порождён наглядный пример того, что бывает при несоблюдении этих правил.
Выглядит "прекрасно", не правда ли? Но мало того, что эта проблема возникла в принципе, но в силу самой сути Git как системы для совместной разработки эта проблема начала проявляться и у других разработчиков.
Для того, чтобы успешно разрабатывать мод, рекомендуется ознакомиться с данным материалом. Он поможет Вам легко и непринуждённо работать с Git, а соблюдение рекомендаций позволит не порождать подобного рода проблем.
В данном руководстве Git будет описан в упрощённом виде, без погружения в детали, сложные для понимания новичков.
Для установки Git в Windows необходимо загрузить установочный пакет. Все настройки в процессе установки рекомендуется оставить по умолчанию. Git Bash должен быть установлен.
Установка Git в Linux зависит от пакетного менеджера дистрибутива. На данной странице представлены консольные команды для установки Git. Обратите внимание, что для установки git могут потребоваться привелегии суперпользователя: их можно получить, используя команды sudo, su или путём входа в систему как root.
Проекты располагаются в репозиториях. Собственно, репозиторий проекта Sons of Mobius находится здесь. Впрочем, Вы, скорее всего, попали на данное руководство именно зайдя на страницу репозитория на GitHub.
В репозитории хранятся файлы проекта. В подавляющем большинстве случаев это исходный код и ресурсы (картинки, видео, значки, вспомогательные файлы и т.д.).
В каждом репозитории есть ветки. Каждая ветка содержит свои версии файлов проекта, которые могут (и будут) различаться от ветки в ветке. Создание ветвей происходит посредством операции ответвления. Смысл ветвления заключается в том, чтобы при параллельной работе над файлами проекта не происходило асинхронного изменения одних и тех же файлов: если такое происходит, то Git не может автоматически решить вопрос актуальности версии; такая ситуация называется конфликтом. Подробнее о недопущении конфликтов будет рассказано в главе о правильном ветвлении.
Репозиторий и ветки бывают удалёнными и локальными. Для Вас это означает, что удалённый репозиторий находится на GitHub, а локальный — на Вашем ПК.
Снимки версий файлов проекта на ветках называются коммитами. Пользователи создают коммиты путём фиксации изменений. В коммите находятся список изменённых файлов (в том числе добавленных и удалённых), изменения в самих файлах, описание коммита, данные об авторстве, временная метка и хэш. Необходимо уточнить, что фиксация изменений работает только для отслеживаемых файлов: неотслеживаемые файлы и папки указываются в файле .gitignore (для всех участников проекта) или .git/info/exclude (только для Вас). Подробнее об этих файлах будет рассказано позднее.
Приведение различных версий файлов необходимо при соединении воедино результатов работы множества пользователей. Самым правильным способом переноса изменений на другую ветку является слияние: в результате слияния все коммиты с одной ветки попадают на другую. На одной ветке коммиты идут строго по порядку, определяемому временем их создания, но в сочетании с другими ветками образуется рассинхронизация коммитов по времени. При слиянии нескольких веток в одну можно оценить получившееся дерево коммитов как визуально, так и в текстовом формате. При этом стоит учитывать возможность возникновения конфликтов при слиянии (об их разрешении будет рассказано далее).
Взаимодействие с репозиторием осуществляется путём выполнения команд git. Они могут быть выполнены как с помощью консоли, так и средствами используемой Вами среды разработки (IDE). Базовые команды git приведены далее.
-
Клонирование репозитория (Clone). Скачивает репозиторий в заданную папку.
Команда:git clone
.
Чтобы клонировать репозиторий Sons of Mobius на свой ПК, необходимо выполнить командуhttps://github.com/SoM-Team/Sons-of-Mobius.git
из той папки, в которую Вы хотите клонировать репозиторий. -
Получение изменений (Fetch). Получает изменения из главной ветки и
переписывает их в локальный репозиторий. С помощью данной операции извлекается информация об удалённых ветках и последних коммитах на них. Если на текущей ветке имеются удалённые изменения, то они не будут занесены в локальную ветку автоматически.
Команда:git fetch
. -
Вытягивание изменений (Pull). Делает то же самое, что и Fetch, но также записывает изменения с удалённой рабочей ветки в локальную.
Команда:git pull
. -
Фиксация изменений (Add). Фиксирует изменения файлов в локальной ветке для дальнейшего создания коммита.
Команда:git add
.
Для фиксации всех отслеживаемых файлов выполняется командаgit add -A
.
Для фиксации только определённых файлов необходимо перечислять их после слова add. Например, так:git add hello.txt goodbye.txt
. -
Создание коммита. Создаёт коммит с зафиксированными изменениями.
Команда:git commit
.
Создание коммита с сообщением:git commit -m "Message"
. Создание коммита с сообщением и автоматической фиксацией изменений всех файлов:git commit -a -m "Message"
. -
Отправка изменений (Push). Отправляет ветки в удалённый репозиторий.
Команда:git push
.
Отправить все ветки:git push origin
.
Отправить определённую ветку:git push <branch_name>
.
Учтите, что перед отправкой веток необходимо вытянуть изменения, иначе операцию провернуть не удастся. Отправить свежесозданную ветку:git push -u <branch_name>
. -
Переход (Checkout). Переключается в точку дерева коммитов. Как правило, используется для перехода с ветки на ветку, а также для создания новых веток. Команда:
git checkout
.
Переход на коммит:git checkout <commit_hash>
(не рекомендуется переходить на коммит, не существующей в Вашей текущей ветке).
Переход на ветку:git checkout <branch_name>
.
Создание ветки из текущей:git checkout -b <new_branch_name> -u origin/<new_branch_name>
. -
Слияние (Merge). Объединяет два и более набора коммитов в один. Под наборами коммитов понимаются в том числе и ветки, и чаще всего они и подразумеваются при упоминании операции слияния. Команда:
git merge
.
Слияние ветки B в ветку A:
git checkout branch_A
git merge branch_B
-
Отмена изменений (Revert). Создаёт новый коммит, отменяющий один или несколько предыдущих, не изменяя историю коммитов, предшествующих ему. Это самый безопасный способ отменить неудачный коммит.
Команда:git revert
.
Отмена последнего коммита:git revert HEAD
.
Совместная разработка предполагает, как ни странно, участие множества разработчиков. Чтобы не портить жизнь друг другу и не саботировать разработку вообще, им необходимо знать о существовании культуры ведения репозитория и придерживаться определённых правил по работе с ним.
Первым делом необходимо знать, что ветки в Git придуманы не просто для прикола, а чтобы разрешать проблемы, возникающие при асинхронной работе над файлами проекта. А асинхронной является, в общем-то, любая работа над ними. Ну не научились мы ещё в хайвмайнд с синхронизацией, что поделать.
Для ведения веток придуманы специальные конвенции. Одной из самых распространённых считается git-flow. Нам от неё нужно знать только то, что существуют несколько основных веток, исполняющих существенные роли в проекте, а разработчики придерживаются определённых правил работы с ними. Нам из всего git-flow достаточно вычленить две основные ветки: master и develop.
Ветка master является главной веткой проекта, и поэтому обладает монашеской неприкосновенностью. Любой разработчик должен с трепетом относиться к этой ветке и всячески пресекать наглые посягательства на её тело. В эту ветку вносится только самый стабильный код, из которого можно собрать полностью рабочую актуальную версию.
Ветка develop является второй по важности веткой проекта. В ней находятся полустабильные изменения, готовящиеся к тому, чтобы попасть в следующую основную версию.
Ветки master и develop мы будем называть публичными, равно как и любые другие, которые предполагаются для совместного использования. Ветки, предназначенные для личного использования конкретным разработчиком, будут называться личными.
Итак, самое важное, что должен знать любой разработчик, использующий Git, описаны далее.
-
Операции Push в публичные ветки запрещены. Никогда, слышите, НИКОГДА, не нарушайте данное правило! Помните иллюстрацию в начале? Это случилось как раз в результате нарушения данного правила. Отправляйте изменения только в свои личные ветки.
-
Операции Push в чужие личные ветки запрещены. Никому не будет приятно, если он не сможет запушить в свою ветку, потому что там оставил свои следы кто-то другой. Но что ещё хуже, это может сделать код на ветке неработоспособным и породить конфликты коммитов. Причём эти конфликты зачастую переходят в конфликты личностные. Вы же не хотите этого?
-
Перенос изменений из одной ветки в другую осуществляется только путём слияния. Никаких операций cherry-pick (Вам, в общем-то говоря, не нужна эта операция, если Вы придерживаетесь данного свода правил). И, разумеется, ни в коем случае нельзя просто копировать файлы из одной ветки, переходить на другую и вставлять их туда. Даже наличие справки не освобождает идиотов от ответственности за такое преступление против человечности.
-
Если предполагается совместная работа над одной фичей, то необходимо создать ветку под фичу, а из неё создать личные ветки для разработчиков. Помните правило 1? То-то и оно. Разумеется, нужно помнить и про правило 3. В таком случае количество проблем будет сведено к минимальному.
-
Слияние кода в публичные ветки необходимо осуществлять путём создания промежуточных. Протестировали работоспособность своего кода и уверены, что всё работает как часы? Не торопитесь. Вполне вероятно, что на ветке develop появились изменения от других разработчиков. Вполне вероятно также, что какой-нибудь нерадивый разработчик всё там сломал. Первым делом создайте промежуточную ветку из develop и попробуйте сделать слияние своей ветки в неё: а вдруг что-то не так? Если всё в порядке, то сливайте промежуточную ветку в develop. Если всё сломалось и не работает вместе, то заявите о наличии проблем остальным разработчикам или найдите виноватого самостоятельно, после чего продолжайте работу в своей ветке, пока ошибки в основной не будут исправлены.
Необходимо заметить, что вышеописанное правило касается не только ветки develop. Ветки, предназначенные для совместной работы над одной фичей, также должны быть слиты посредством такой процедуры. Это поможет избавиться от лишних проблем и ошибок заранее. -
Для слияния кода в публичные ветки создаются запросы на слияние. Проще всего их создавать, рассматривать и принимать/отвергать через соответствующую страницу на GitHub. Запросы на слияние делаются для того, чтобы остальная команда имела возможность проверить Вашу работу до того, как она попадёт в публичную ветку. Данное правило не столь строгое: его можно не придерживаться, если над одной фичей работают 2-3 человека, легко держащие в голове всё, что нужно для выполнения задачи. Но вот если речь идёт о важной публичной ветке, особенно о develop или master, то данное правило должно обязательно соблюдаться. В ситуации, когда проверить Вашу работу никто не может, Вы можете сами принять свой же запрос на слияние. Но помните о том, что он обязательно должен быть создан, дабы Ваши изменения можно было откатить в случае чего. Учтите, что код, попадающий в develop, должен сливаться туда безо всяких конфликтов, и если следовать данным правилам, то их и не будет. Если есть множество обновлений кода от разных разработчиков, которые должны попасть в develop, то см. п. 5. Аналогично для master.
-
При переключении на другую ветку фиксируйте изменения и создавайте коммит, либо отменяйте свои изменения. Это делается для избежания непреднамеренного смешивания файлов.
-
Предпочитайте использовать операцию Revert для отмены изменений. Как уже было сказано, данная операция не изменяет историю коммитов и не превращает дерево коммитов в кашу. Существуют ситуации, когда необходимо применить другие способы отмены изменений, и о них мы упомянем далее. Однако для публичных веток используйте Revert: удаление коммитов может привести к тому, что у других участников этот коммит может остаться, что приведёт к нарушению истории коммитов и усугублению ситуации.
-
И, наконец, самое главное правило — не бойтесь обращаться за помощью к более опытным коллегам. Не стыдно не знать, стыдно не учиться. Но ещё стыднее косячить с умным видом.
-
Используйте программы, позволяющие оперировать с репозиторием в графическом режиме. Даже опытным разработчикам порой сложно совершать все операции в консоли. Да и в целом это может отнимать много времени. Кроме того, такие программы почти всегда позволяют визуально оценить ход проекта. Ну и самый важный плюс заключается в возможности быстро и наглядно разрешать конфликты коммитов.
-
Делайте коммиты небольшими. Сделали небольшое изменение? Фиксируйте и делайте коммит. Не нужно копить кучу изменений, а потом создавать один огромный коммит: если возникнут проблемы, то придётся проверять кучу файлов. Хуже того, откат большого числа файлов неприятен. Ещё хуже, если откатывать придётся при наличии последующих коммитов.
-
Сделали коммит? Отправляйте на сервер. Мало ли что может случиться с Вашим ПК. Буквально завтра у него сгорит блок питания, забирая с собой все диски. Или сдохнет SSD. Я не знаю, что именно из этого произойдёт, но что-нибудь да случится точно, и причём именно завтра. Я гарантирую это. Это обязательно произойдёт, и обязательно именно завтра. Вы же не хотите потерять из-за эдакой оказии существенную часть работы?
-
Соблюдайте принятую в проекте нотацию написания кода. Помните, что код чаще читается, нежели пишется. И если Вы будете писать код также, как и остальные разработчики, то Вам будет проще понять их код, а им Ваш. Это позволяет нам легко помогать друг другу.
-
Удаляйте ненужные ветки. Со временем количество веток может существенно увеличиться, раздувая репозиторий и усложняя навигацию. Дабы избежать этого, необходимо удалять ненужные ветки после слияний и прочий хлам.
-
Советуйтесь с коллегами по возникающим вопросам. Не забывайте, что у каждого разработчика своя зона ответственности, и двум разработчиками будет сложно вникнуть в проблемы друг друга при отсутствии внятной документации. И не забывайте про пункт 4: это упростит взаимопонимание.
-
В: Мне не удаётся запушить коммиты в удалённый репозиторий из-за отсутствия права на это.
О: Это само собой разумеется, если Вы не числитесь в рядах разработчиков мода. Но если числитесь, то необходимо запросить у кураторов проекта права на редактирование репозитория. Когда они будут Вам выданы, Вам будет отправлено письмо на почту с просьбой подтвердить своё участие в проекте. Если не удаётся запушить и после этого, проверьте, что Вы правильно указали учётные данные для входа в удалённый репозиторий (данные от аккаунта GitHub или SSH-ключи).
Вы можете попробовать задать логин и пароль для репозитория следующим образом. Выполните данные команды из папки репозитория:git config user.name "your_login" git config user.password "your_password"
-
В: У меня не получается отправить изменения в удалённый репозиторий. Я получаю ошибку
Updates were rejected because a pushed branch tip is behind its remote ounterpart
. Что делать?
О: Ответ на данный вопрос предлагает сам git в консоли: необходимо совершить операцию git pull перед отправкой изменений. Сиутация возникает в тех случаях, когда на удалённой ветке появляются изменения, которых нет в Вашей локальной. -
В: У меня возникли конфликты при вытягивании изменений (pull). Что делать?
О: Использоватьgit mergetool
для их разрешения. Либо программу с графическим интерфейсом, что предпочтительнее для новичков. -
В: У меня возникли конфликты при слиянии. Что делать?
О: Как и в прошлом случае, нужно разрешить конфликты. Нужно понимать, что вытягивание изменений (pull) является комбинацией команд fetch и merge: fetch получает последние изменения с удалённого репозитория и записывает их в локальный, но не сливает их в Вашу ветку автоматически. А merge сливает, завершая этот процесс. -
В: Как создать запрос на слияние?
О: Можно сделать это через интерфейс GitHub на данной странице. Необходимо описать проделанные изменения и назначить ответственных проверяющих. Также укажите метки, позволяющие вкратце описать затронутые части кода. Если проверить некому, принимайте запрос самостоятельно, но обязательно убедитесь, что Ваш код работает как положено, и что Вы сливаете его в нужную ветку, а не куда попало. Как уже было отмечено ранее, в develop должен попадать стабильный код с новыми фичами и без старых багов, поэтому создание запросов на слияние в данном случае строго обязательно. Также убедитесь, что правильно разрешаете конфликты коммитов. Если не уверены, что делаете это правильно, или какой код лучше и актуальнее, то оставьте это на усмотрение проверяющих. -
В: Мне нужно отменить более одного коммита. Как мне это сделать?
О: Есть несколько способов отменить сразу несколько коммитов.
Способ 1: выполнение несколькихgit revert
подряд без коммитов. Способ подойдёт для небольшого числа коммитов. Допустим, нужно откатить два коммита. В таком случае выполните следующие команды:git revert --no-commit <commit2> git revert --no-commit <commit1> git commit -m "Reverted last two commits."
Аргумент --no-commit позволяет откатить изменения без создания коммита. Коммит с фиксацией откатов создаётся в конце вручную. Учтите, что добавленные файлы не удалятся. Способ 2: переход на старый коммит с созданием нового. Подойдёт, если нужно откатиться на конкретный коммит, но с сохранением добавленных файлов. Небезопасный вариант: не используйте его на публичных ветках.
git checkout -f <commit> -- . git commit -a
Способ 3: выполнение
git reset
со сбросом всех изменений. Предполагает удаление всех изменений. Используется в случаях, когдасовсем стыдно за содеянноепроще удалить, чем исправлять.git reset --hard <target_commit> git reset --soft <last_commit> git commit -m "Reverted last commits."
Если не хочется терять сделанные изменения насовсем, то создайте новую ветку и выполните данный откат на ней. Используйте данный способ только локально.
-
В: Я случайно отправил коммиты не в ту ветку. Что делать?
О: Неприятная ситуация. Удалять коммиты ни в коем случае не нужно. Необходимо переназначить указатель имени ветки для коммитов, которые Вы отправили не по адресу. Для этого необходимо знать хэши коммитов (можете просмотреть их с помощьюgit log
). Далее выполняем командуgit push -f origin <commit_hash>:<branch_name>
.
Есть и другой способ, с использованием командыgit cherry-pick
. Находим последний правильный коммит и переходим на него:git checkout <correct_commit_hash>
.
Создаём временную ветку:git checkout -b <temp_branch_name>
.
Далее переносим лишний коммит на временную ветку:git cherry-pick <incorrect_commit_hash>
.
Если имеется несколько лишних коммитов, то берём хэши первого и последнего из них и выполняем cherry-pick следующим образом:git cherry-pick <first_incorrect_commit_hash>..<last_incorrect_commit_hash>
.
Переключаемся обратно на ветку, в которую те коммиты не должны были попасть.git checkout <branch_name>
.
Смещаем указатель ветки на последний корректный коммит:git reset --hard <correct_commit_hash>
.
Отправляем изменения:git push -f
.
Если необходимо данные коммиты перенести в какую-либо ветку, делайте слияние. -
В: Как мне удалить ветку?
О: Локально ветка удаляется командойgit branch -d <branch_name>
. Не забудьте переключиться на другую ветку с помощьюgit checkout
, иначе ничего не получится. Если ветка не полностью слита (is not fully merged
), то для принудительного удаления используйте командуgit branch -D <branch_name>
. Если Вы хотите удалить удалённую ветку (в смысле, находящуюся в репозитории на GitHub; такой вот русский язык), то используйте командуgit push origin -d <branch_name>
. Однако лучше бы Вам не приходилось её использовать, дабы случайно не зацепить другую ветку. -
В: Что такое .gitignore и .git/info/exclude?
О: Это файлы, в которых указываются файлы, которые не учитываются при фиксировании изменений.
.gitignore лежит в корневой папке репозитория. Файлы, указанные в нём, не учитываются ни у кого из участников проекта. В нём обычно указываются файлы и папки, специфичные для сред разработки (.idea, .vs, .vscode и т. д.; все эти папки создаются IDE).
В .git/info/exclude указываются файлы, которые не учитываются локально, т. е. только у Вас. Рекомендуется указывать в нём различные временные файлы, которые нужны Вам, но которые не должны попадать в удалённый репозиторий. -
В: Здесь нет никаких советов для моей ситуации.
О: Обратитесь за помощью к коллегам. Они помогут Вам решить проблему. Если она действительно не описана здесь, то мы её обязательно сюда добавим.
- Guides
1.1. Git basics for SoM developers (RU)
1.2. Coding convention (RU)
1.3. National focus design documents style (RU) - Common information
2.1. Reserved names and ranges - In-development features and mechanics
3.1. Ring currency mechanic