
Мы продолжаем курс по системе контроля версий git. Сегодня разберемся, как работать с ветками. Ветки позволяют работать над кодом так, чтобы на время разработки, основная версия проекта оставалась без изменений.
Представьте, что у вас есть код, который работает. В какой-то момент вы решили добавить в него изменения. Работа над изменениями может занять некоторое время, в какой-то момент код может даже перестать работать. А вам нужно, чтобы в любой момент можно было воспользоваться рабочей версией проекта. В таких ситуациях могут помочь ветки.
Как настроить отображение веток
Git изначально настроен на работу с ветками. Когда мы создавали репозиторий, у нас автоматически появилась ветка main, в которую и коммитились все наши изменения. Важно всегда понимать, в какой ветке мы сейчас находимся. В git для этого есть понятие current branch.
Откроем терминал по адресу нашей папки. На Windows вы сразу увидите, в какой ветке находитесь. На mac это нужно настроить.
Создадим файл: touch ~/.zchrc.
Откроем ее: open ~/.zchrc.
Введем в открывшийся редактор кусок кода:
function parse_git_branch() {
git branch 2> /dev/null | sed -n -e 's/^\* \(.*\)/[\1]/p'
}
COLOR_DEF=$'\e[0m'
COLOR_USR=$'\e[38;5;243m'
COLOR_DIR=$'\e[38;5;197m'
COLOR_GIT=$'\e[38;5;39m'
setopt PROMPT_SUBST
export PROMPT='${COLOR_USR}%n ${COLOR_DIR}%~ ${COLOR_GIT}$(parse_git_branch)${COLOR_DEF} $ '
Сохраним изменения в файле и вернемся в терминал.
Вводим команду source ~/.zchrc. Обозначение ветки появилось.
Когда в следующий раз будем открывать терминал, достаточно ввести только последнюю команду.


Как создать ветку в Git
Представим, что мы хотим добавить в код input, чтобы пользователь вводил свое имя с клавиатуры. Пробовать изменения мы будем в отдельной ветке.
Создать новую ветку можно с помощью команды git branch <название ветки>. Важно, чтобы название было понятным для вас и других участников проекта.
Создадим новую ветку для проекта: git branch input.
Переключимся на новую ветку с помощью команды git checkout input. (Чтобы создать ветку и переключиться на нее за одно действие, можно воспользоваться флагом -b: git checkout -b <название ветки>.)
Внесем изменения в наш файл в ветке input. Для этого перейдем в редактор. Пусть код запрашивает имя пользователя, а потом здоровается с ним.
Добавим в начало запрос на ввод: name = input("What's your name? ")
И изменим первую строку вывода: print("Hello, ", name,"!")


Проверим, как работает наш код. Для этого нужно нажать на значок play в верхнем правом углу редактора. Код сначала просит нас ввести имя, а потом выводит нужную информацию. Изменения удались.

Закоммитим изменения: git commit -a -m “Add input”.
Проверим git status, убедимся, что рабочее дерево чистое. Проверим историю: git log. Видим весь путь работы: последнее изменение и все изменения, которые были еще до ответвления. Чтобы выйти из истории, нужно нажать q в английской раскладке.

Вернемся в основную ветку с помощью команды git checkout main и зайдем в редактор. Изменения пропали, потому что в основную ветку мы их еще не добавляли. Проверяем историю: git log. В ветке main видим только старые коммиты, до ответвления.

Как сливать ветки и решать конфликты
Когда мы сделали все нужные изменения в коде, проверили, что они работают так, как мы хотим, можно переносить изменения в основной код.
Сначала нужно переключиться на основную ветку: git checkout main.
Теперь можем забрать изменения из ветки input: git merge --no-ff <название ветки, изменения из которой забираем> -m “Сообщение о слиянии веток”.
Такая команда создаст новый коммит, в котором объединятся две ветки.
Флаг --no-ff отменяет механизм fast-forward, который стоит в git по умолчанию. Если его не отменить, git не будет создавать новый коммит, в котором объединятся две ветки, а просто сделает дополнительную ветку веткой main. Иногда такой механизм полезен, но сейчас он нас запутает, поэтому отключаем его. Вы можете поэкспериментировать и посмотреть, в какой ситуации какой механизм вам больше подходит.
В нашем случае git понял, как нужно совместить две ветки. Проверим редактор, чтобы убедиться, что результат тот, который нам нужен.


