Перевод второй части статьи «How to Use Git and Git Workflows – a Practical Guide».
В первой части статьи мы рассмотрели установку Git и настройку аккаунта на GitHub, создание нового репозитория на GitHub, клонирование репозитория, ветвление. Также мы научились просматривать текущее состояние проекта и сделали свой первый коммит.
В этой части мы рассмотрим:
- Как запушить коммит на GitHub
- Добавляем еще один коммит в Git
- Как вносить изменения в стейджинг
- Как просматривать разницу между изменениями в Git
- Совместная работа в Git
- Ветки отдельных функций в Git
Как запушить коммит на GitHub
У нас есть новый коммит на нашей локальной машине. Теперь нам нужно обновить наш «источник истины» — удаленный origin
-репозиторий (GitHub).
В настоящее время локально мы находимся в ветке main
. Нам нужно сообщить GitHub-у, чтобы он обновил собственную ветку main
этим новым коммитом.
Для этого используется команда git push
(push — «толкать, пихать»). Мы можем указать, куда именно мы хотим запушить коммит и в какую конкретно ветку.
(main)$ git push origin main Enumerating objects: 4, done. Counting objects: 100% (4/4), done. Delta compression using up to 16 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 326 bytes | 326.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0) To github.com:johnmosesman/practical-git-tutorial.git 2592324..a8f8b95 main -> main
Здесь мы запушили изменения в origin
(GitHub), в ветку main
.
Вывод команды сообщает нам об операциях с файлами, которые пришлось совершить Git, а последняя строка говорит о том, какие коммиты были запушены и куда:
To github.com:johnmosesman/practical-git-tutorial.git 2592324..a8f8b95 main -> main
Мы видим, что мы запушили нашу ветку main
в ветку main
на GitHub.
Если мы посмотрим лог проекта (git log
), мы заметим, что теперь ветки main и в локальном репозитории, и в origin нацелены на один и тот же коммит.
(main)$ git log commit f5b6e2f18f742e2b851e38f52a969dd921f72d2f (HEAD -> main, origin/main, origin/HEAD) Author: John Mosesman <johnmosesman@gmail.com> Date: Mon Mar 22 10:07:35 2021 -0500 Added the intro line to chapter 1
В общем, в origin
(GitHub) в ветке main
(origin/main
) последним коммитом в истории теперь выступает наш коммит.
Если бы мы работали совместно с другими людьми, они теперь могли бы вытащить последние изменения из GitHub-репозитория на свои машины и тоже начать редактировать Главу 1.
Добавляем еще один коммит в Git
Прежде чем приступить к теме коллаборации, давайте внесем еще одно маленькое изменение. Посмотрим, что происходит, когда мы редактируем уже существующий файл.
Добавим в наш текстовый файл еще одну строку:
(main)$ echo "It was the best of times, it was the worst of times" >> chapter-1.txt (main)$ cat chapter-1.txt Chapter 1 - The Beginning It was the best of times, it was the worst of times
Команда cat
позволяет нам просмотреть файл. Мы видим, что теперь в нем две строки.
Давайте еще раз проверим статус нашего Git-репозитория:
(main)$ git status On branch main Your branch is up to date with 'origin/main'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: chapter-1.txt no changes added to commit (use "git add" and/or "git commit -a")
В самом верху написано, что наша ветка полностью соответствует origin/main
.
Это может показаться странным, ведь мы только что изменили файл. Но здесь Git сравнивает только коммиты, которые мы совершили, с коммитами в origin/main
(а не изменения вообще).
В следующем разделе дается немного больше информации:
Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: chapter-1.txt
Git сообщает, что у нас есть изменения, не подготовленные к коммиту. И прежде чем мы сможем сделать коммит набора правок, нам сначала нужно подготовить их, внеся в стейджинг.
Как вносить изменения в стейджинг
Чтобы показать всю пользу стейджинга, давайте внесем в него наши изменения при помощи команды git add
:
(main)$ git add . (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) modified: chapter-1.txt
Теперь эти изменения готовы к коммиту. Но прежде чем сделать коммит, давайте изменим кое-что в файле chapter-1.txt.
Я полностью заменю содержимое этого файла новым текстом.
Примечание. Я использую оператор перенаправления >
, а не >>
. Первый заменяет содержимое файла новым содержимым, а второй добавляет текст в конец существующего файла.
(main)$ echo "New file contents" > chapter-1.txt (main)$ cat chapter-1.txt New file contents (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) modified: chapter-1.txt Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: chapter-1.txt
В выводе git status
мы видим, что у нас есть и подготовленные, и неподготовленные изменения («Changes to be committed» и «Changes not staged for commit»).
Хотя в самом файле содержится один вариант текста, Git отслеживает для нас оба изменения. Даже несмотря на то, что это изменения одних и тех же строк!
Но приведенный выше вывод команды не дает нам информации о том, что это были за изменения. Мы знаем лишь об их существовании.
Чтобы просмотреть эти изменения, давайте сначала воспользуемся командной строкой (сам я никогда не применяю ее с этой целью), а затем используем GUI (что куда удобнее).
Как просматривать разницу между изменениями в Git
Чтобы увидеть изменения, нам нужно просмотреть в Git diff.
diff (сокр. от difference, «разница») — это разница между двумя наборами изменений. Это может быть разница между подготовленными и неподготовленными изменениями или же разница между коммитами.
Чтобы посмотреть diff в командной строке, используется команда git diff
.
Мы рассмотрим этот маленький пример чисто для полноты картины. Но нас интересует эффективная работа с Git. А когда ваши изменения приобретают достойный объем и разбросаны по множеству файлов, пользоваться командной строкой для их просмотра становится неудобно.
(main)$ git diff diff --git a/chapter-1.txt b/chapter-1.txt index 0450d87..4cbeaee 100644 --- a/chapter-1.txt +++ b/chapter-1.txt @@ -1,2 +1 @@ -Chapter 1 - The Beginning -It was the best of times, it was the worst of times +New file contents
Мой терминал пытается расцвечивать результат для улучшения читаемости. В выводе команды мы видим название файла, который изменился (chapter-1.txt), а под ним — собственно изменения. Давайте обратим внимание на следующие строки:
-Chapter 1 - The Beginning -It was the best of times, it was the worst of times +New file contents
Строки, начинающиеся со знака минус (-
), — это строки, которые мы полностью удалили. Строки, начинающиеся со знака плюс (+
) — те, которые мы добавили.
Когда у вас много файлов и много изменений в каждом, этот вывод быстро становится неудобочитаемым. Есть лучший способ просматривать изменения — при помощи графического интерфейса. Моей карьере уже почти десять лет, но я все равно для просмотра diff-ов пользуюсь простой программой с GUI.
Программа, которой пользуюсь я, называется GitX. Она давно вышла в тираж и уже даже не поддерживается. Но для просмотра diff-ов годится.
Я не то чтобы рекомендовал вам именно эту программу, но она бесплатная, так что можете попробовать. Еще есть десктопный клиент для GitHub. Сам я никогда им не пользовался, но это, вероятно, хороший вариант.
Итак, после этого маленького отступления, давайте посмотрим, как выглядит diff в моем инструменте.
Для начала, с правой стороны, в подготовленных изменениях мы видим наше вставленное второе предложение:
В неподготовленных изменениях с левой стороны мы видим полное удаление двух строк и добавление новой строки:
Это соответствует тем командам, которые мы выполняли.
При помощи программы с графическим интерфейсом разобраться в изменениях куда проще. Эта программа также позволяет быстро переключаться между подготовленными и неподготовленными файлами, просто перетаскивая их. Я даже могу вернуть из стейджинга отдельные строки в файле.
Использование командной строки в данном случае не дает никаких дополнительных преимуществ, но вы можете пользоваться тем инструментом, который вам больше нравится.
Итак, мы рассмотрели, как работает стейджинг и Git diff. Теперь давайте сбросим наши неподготовленные изменения, чтобы вернуться и закоммитить наше первое изменение.
Последний вывод git status
, собственно, подсказывал нам, что мы можем это сделать при помощи команды git restore
. Мы можем передать этой команде путь к файлу или поставить точку, чтобы «захватить» всю директорию.
(main)$ git restore .
Если мы проверим статус еще раз, мы увидим, что вернулись к нашим подготовленным изменениям и готовы к коммиту.
Примечание. Git позволяет коммитить только те изменения, которые находятся в стейджинге (т. е. подготовленные). Поэтому мы могли бы оставить неподготовленные изменения в нашей рабочей директории и это никак не помешало бы процедуре коммита.
Но в таком случае нам было бы менее удобно работать с изменениями в будущем, так что имело смысл просто сбросить ненужное, чтобы рабочая директория была в хорошей форме.
Давайте, наконец, закоммитим эти изменения, добавив сообщение о том, что именно мы сделали:
(main)$ git commit -m "Added the intro line to chapter 1" [main f5b6e2f] Added the intro line to chapter 1 1 file changed, 1 insertion(+)
Проверяем статус проекта еще раз и видим, что наша ветка на 1 коммит опережает origin/main
:
(main)$ git status On branch main Your branch is ahead of 'origin/main' by 1 commit. (use "git push" to publish your local commits) nothing to commit, working tree clean
Давайте теперь запушим изменения:
(main)$ git push origin main
Совместная работа в Git
Пока мы рассматривали простейший случай: работу одного человека в одной ветке.
Но обычно над проектами работают по нескольку человек, и веток у них может быть много. И тут проявляется настоящая мощь Git: эта система делает возможным сотрудничество и отслеживание изменений во времени.
Пока давайте продолжим работать так, как будто мы — единственный человек в проекте, но немного подгоним наш рабочий процесс, чтобы подготовиться к изменению ситуации.
В целом, хорошим тоном считается НЕ работать напрямую в ветке main
.
Главная ветка призвана быть «источником истины» для проекта, и изменения, вносимые в нее, должны тщательно проверяться. Любое изменение в origin/main
становится источником истины для любого человека, работающего над этим проектом, поэтому все изменения вносятся обдуманно и после код-ревью.
Вместо того чтобы работать непосредственно в main
, давайте сделаем ответвление и создадим собственную ветку для того функционала, над которым работаем (feature branch). Все внесенные изменения мы потом сольем (смержим, merge
) обратно в main.
Многовато терминологии. Давайте будем продвигаться постепенно, разбирая каждый шаг.
Ветки отдельных функций в Git
Для начала давайте сделаем ответвление main
и создадим отдельную ветку для нашей функции.
Делая ответвление ветки, вы создаете копию этой ветки в ее состоянии на текущий момент. После этого вы можете вносить любые изменения в свою ветку, и это не отразится на исходной.
Чтобы это проверить, давайте создадим новую ветку chapter-2. Для этого мы используем команду git checkout
с флагом -b
и указываем имя новой ветки:
(main)$ git checkout -b chapter-2 Switched to a new branch 'chapter-2' (chapter-2)$
Обратите внимание, что в строке предложения терминал теперь показывает название новой ветки, chapter-2. Изменения, которые мы внесем в chapter-2, никак не заденут main
. У нас по сути появилась новая песочница, где мы можем менять что угодно, не рискуя навредить main.
«Под капотом» здесь происходят любопытные вещи, но для целей этого руководства нам нужно лишь знать, что в Git «checkout» означает «сделай так, чтобы мой локальный проект выглядел в точности так же, как весь проект выглядел в определенный момент». Можете считать, что ветка — указатель, указывающий на определенный момент в Git-истории.
При этом происходит много всего другого, но пока вам хватит и этого определения.
Итак, у нас есть новая ветка и пока что она идентична main
(мы же еще не вносили никаких изменений).
Теперь давайте повторим то, что мы уже делали прежде. Создадим новый файл chapter-2.txt, поместим в него кое-какой контент и закоммитим:
(chapter-2)$ touch chapter-2.txt (chapter-2)$ echo "Chapter 2 - The next chapter" >> chapter-2.txt (chapter-2)$ git status On branch chapter-2 Untracked files: (use "git add <file>..." to include in what will be committed) chapter-2.txt nothing added to commit but untracked files present (use "git add" to track) (chapter-2)$ git add . (chapter-2)$ git commit -m "Creates chapter 2 and adds the topic sentence" [chapter-2 741822a] Creates chapter 2 and adds the topic sentence 1 file changed, 1 insertion(+) create mode 100644 chapter-2.txt
Тут ничего нового, все то же, что и с Главой 1.
Теперь у нас в ветке chapter-2 есть новый коммит. Давайте посмотрим, как выглядит лог проекта.
(chapter-2)$ git log commit 741822a9fd7b15b6e3caf437dd0617fabf918449 (HEAD -> chapter-2) Author: John Mosesman <johnmosesman@gmail.com> Date: Mon Mar 22 10:33:26 2021 -0500 Creates chapter 2 and adds the topic sentence commit f5b6e2f18f742e2b851e38f52a969dd921f72d2f (origin/main, origin/HEAD, main) Author: John Mosesman <johnmosesman@gmail.com> Date: Mon Mar 22 10:07:35 2021 -0500 Added the intro line to chapter 1 commit a8f8b95f19105fe10ed144fead9cab84520181e3 Author: John Mosesman <johnmosesman@gmail.com> Date: Fri Mar 19 12:27:35 2021 -0500 New chapter 1 file with chapter heading ...
В логе мы видим, что последний коммит показывается сверху, а HEAD
опять отличается от origin
. И это естественно, ведь наших локальных изменений еще нет на GitHub.
Теперь нам нужно вставить наши новые изменения в ветку main
. Этим мы займемся в следующей части.
[customscript]techrocks_custom_after_post_html[/customscript]
[customscript]techrocks_custom_script[/customscript]