Перевод первой части статьи «How to Use Git and Git Workflows – a Practical Guide».
Все говорят, что разработчику нужно знать Git — и это правда. Но будем откровенны: Git не так прост.
Моей карьере разработчика уже почти десять лет, но я все еще изучаю этот инструмент и приемы эффективной работы с ним.
Недавно я даже понял, что весьма превратно понимал одну ключевую команду, которой пользовался бессчетное число раз.
Я считаю, что как и многие другие вещи в программировании, Git лучше всего изучать на практике. Начните пользоваться инструментом — и постепенно освоите и основы, и продвинутый функционал.
В этом руководстве мы именно так и поступим. Чтобы изучить Git с нуля и понять, как с его помощью осуществляется коллективная работа, мы разберем несколько практических примеров.
Мы будем использовать простые команды и разбирать стоящие за ними концепции — но только в том объеме, который способствует лучшему пониманию.
Безусловно, в этой статье мы не сможем рассмотреть все аспекты работы с Git, но более сложные вещи вы освоите самостоятельно в процессе работы.
Также отмечу, что я не буду использовать древовидные схемы (такие, как на иллюстрации снизу). Дело в том, что лично меня они всегда только сбивали с толку, и то, что я никогда не представлял себе Git именно таким образом, не помешало мне стать продуктивным разработчиком.
В первой части статьи мы рассмотрим следующие темы:
- Как установить Git и настроить аккаунт на GitHub
- Как создать новый репозиторий на GitHub
- Как клонировать Git-репозиторий
- Ветки в Git
- Как посмотреть состояние проекта в Git
- Как сделать первый коммит
Я советую вам испытывать все описываемые команды самостоятельно, на вашей машине. Итак, начнем!
Как установить Git и настроить аккаунт на GitHub
Начнем с рутинных, но необходимых вещей.
Если вы уже установили Git на своей машине, завели аккаунт на GitHub (или GitLab, или Bitbucket) и настроили SSH-соединение, то этот раздел можно пропустить.
Если нет, для начала нужно установить Git.
В этом туториале мы будем использовать GitHub. Зарегистрироваться на этом сайте можно по ссылке.
Заведя аккаунт, нужно создать SSH-ключ. Это позволит вам отправлять ваш код с вашей локальной машины на GitHub (при помощи ключа GitHub будет проверять, что вы — это вы). Это не сложно: просто следуйте инструкции.
Как создать новый репозиторий на GitHub
Следующее, что нам нужно сделать, это создать репозиторий на GitHub.
Это просто. Нажмите кнопку «New» на вашей домашней странице:
Затем выберите имя для репозитория и укажите, будет он приватным или публичным. Опционально можно добавить файл README. Затем нажмите кнопку «Create repository».
Свой репозиторий я назвал practical-git-tutorial. В нем содержатся все шаги, описанные в этом руководстве, так что при желании можете пользоваться им как справочником.
Как клонировать Git-репозиторий
Чтобы начать работать, нам нужно «клонировать» репозиторий. Клонирование означает скачивание из источника всего кода проекта, а также метаданных. Источником в нашем случае является GitHub.
Чтобы клонировать репозиторий, используйте команду git clone <URL>
.
В примере я использовал URL репозитория, который только что создал, а вам нужно подставить URL вашего.
Примечание: команды, которые нужно запускать в терминале, предваряются значком $.
$ git clone git@github.com:johnmosesman/practical-git-tutorial.git Cloning into 'practical-git-tutorial'... remote: Enumerating objects: 6, done. remote: Counting objects: 100% (6/6), done. remote: Compressing objects: 100% (3/3), done. remote: Total 6 (delta 0), reused 0 (delta 0), pack-reused 0 Receiving objects: 100% (6/6), done.
Позднее мы рассмотрим git clone
более подробно. Пока просто знайте, что после выполнения этой команды проект будет загружен на вашу машину и размещен в отдельной папке в вашей текущей рабочей директории.
Давайте перейдем в папку проекта (при помощи команды cd
):
$ cd practical-git-tutorial/ /practical-git-tutorial (main)$
Мы перешли в папку проекта (это обычная папка, такая же, как все остальные). Ваш терминал может выводить рядом с именем папки слово (main)
.
Ветки в Git
Наличие (main)
рядом с именем папки означает, что в настоящее время мы находимся в ветке под названием main. Что такое ветка (англ branch)? Считайте, что это копия проекта в определенный момент времени, которую можно изменять независимо от других веток.
Рассмотрим пример. Если бы мы писали книгу, у нас могли бы быть следующие ветки:
main
branch (главная ветка)table-of-contents
branch (ветка содержания)chapter-1
branch (ветка первой главы)chapter-2
branch (ветка второй главы)- и так далее.
Ветка main
— главная. Это место, где мы будем собирать все содержимое воедино, в законченную книгу.
Создавая дополнительные ветки, мы можем разделять нашу работу на сколь угодно много частей, а затем отслеживать их по отдельности.
Допустим, я работаю над Главой 1, а вы — над Главой 2. Мы можем создать две разные ветки, chapter-1
и chapter-2
, каждая из которых будет отдельной копией текущего состояния книги.
Это даст нам возможность работать над своими главами по отдельности, не наступая друг другу на ноги и без риска случайно перезаписать написанное коллегой. У каждого будет своя рабочая копия.
Когда один из нас закончит работу над своей главой, он сможет добавить содержимое этой главы обратно в ветку main
. Когда мы оба закончим работу, в ветке main будет и Глава 1, и Глава 2.
Несмотря на все, что я сказал, временами коллеги все же перезаписывают изменения, внесенные товарищами по команде, или меняют один и тот же кусок кода, и тогда им приходится утрясать различия. Но об этом позже.
Примечание. Главная ветка может называться не main
, а master
: это зависит от проекта. Функциональной разницы нет.
Как посмотреть состояние проекта в Git
Работая над проектами, мы довольно часто проверяем их состояние и смотрим, какие изменения были внесены.
Чтобы просмотреть статус нашего проекта, мы используем команду git status
:
(main)$ git status On branch main Your branch is up to date with 'origin/main'. nothing to commit, working tree clean
Давайте разберем вывод команды.
Первое, что нам сообщает git status
, это то, что мы находимся в ветке main
:
On branch main
Второе предложение немного интереснее:
Your branch is up to date with 'origin/main'.
Git сообщает, что наша ветка полностью соответствует некоему origin/main
.
Это новая концепция. origin
(или remote) — удаленный источник, т. е., находящийся не на вашей локальной машине.
В этом проекте у нас есть наша локальная копия проекта. Но мы также могли бы добавить удаленные источники, с которыми тоже работаем.
Вернемся на момент к нашему примеру с книгой. Если бы я писал Главу 1 на своей машине, а вы — Главу 2 на вашей машине, мы могли бы добавить себе компьютеры друг друга в качестве удаленных источников, чтобы обмениваться внесенными изменениями. Ведь одно из главных достоинств Git — контролируемое сотрудничество с другими людьми.
На практике сообщество разработчиков в целом пришло к выводу, что лучше не обмениваться изменениями в стиле «все-со-всеми», а иметь единый источник истины для кода. Текущее состояние кодовой базы в этом источнике считается «правильным», а все остальные с ним сверяются. По соглашению это место называется origin (англ. начало, источник).
В нашем случае origin — репозиторий на GitHub.
На самом деле мы можем посмотреть, что у нас считается origin, запустив команду git remote -v
(-v
означает «verbose»: информация будет выводиться «многословно», подробно).
(main)$ git remote -v origin git@github.com:johnmosesman/practical-git-tutorial.git (fetch) origin git@github.com:johnmosesman/practical-git-tutorial.git (push)
Эта команда выводит список всех наших удаленных репозиториев. Мы видим, что у нас есть удаленный репозиторий с именем origin
, а его Git URL указывает на наш репозиторий на Github.com. Это было настроено автоматически, когда мы запустили git clone.
Но вернемся к выводу команды git status
:
Your branch is up to date with 'origin/main'.
Когда мы запросили статус проекта, Git ответил, что наша локальная ветка main
полностью соответствует ветке main
в нашем origin
(GitHub).
Git «увидел», что в origin
, который мы клонировали, в качестве главной ветки была ветка main
. И команда git clone
автоматически создала для нас локальную ветку main
.
В общем, на нашей локальной машине не внесено никаких изменений, которых нет на GitHub, и наоборот. Наша локальная ветка main
и ветка main
в репозитории на GitHub идентичны.
Когда мы внесем какие-нибудь изменения, в выводе команды git status
сообщение уже будет другим. Оно будет отражать разницу между нашим локальным репозиторием и репозиторием origin
(GitHub).
Последнее сообщение git status касается состояния локального проекта:
nothing to commit, working tree clean
Мы вернемся к этому чуть позже, когда внесем какие-нибудь изменения. Но в общем это предложение говорит о том, что мы еще ничего не сделали, так что нет никаких изменений, о которых следовало бы сообщить.
Подобьем итоги. Выполнив команду git status
, мы узнали следующие вещи:
- мы находимся в ветке
main
- наша локальная ветка main идентична ветке
main
вorigin
(GitHub) - мы еще не внесли никаких изменений в проект.
Как сделать первый коммит
Теперь, когда мы разобрались с начальным состоянием проекта, давайте внесем какие-нибудь изменения и посмотрим на результат.
Продолжая аналогию с написанием книги, давайте создадим новый файл chapter-1.txt и вставим в него какой-то текст.
(Вы можете выполнить в терминале команды, указанные ниже, или просто создать файл в любом текстовом редакторе).
(main)$ touch chapter-1.txt (main)$ echo "Chapter 1 - The Beginning" >> chapter-1.txt (main)$ cat chapter-1.txt Chapter 1 - The Beginning
Мы создаем файл chapter-1.txt при помощи команды touch
и вставляем в него текст «Chapter 1 — The Beginning» при помощи команды echo
и оператора перенаправления. Чтобы проверить результат, выводим содержимое файла на экран при помощи команды cat
.
У нас есть простой текстовый файл с маленьким текстом.
Давайте теперь запустим git status
и посмотрим, что изменится в выводе.
(main)$ git status On branch main Your branch is up to date with 'origin/main'. Untracked files: (use "git add <file>..." to include in what will be committed) chapter-1.txt nothing added to commit but untracked files present (use "git add" to track)
Да, кое-что определенно изменилось. Мы видим раздел, описывающий «Untracked files» («Неотслеживаемые файлы»), в котором есть наш файл chapter-1.txt.
Прежде чем Git начнет отслеживать изменения в файле, нам сначала нужно сказать ему делать это. И, как написано в конце сообщения, для этого можно использовать команду git add
:
(main)$ git add chapter-1.txt
(Можно не указывать конкретное имя, а просто поставить точку. Таким образом будут «захвачены» все изменения в директории).
Давайте еще раз проверим статус проекта:
(main)$ git status On branch main Your branch is up to date with 'origin/main'. Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: chapter-1.txt john:~/code/practical-git-tutorial (main)$
Сообщение снова изменилось. Теперь в нем говорится, что у нас есть некоторые изменения, готовые к «закреплению» — коммиту.
В Git коммит — это сохраненный кусочек работы. Но это сохранение отличается от сохранения файла в текстовом редакторе.
Можно считать, что коммит — это завершенная идея или юнит работы.
Вернемся к аналогии с книгой. Если бы мы продолжили писать первую главу книги, это могло бы выглядеть так:
- Написать название главы. /Нажать кнопку «Сохранить» в редакторе/
- Написать первый абзац. /Снова нажать кнопку «Сохранить»/
- Написать второй абзац. /«Сохранить»/
- Написать последний абзац. /«Сохранить»/
Мы «сохранили» документ четыре раза, но после этих четырех сохранений у нас на руках первый черновик нашей главы, а этот черновик — один «юнит» нашей работы.
Мы хотим сохранить этот файл на своем компьютере. Но кроме этого мы также хотим обозначить, что это — юнит завершенной работы (несмотря на то, что всего лишь черновик). Это кусочек труда, который стоит того, чтобы его хранить. Возможно, мы вернемся к нему в будущем и отредактируем. А может, соединим этот черновик с черновиком всей книги.
Чтобы обозначить эту веху, мы создаем новый коммит. Каждый коммит получает собственный уникальный идентификатор. Порядок коммитов фиксируется.
Чтобы закоммиттить наши изменения, сначала их нужно внести в зону стейджинга (подготовки) при помощи команды git add
.
(О стейджинге мы еще поговорим).
Затем нам нужно завершить сохранение изменений при помощи команды git commit.
Считается хорошим тоном добавлять описание того, какие именно изменения вы внесли и, что более важно, — зачем вы это сделали.
Когда в истории собираются сотни или даже тысячи коммитов, становится практически невозможно понять, почему было сделано то или иное изменение. Невозможно — если, конечно, не оставлять хороших сообщений коммитов. Git покажет нам, какие файлы изменились и что за изменения были внесены, но мы должны написать в сообщении о том, какую смысловую нагрузку несут эти изменения.
Давайте закоммитим новый файл с сообщением. Чтобы добавить сообщение, припишем к команде флаг -m
(от message).
(main)$ git commit -m "New chapter 1 file with chapter heading" [main a8f8b95] New chapter 1 file with chapter heading 1 file changed, 1 insertion(+) create mode 100644 chapter-1.txt
Мы сохранили этот кусочек работы и можем увидеть это, просмотрев лог Git при помощи команды git log
:
(main)$ git log commit a8f8b95f19105fe10ed144fead9cab84520181e3 (HEAD -> main) Author: John Mosesman <johnmosesman@gmail.com> Date: Fri Mar 19 12:27:35 2021 -0500 New chapter 1 file with chapter heading commit 2592324fae9c615a96f856a0d8b8fe1d2d8439f8 (origin/main, origin/HEAD) Author: John Mosesman <johnmosesman@users.noreply.github.com> Date: Wed Mar 17 08:48:25 2021 -0500 Update README.md commit 024ea223ee4055ae82ee31fc605bbd8a5a3673a0 Author: John Mosesman <johnmosesman@users.noreply.github.com> Date: Wed Mar 17 08:48:10 2021 -0500 Initial commit
Глядя на этот лог, мы видим, что у нас в истории проекта есть три коммита.
Последний из них — тот, который мы только что сделали. Мы видим наше сообщение коммита.
До него было еще два коммита: один был сделан, когда я инициализировал проект, а второй — когда обновил файл README.md на GitHub.
Обратите внимание, что к каждому коммиту прилагается длинная строка чисел и букв:
commit a8f8b95f19105fe10ed144fead9cab84520181e3 (HEAD -> main)
Эта строка называется SHA. Это уникальный ID, сгенерированный для коммита при помощи алгоритма хеширования. Пока просто обратите на него внимание, а позже мы к нему вернемся.
После SHA коммитов мы видим еще пару интересных вещей:
(HEAD -> main)
рядом с последним коммитом(origin/main, origin/HEAD)
рядом с предпоследним коммитом.
Это говорит нам о текущем статусе нашей ветки и удаленных веток (насколько он нам известен).
Что касается последнего коммита, мы видим, что HEAD
указывает на нашу локальную ветку main
(HEAD -> main
). HEAD — это указатель на текущую ветку.
Это имеет смысл. Мы только сделали коммит и пока больше ничего не делали. Мы все еще во временной точке этого коммита.
Если мы посмотрим на предыдущий коммит, начинающийся с 25923, мы увидим рядом с ним (origin/main, origin/HEAD)
. Это говорит нам о том, что в origin
(GitHub) HEAD
указывает на наш предыдущий коммит.
В общем, наша машина думает, что последнее изменение в локальной ветке main
— коммит с добавленной Главой 1. Также наша машина думает, что на GitHub последнее изменение — коммит, которым я обновил README перед написанием этой статьи.
И это понятно: мы же не сообщали GitHub-у о самом последнем нашем коммите. GitHub все еще думает, что репозиторий соответствует текущему состоянию проекта.
Конец первой части. В следующей части мы отправим наш новый коммит на GitHub.
[customscript]techrocks_custom_after_post_html[/customscript]
[customscript]techrocks_custom_script[/customscript]
Спасибо за перевод понятного и подробного объяснения работы с GitHub!!!
Это очень крутая статья!! Все просто и понятно. Спасибо большое за то, что изложили такую ценную информацию доступно для понимания новичка!)
«Чтобы клонировать репозиторий, используйте команду git clone .»
Где?