Иногда Git не понимает, как именно нужно объединить ветки и выводит сообщение о конфликте. В таких ситуациях, мы должны показать ему это. Для этого переходим в редактор, удаляем лишние символы и приводим код к тому виду, который нам нужен. Сохраняем файл в редакторе, проверяем git status — увидим сообщение о конфликте. Чтобы показать Git, что мы разрешили конфликт, просто закоммитим изменения: git commit -a -m «Add input in main».
Проверим историю: git log. Если видим сообщение о коммите, в котором сливаются две ветки, значит, все получилось.

Историю изменений, создания новых веток и слияния можно визуализировать: git log --oneline --graph.
Звездочкой показан каждый коммит, мы видим, что происходило на каждом шаге, в какой момент появилась новая ветка и что мы в ней делали, в какой момент слили ветки.

Как залить изменения на GitHub
Отправляем изменения на удаленный репозиторий: git push.
Проверяем GitHub. Изменения появились, но залилась только ветка main. Другие ветки нужно заливать отдельно: git push -u origin <название ветки>.
Зальем ветку input: git push -u origin input. Видим, что на GitHub появились две ветки. Переключиться между ветками можно в меню branch.

Как перемещаться по коммитам
Еще один важный указатель в git — это head. Он указывает, на какой ветке мы находимся. Если мы перейдем в историю, увидим, что head указывает на ветку main и на удаленную ветку origin_main. Это значит, наш локальный и удаленный репозитории синхронизированы.
Перейдем на другую ветку командой git checkout input, и в истории head будет указывать уже на input.


Мы можем перейти не только на другую ветку, но и на отдельный коммит. Будто перенестись в прошлое и посмотреть, как работал наш код на одном из этапов разработки. Сначала переключимся на основную ветку.
Посмотрим историю изменений: git log --oneline. (Эта команда дает более компактное отображение истории по сравнению с git log.)
Переходим на один из первых коммитов: git checkout <первые символы кода идентификатора>. Head уже будет указывать на отдельный коммит, а в редакторе код тоже вернулся на тот этап.


С помощью таких перемещений по коммитам, мы можем искать ошибки, понимать, в какой момент код работал хорошо, а с какого этапа что-то пошло не так. Мы можем даже вносить изменения на этом этапе, но для этого нужно создать отдельную ветку.
Создадим новую ветку и переключимся на нее в одно действие с помощью флага -b: git checkout -b calc.
Добавим изменения в редактор: допишем строку 2+2. Сохраняем изменения в редакторе.
Добавим файл в отслеживание и коммитим изменения: git commit -a -m “Add calculation”.
Вернемся в основную ветку: git checkout main. Посмотрим все ветки: git branch. Видим, что появилась новая ветка calc.

Сделаем визуализацию наших изменений: git log --oneline --graph --all. Видим, что со второго коммита ответвилась еще одна ветка.

Как удалить ветку в Git
Если мы понимаем, что ветка больше не нужна, можно ее удалить. При этом удаляемая ветка не должна быть той веткой, в которой мы находимся. Удалим ветку calc: git branch -d calc. Git предупреждает, что ветка еще не объединена с основной веткой и что удалять ее опасно. Но мы уверены, что хотим удалить ветку, поэтому вводим еще одну команду, которую нам подсказывает git: git branch -D calc.
Теперь удалим ветку input. Она уже залита на GitHub, поэтому сначала удалим ее с удаленного репозитория: git push --delete origin input
Проверим Git Hub: ветка удалилась. Теперь удаляем ветку локально: git branch -d input.
Проверим наши ветки: git branch. Ветки удалились, осталась только ветка main.

Если по ходу работы у вас появляются ошибки, попробуйте найти решение в интернете. Часто достаточно скопировать полученную ошибку и вбить ее в поиск в браузере. Если все же не получается найти ответ, пишите нам в чате в Telegram.