Вы новичок с git? Выполните несколько следующих шагов, чтобы комфортно делать изменения в кодовой базе, открывать pull request (PR) и сливать текущий код с главной веткой проекта (merge). Важные термины git и GitHub выделены синим текстом, и предоставляются ссылки на официальную документацию по git.
Примечание: здесь приведен вольный перевод статьи [1].
[Шаг 0: Установка git, создание учетной записи на GitHub]
Установка git и получение учетной записи GitHub бесплатны. Обратите внимание, что в этом руководстве мы будем использовать git только в командной строке. Однако существует несколько хороших утилит для git, имеющих графический интерфейс. Автор считает, что командная строка упростит обучение специфических командам git, после чего можно будет попробовать и GUI-интерфейс для git.
После того, как git скачан и установлен, создайте себе учетную запись GitHub [2].
Стоить заметить, что GitHub не тоже самое, что git. Git это система управления версиями с открытым исходным кодом, созданная разработчиками в 2005 году, работающими на Linux. GitHub это компания, основанная в 2008 году, которая создала публичный ресурс для хранения репозиториев, интегрированный с инструментами git. GitHub не нужен для использования git, однако обратное неверно - GitHub нельзя использовать без git. Существует много других альтернатив GitHub, таких как GitLab, BitBucket, и решения на основе Вашего собственного хоста, такие как gogs и gittea. Все они именуются в терминологии git как удаленные (сетевые) хранилища (remotes), и совершенно не обязательно их использовать. Вам не нужен удаленный сервер, чтобы использовать git, однако удаленный сервер упростит совместное использование Вашего кода другими программистами.
[Шаг 1: Создание локального репозитория git]
Основной принцип использования git - один репозиторий на один проект. Хотя в целом это не обязательно - просто общепринятая практика, точно такая же как одна папка под один проект. Когда создается новый проект на локальной машине, создайте для него новый репозиторий (repository, часто для краткости репозиторий называют 'repo').
Для git мы будем использовать строку терминала. Если Вы пользователь Linux, но плохо ориентируетесь в базовых командах этой операционной системы, изучите ресурс [4].
Если Вы пользователь Windows, и установили пакет инструментария git, то в контекстном меню Проводника появятся две ссылки для запуска утилит git: Git GUI here и Git Bash Here. Контекстное меню с этим ссылками открывается, если кликнуть правой кнопкой мыши на папке проекта. Если запустить Git Bash Here, то сразу запустится консоль командной строки с текущим каталогом проекта.
Чтобы начать, откройте окно терминала и поменяйте текущий каталог на тот, где находится Ваш проект. И на Linux, и на Windows это делается командой cd (change directory). Например, у Вас на диске есть каталог projects, и нужно создать новый проект в новом каталоге myproject. Для этого команды в консоли Linux могут быть примерно такие:
$ cd ~/Desktop
$ mkdir myproject
$ cd myproject/
После этих команд текущим каталогом будет myproject, это будет папка проекта.
Для случая, когда папка проекта STM32F407-Blink уже существует на диске, в консоли команд Windiows:
Чтобы создать репозиторий проекта в папке myproject, запустите команду git init:
$ git init
Initialized empty Git repository in /Users/пользователь/Desktop/myproject/.git/
[Шаг 2: добавление нового файла в репозиторий]
Пойдем дальше, и создадим новый файл для проекта с помощью любого текстового редактора, либо (под Linux) командой touch. Команда touch newfile.txt просто создаст пустой файл с именем newfile.txt.
$ touch main.c
$ ls
main.c
Когда Вы добавили, или изменили файлы в папке, где находится git repo, то при запуске git заметит, что внутри repo существует этот файл. Однако git не будет отслеживать изменения в добавленном файле (файлах), если ему это не указать явным образом. Git сохраняет/обслуживает изменения только в тех файлах, на которых у него настроен трекинг, поэтому нам нужна специальная команда для git, если мы хотим, чтобы он отслеживал наш новый файл.
После создания нового файла можно использовать команду git status чтобы увидеть, о каких файлах git знает, что они существуют. Пример вывода команды git status в только что созданном репозитории, в котором пока не настроен трекинг файлов проекта:
m:\work\STM32F407-Blink>git status
On branch master
No commits yet
Untracked files:
(use "git add < file >..." to include in what will be committed)
nothing added to commit but untracked files present (use "git add" to track)
m:\work\STM32F407-Blink>
Этим выводом git нам сообщает: "вижу, что в каталоге репозитория создано несколько новых файлов и каталогов, но пока не введете команду 'git add', я ничего с этими файлами делать не буду". Список этих файлов выделен красным цветом, который показывает, что за этими файлами git должен следить, но пока они не добавлены в базу git и не отслеживаются.
Одна из самых запутанных вещей, когда Dы впервые изучаете git, является концепция staging environment, и как это связано с фиксацией проекта в репозитории (commit).
Фиксация (commit) это запись в базу данных репозитория новых изменений, которые были сделаны в файлах проекта с момента последней фиксации (далее вместо "фиксации" буду использовать термин commit). В сущности Вы делаете изменения в своем repo (например, добавление файла или модификация файла) и затем говорите операцией commit для git, чтобы он внес эти изменения в commit.
Commit-ы составляют историю изменений проекта, и позволяют перейти к любой стадии проекта (откатить проект), для которой ранее был сделан commit.
Как указать git, какие файлы надо поместить в commit? Здесь мы сталкиваемся с термином staging environment, или индексом. Как было видно на шаге 2, когда мы сделали изменения в своем repo, git сказал, что файл (файлы) был изменен, но с ним никаких операций не проводилось (наподобие операций, которые делаются над файлами, добавленными в commit).
Чтобы добавить файл в commit, необходимо сначала добавить его в staging environment (проиндексировать). Чтобы это сделать, мы будем использовать команду git add < имяфайла > (см. шаг 3 далее).
Как только была выполнена команда git add для файла (файлов), которые необходимо добавить в staging environment репозитория, можно теперь сказать git, чтобы он упаковал этот файл (файлы) в commit с помощью команды git commit.
Замечание: staging environment иногда называют 'staging', это более новый, предпочтительный термин для организации хранилища репозитория, но в будущем Вы заметите, что staging называют также индексом.
[Шаг 3: добавление файла в staging environment]
Добавление файла в staging environment делает команда git add. Если после неё вы вернетесь к команде git status, то увидите, что git добавил этот файл в staging environment (будет выведена строка "Changes to be committed").
Пример команды git add (маска * вместо имени файлов говорит о том, что нужно добавить сразу несколько файлов и папок):
d:\asm\STM32F407-Blink>git add *
d:\asm\STM32F407-Blink>
Если добавляемых файлов и папок много, то для создания базы данных git задумается на несколько секунд. Пример вывода команды git status после добавления файлов в базу (список файлов большой, поэтому он сокращен многоточиями ...):
m:\work\STM32F407-Blink>git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached ..." to unstage)
new file: .gitignore
new file: .mxproject
new file: Drivers/CMSIS/Core/Include/cmsis_armcc.h
new file: Drivers/CMSIS/Core/Include/cmsis_armclang.h
new file: Drivers/CMSIS/Core/Include/cmsis_compiler.h
new file: Drivers/CMSIS/Core/Include/cmsis_gcc.h
new file: Drivers/CMSIS/Core/Include/cmsis_iccarm.h
...
new file: Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h
new file: Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/stm32f4xx_hal_can_legacy.h
new file: Drivers/STM32F4xx_HAL_Driver/Inc/stm32_assert_template.h
new file: Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h
new file: Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h
new file: Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h
new file: Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h
...
new file: EWARM/Project.eww
new file: EWARM/STM32F407-Blink.dep
new file: EWARM/STM32F407-Blink.ewd
new file: EWARM/STM32F407-Blink.ewp
new file: EWARM/STM32F407-Blink.ewt
new file: EWARM/settings/Project.wsdt
new file: EWARM/settings/STM32F407-Blink.Release.cspy.bat
new file: EWARM/settings/STM32F407-Blink.Release.cspy.ps1
new file: EWARM/settings/STM32F407-Blink.Release.driver.xcl
new file: EWARM/settings/STM32F407-Blink.Release.general.xcl
new file: EWARM/settings/STM32F407-Blink.STM32F407-Blink.cspy.bat
new file: EWARM/settings/STM32F407-Blink.STM32F407-Blink.cspy.ps1
new file: EWARM/settings/STM32F407-Blink.STM32F407-Blink.driver.xcl
new file: EWARM/settings/STM32F407-Blink.STM32F407-Blink.general.xcl
new file: EWARM/settings/STM32F407-Blink.crun
new file: EWARM/settings/STM32F407-Blink.dbgdt
new file: EWARM/settings/STM32F407-Blink.dnx
new file: EWARM/startup_stm32f407xx.s
new file: EWARM/stm32f407xx_flash.icf
new file: EWARM/stm32f407xx_flash_for_bootloader.icf
new file: EWARM/stm32f407xx_sram.icf
new file: Inc/main.h
new file: Inc/pins.h
new file: Inc/stm32f4xx_hal_conf.h
new file: Inc/stm32f4xx_it.h
new file: STM32F407-Blink.ioc
new file: Src/main.c
new file: Src/stm32f4xx_hal_msp.c
new file: Src/stm32f4xx_it.c
new file: Src/system_stm32f4xx.c
new file: backup.bat
new file: clean.bat
new file: readme.txt
new file: util/append-STM32-hardware-CRC/.gitignore
new file: util/append-STM32-hardware-CRC/LICENSE.md
new file: util/append-STM32-hardware-CRC/README.md
new file: util/append-STM32-hardware-CRC/src/crc32.sln
new file: util/append-STM32-hardware-CRC/src/crc32/Program.cs
new file: util/append-STM32-hardware-CRC/src/crc32/Properties/AssemblyInfo.cs
new file: util/append-STM32-hardware-CRC/src/crc32/Vurdalakov/AssemblyInfo.cs
new file: util/append-STM32-hardware-CRC/src/crc32/Vurdalakov/CRC32.cs
new file: util/append-STM32-hardware-CRC/src/crc32/Vurdalakov/CRC32Managed.cs
new file: util/append-STM32-hardware-CRC/src/crc32/Vurdalakov/CommandLineOption.cs
new file: util/append-STM32-hardware-CRC/src/crc32/Vurdalakov/CommandLineOptions.cs
new file: util/append-STM32-hardware-CRC/src/crc32/Vurdalakov/CommandLineParser.cs
new file: util/append-STM32-hardware-CRC/src/crc32/app.config
new file: util/append-STM32-hardware-CRC/src/crc32/crc.c
new file: util/append-STM32-hardware-CRC/src/crc32/crc32.csproj
Git был разработан для отслеживания изменений только в программном коде, оформленном как простой текст. Однако в каталоге проекта может быть и много других файлов, которые генерируются в процессе компиляции (*.obj, *.a, *.bin, *.hex, *.lst, *.map и другие подобные). Эти файлы по сути временные, не несут в себе никакой смысловой нагрузки, и программистом не просматриваются и не редактируются. Существуют и другие файлы, которые нет смысла добавлять в базу git - например файлы документации (*.pdf, *.html, *.chm), картинки (*.bmp, *.jpg, *.png).
Перечисленные файлы не являются текстовыми, просмотр их в сыром виде, как текста, никакой пользы не дает. Но если не настроить их исключение из базы git, то в будущем при активной работе с проектом это создаст большую проблему - база данных git будет нести много бесполезной нагрузки и сильно разрастаться в объеме.
Для борьбы с этой проблемой был специально создан файл .gitignore, который позволяет создать список файлов и папок, которые не должны отслеживаться git. Вот пример такого файла:
Существует команда git add -n *, которая позволяет не добавить, а предварительно посмотреть список файлов, которые добавит команда git add *. Это очень полезно для отладки файлов .gitignore.
[Шаг 4: создание commit]
Настало время сделать Ваш первый commit!
Запустите команду git commit -m "Тут вставьте комментарий к commit-у":
Выведенный список файлов покажет, что в этом commit содержится. В комментарии, указанном опцией -m, обычно кратко указывают, что было сделано в этом commit. Это могут быть как новые функции (файлы модулей), добавленные в проект, или исправления ошибок, или может быть просто исправление опечатки. Не стоит в комментарии к commit писать что-то на подобие "asdfadsf" или "foobar". Это введет в депрессию других людей, просматривающих репозиторий, да и Вас тоже, когда через пару месяцев никто уже и не вспомнит, какие изменения и зачем были в этот момент сделаны. Коммиты навсегда останутся в репозитории (технически их все-таки удалить можно, если очень хочется, но это пожалуй грязный трюк), и если для commit плохо составлен комментарий, то в будущем он станет фактически бесполезным.
Примечание переводчика: люблю начинать комментарий к commit шестью цифрами, обозначающими год, месяц, день, например вот так (2021 год, июнь, 4 число): git commit -m "210604 first commit". Не делайте текст комментария на русском языке, потому что это может привести к проблеме кодировки текста (кракозябрам) на некоторых платформах.
[Шаг 5: создание новой ветки (branch)]
Теперь, когда Вы создали новый commit, давайте попробуем сделать что-то более продвинутое.
Может произойти так, что Вы хотите добавить в проект новую функцию, но беспокоитесь о внесении изменений в проект при разработке этой функции. Для такой ситуации в git предусмотрена такая вещь, как ветка (branch).
Ветки позволяют вам перемещаться назад и вперед между состояниями проекта. Официальная документация git описывает branch-и так: 'A branch in Git is simply a lightweight movable pointer to one of these commits.' ("Ветвь в Git это просто облегченный, перемещаемый указатель на один из существующих commit-ов"). Например, если Вы хотите добавить новую страничку на свой сайт, то можете создать новую ветку только для этой страницы, без какого-либо влияния на основную часть проекта. Как только Вы закончите разработку этой странички и убедились, что все сделали правильно, можно будет влить внесенные изменения в основную ветку проекта (primary branch, операция слияния называется merge). Когда Вы создаете новую ветку, Git сохранит трек commit-ов, то которых эта ветка ушла, так что он знает всю историю за этими файлами.
Допустим, что Вы находитесь на основной ветви проекта, и хотите создать новую ветку, чтобы разработать новую веб-страничку. Для этого выполните команду git checkout -b < имявашейветки >. Эта команда автоматически создаст новую branch, и перейдет на неё от primary branch.
После выполнения этой команды Вы можете использовать команду git branch, чтобы убедиться, что ветка была создана:
$ git branch
master
* my-new-branch
Звездочка слева от имени ветки показывает, на какой ветви Вы находитесь в настоящий момент.
По умолчанию каждый репозиторий git содержит первую ветку с именем master (и она обычно используется как primary branch, главная ветка в проекте). В рамках мировой тенденции по толерантности и борьбы с расизмом некоторые группы разработчиков начинают использовать альтернативные имена для ветки по умолчанию (например, в этом руководстве мы используем для главной ветки "primary", primary branch). В другой документации и других обсуждениях Вы можете по прежнему увидеть "master" или другие термины для обозначения главной ветки. Независимо от имени просто имейте в виду, что у каждого репозитория есть главная ветка, которую можно рассматривать как официальную (проверенную) версию репозитория. Если это вебсайт, то главная ветка это так версия сайта, которую пользователи видят в онлайне. "Главность" ветки не нужна (git не рассматривает какие-либо ветки иначе, чем другие ветки), но по традиции git в проекте используется именно так.
Если Вы интересуетесь решениями по использованию разных имен для веток, то на GitHub есть соответствующий материал по переименованию главной ветви, см. [5].
Если сейчас Вы переключитесь обратно на primary branch, и сделаете некоторые дополнительные commit-ы, то новая ветка не увидит эти новые изменения, пока эти изменения не будут влиты (merge) в новую ветку.
[Шаг 6: Создание нового репозитория на GitHub]
Если Вы хотите следить за своим кодом (управлять версиями проекта) только локально, но GitHub (или другие онлайн-хранилища репозиториев) использовать совершенно не обязательно. Однако если Вы хотите работать в команде разработчиков, то можете использовать GitHub для совместной работы (изменениями кода) в одном проекте.
Чтобы создать новый repo на GitHub, залогиньтесь на сайте github.com и перейдите на домашнюю страницу. Там можно найти опцию "New repository" (новый репозиторий) под знаком "+" рядом с картинкой Вашего профиля, в верхнем правом углу панели навигации:
После клика на эту кнопку GitHub запросит у Вас имя для repo и для его краткого описания:
После заполнения информации на этой страничке кликните на кнопку Create repository для создания нового repo.
GitHub спросит, хотите ли Вы создать совершенно новый repo с нуля, или хотите добвавить repo, который создан у Вас локально. Для последнего случая, когда мы уже создали локально новый repo, и хотим поместить его на GitHub следуйте указаниям '....or push an existing repository from the command line':
m:\work\STM32F407-Blink>git push -u origin main
Logon failed, use ctrl+c to cancel basic credential prompt.
Username for 'https://github.com': microsindotnet
Password for 'https://microsindotnet@github.com':
Enumerating objects: 1123, done.
Counting objects: 100% (1123/1123), done.
Delta compression using up to 2 threads
Compressing objects: 100% (1092/1092), done.
Writing objects: 100% (1123/1123), 12.04 MiB | 1.70 MiB/s, done.
Total 1123 (delta 450), reused 0 (delta 0)
remote: Resolving deltas: 100% (450/450), done.
To https://github.com/microsindotnet/STM32F407-Blink.git
* [new branch] main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.
m:\work\STM32F407-Blink>
Примечание: нужно будет поменять URL в первой команде так, чтобы URL соответствовал Вашему имени пользователя и имени репозитория. На страничке GitHub будет соответствующая подсказка, откуда можно напрямую копировать и вставлять команды git remote add, git branch и git push.
[Шаг 7: Проталкивание (push) ветки на GitHub]
Теперь мы сделаем push для commit нашей новой ветки в наш новый репозиторий на GitHub. Это даст возможность другим людям увидеть изменения, которые Вы сделали. Если изменения были одобрены владельцем репозитория, то они могут быть объединены с основной веткой репозитория (merged into primary branch).
Чтобы сделать push изменений в новую ветку на GitHub, нужно выполнить команду git push origin имявашейветки. GitHub автоматически создаст эту ветку в своем сетевом репозитории:
$ git push origin my-new-branch
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 313 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/microsindotnet/STM32F407-Blink.git
* [new branch] my-new-branch -> my-new-branch
Примечание: если Вы используете GitHub локально впервые, то эта команда может предложить ввести имя пользователя и пароль GitHub.
Возможно, Вам будет непонятно, что в этой команде означает слово "origin". Когда Вы клонируете удаленный репозиторий на своем локальном компьютере, git создает для Вас псевдоним. Почти во всех случаях этот псевдоним называется "origin". По существу это слово является кратким обозначением URL удаленного репозитория. Итак, чтобы выгрузить (push) Ваши изменения в удаленный репозиторий, то существует 2 варианта команды: git push git@github.com:git/git.git имявашейветки или git push origin имявашейветки.
Если Вы обновите страницу GitHub, то увидите, что указанная ветка была помещена в репозиторий. Также можно кликнуть на ссылку 'branches', чтобы увидеть свою ветку.
Теперь мы будем делать pull request.
[Шаг 8: Создание pull request (PR)]
Запрос на извлечение (pull request, или PR) это способ оповещения владельцев репозитория, что Вы хотите сделать некие изменения в своем коде. Это позволит владельцам repo просмотреть Ваш код и убедиться, что он достаточно хорош, чтобы поместить эти изменения в primary branch.
Вот так выглядит страница PR перед отправкой запроса:
[]
И вот так это выглядит, когда запрос PR был отправлен:
[]
Вы можете увидеть большую зеленую кнопку внизу 'Merge pull request'. Клик на ней означает, что Вы вольете свои изменения в primary branch.
Иногда Вы будете совладельцем, или единственным владельцем репозитория, и в этом случает может не понадобиться создавать PR, чтобы влить Ваши измнения. Однако все-таки хорошей идеей будет сделать PR, чтобы можно было сохранить более полную историю Ваших обновлений и убедиться, что всегда создается новая ветка при внесении изменений.
[Шаг 9: Merge PR]
Пойдем дальше и кликнем на кнопку 'Merge pull request'. Это сольет ваши изменения с главной веткой проекта.
[]
Когда это было сделано, лучше всего удалить Вашу ветку (слишком большое количество веток загрязняют репозиторий), для этого кликните на кнопку 'Delete branch'.
Вы можете дополнительно проверить, что Ваши commit-ы были влиты путем клика на ссылку 'Commits' на первой страничке репозитория.
[]
Появится список всех commit-ов в этой ветке.
[]
Здесь также справа можно увидеть хеш-код для commit. Хеш-код это уникальный идентификатор для определенного commit. Он полезен для обращения к определенным commit-ам, и когда делается откат изменений. Для отката используйте команду git revert < хешкод >.
[Шаг 10: как закачать изменения в репозитории GitHub на свой компьютер]
Сейчас repo на GitHub выглядит несколько иначе, чем локальный repo на компьютере. Например commit, который Вы сделали в своей ветке и слили его с главной веткой, не существует в главной ветке репозитория на локальной машине.
Чтобы получить самые последние изменения, которые Вы сделали в удаленном репозитории, или те изменения, которые сделал кто-то другой, используйте команду git pull origin master (когда работаете с primary branch). В большинстве случаев эту команду можно сократить до git pull.
$ git pull origin master
remote: Counting objects: 1, done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (1/1), done.
From https://github.com/microsindotnet/STM32F407-Blink
* branch master -> FETCH_HEAD
b345d9a..5381b7c master -> origin/master
Merge made by the 'recursive' strategy.
mnelson.txt | 1 +
1 file changed, 1 insertion(+)
Это покажет Вам все файлы, которые изменены, и как они были изменены. Теперь мы можем использовать команду git log, чтобы посмотреть все новые commit-ы.
Примечание: может понадобиться переключиться обратно на главную ветку(primary branch). Это делается командой git checkout master.
[]
[Ссылки]
1. An Intro to Git and GitHub for Beginners (Tutorial) site:hubspot.com. 2. Join GitHub Create your account site:github.com. 3. Краткий справочник по Git. 4. The Linux command line for beginners site:ubuntu.com. 5. Renaming the default branch from master site:github.com.