Ветки в git

Ветки нужны для параллельной разработки. Ответвление от master версии позволяет вести разработку независимо от нее и, потом слить ветку разработки в master.

Создание новой ветки

git checkout -b test-branch
 
#Можно также переключаться на коммиты по их хэшу 

Ключ -b создает новую ветку и уже потом переключается на нее, ибо git checkout это, по сути, команда для переключения между ветками. Таким образом, без этого ключа можно переключаться между ветками. Эта команда, по сути, “выполняет роль” двух других команд:

git branch test-branch  # Создаем новую ветку
git checkout test-branch  # Переключаемся на нее
# то есть, можно и их использовать вместо checkout с ключом -b, но одной командой быстрее
 
#переключиться на прошлую ветку можно так:
git checkout -

git status покажет на какой ветке ты находишься.

После коммита, если заглянуть в git log , можно увидеть в скобках ветку, на которой сделан коммит.

Предположим, ты сделал коммит в test-branch и запущенный там же git log покажет инфу о коммите. Но, переключившись на main и запустив там git log , этого коммита уже не будет, ибо сделан он был не в main. В то же время в test-branch можно будет увидеть коммиты main-а, ибо первый ответвился от него и, естественно, содержит и его коммиты.

После коммита на side ветках, вернувшись в main, можно заметить, что изменений нет, ибо они закоммитись только на side ветках.

Список веток выводится командой:

git branch  # Зеленой будет помечена текущая ветка

Работа с удаленными ветками

Отправка local branch на upstream

При попытке push-нуть коммиты с local branch на upstream branch (удаленная ветка) вылезет ошибка, в которой говорится, что удаленной ветки нет, пушить некуда. В той же ошибке git рекомендует воспользоваться командой, чтобы создать удаленную ветку:

git push --set-upstream origin test-branch
# --set-upstream это тот же -u
# так что можно просто:
git push -u origin test-branch
 
# stdout
# Branch 'test-branch' set up to track remote branch 'test-branch' from 'origin'.
# Что означает:
# Ответвление 'test-branch' настроено на отслеживание удаленного ответвления 'test-branch' от 'origin'.

Имя upstream branch-а может не совпадать с local, но лучше остерегаться этого, как минимум, чтобы не запутаться.

Затягивание upstream branch в local

Рассматриваем вариант, где есть remote repo с удаленной веткой, которой нет в local.
Выполняем git pull и в stdout получаем инфу о наличии новой ветки, но git branch пока что ее не покажет. Чтобы настроить отслеживание между local и upstream ветками, нужно перейти на ветку по имени, которое нам показала git pull :

git checkout test-upstream-branch
 
# stdout
# Branch 'test-upstream-branch' set up to track remote branch 'test-upstream-branch' from 'origin'.
# Switched to a new branch 'test-upstream-branch'

И теперь в git branch можно увидеть эту ветку, стянутую с remote repo.

А посмотреть все ветки (удаленные и локальные) можно так:

git branch -a  # a - all
# Зеленые - локальные, красные - удаленные
 
# И можно посмотреть к каким удаленным веткам привязаны локальные:
git branch -vv
 
# Или удалить ветку
git branch -D branch-name

Откладывание изменений

Это может понадобиться, если во время работы вам, например, понадобилось поработать над чем-то другим, а коммитить не вариант (потому что принято коммитить только законченные изменения) и в то же время, допустим, не вариант переключиться на другую ветку.

Сделанные изменения можно отложить так:

git stash
 
# stdout
# Saved working directory and index state WIP on test-upstream-branch: 22a32de test
# Что значит:
# Всё в рабочей директории сохранено в статусе WIP (Work in Progress - Работа в процессе)

Изменения ‘пропали’, но они вернуться, если запустить git stash pop . Теперь можно делать другие изменения, даже над тем же файлом, изменения которого мы отложили; делаем. Допустим, мы закоммитили эти изменения и теперь вернемся к отложенным изменениям командой:

git stash pop

Git сделает auto merge этих изменений (изменения из коммита и из stash-а) по возможности либо предложит тебе заняться этим.

stash-ить можно и не один раз. Все стэши можно посмотреть командой git stash list , а при возвращении этих изменений они будут возвращаться от последнего к первому.
Можно удалять стэши командой git stash drop 0 , где 0 - это номер стэша, который можно узнать при выведении списка стэшей (между фигурными скобками).

Перенос изменений на другую ветку

Может понадобиться, если по ошибке начали делать изменения в неправильной ветке. Вот последовательность действий:

# Делаем изменения
git stash
git checkout branch-name  # Переходит на нужную ветку
git stash pop  # Возвращаем изменения на эту ветку

Слияние веток

Делаем параллельные коммиты, то есть коммит, допустим, в test-branch и в main. И, находясь, допустим, на main, сливаем ее с test-branch:

git merge test-branch

Если изменения относительно простые, то git сделает auto merge и отправит этот коммит на сервер (merge, по сути, похож на коммит). А если изменения сложные, то git предложит вам вручную исправить всё и сделать коммит, чтобы merge был выполнен.


Конфликты

Это ситуации, при которых git не может слить изменения автоматически. Они происходят при выполнении команд, при которых происходит слияние. Вот основные конфликтные пацаны:

git merge
git stash pop
git pull

При возникновении конфликта слияния выскакивает ошибка такого содержания:

Auto-merging 1.txt
Пытается автоматически слить изменения

CONFLICT (content): Merge conflict in 1.txt
Конфликт, связанный с содержимым (content). Конфликт слияния в файле

Automatic merge failed; fix conflicts and then commit the result.
Не смог автоматически слить; просит исправить конфликты и закоммитить

Чтобы решить конфликт - надо:

  1. Исправить содержимое файла (лучше в VSCode)
  2. Выполнить git add <file>, чтобы дать понять git-у, что конфликт с содержимым решен
  3. И выполнить git commit без -m, ибо git сам напишет свой дефолтный merge message

Если нужно отменить merge, то:

git reset --merge

Pull/merge request

Это запрос на слияние ветки с основной (базовой) веткой проекта. Как правило, pull request-ы владельцу repo кидают разрабы, когда выполнили свою задачу на своей ветке, проверили всё и хоть слить свою ветку в master.

Запрос создается, к примеру, в github во вкладке Pull requests (там всё интуитивно понятно). При создании могут возникнуть конфликты слияний - их там же можно решить и создать pull request. После создания запрос появится в списке запросов во вкладке Pull requests (там запросы бывают в двух статусах: open и closed).

Под названием запроса есть инфа о создателе запроса и о том, что и куда будет вливаться. Ниже есть 4 вкладки: Conversations - обсуждение запроса, Commits - коммиты ветки, Checks - всякие auto проверки кода, Files changed - здесь можно посмотреть, какими будут итоговые изменения после слияния.
Во вкладке Files changed можно наводя мышку на строки (и нажав на появившийся “плюс”) добавить комментарии к любой строке и там же начать обсуждение.
В самом низу, когда всё проверено и принято решение одобрить запрос, можно это сделать тремя способами:

  1. Сделать обычный merge (все коммиты будут добавлены к базовой ветке через обычный merge commit)
  2. Squash здесь означает сжать все коммиты разраба в один и уже потом слить всё (это применимо к ситуации, в которой разраб сделал много коммитов и легче их сжать в один, чтобы потом не путаться)
  3. Rebase здесь означает перебазирование, то есть, коммиты ветки сольются в базовую ветку так, будто они там и делались (тоже делается для упрощения истории коммитов в проекте)

После подтверждения pull request-а появится сообщение о его закрытии (он будет в статусе closed в той самой вкладке):

Так как мы всё слили и side ветка уже не нужна, github предлагает нам удалить ее. Нажатием на эту кнопку можно здесь же удалить side ветку.


Модели ветвления

Они нужны для быстрого deployment-а (быстрого выката в продакшн) и для сохранения единых принципов работы в команде.

Есть две основные модели ветвления:

Git Flow

и TBD (Trunk Based Development).

Разница
У Git Flow есть несколько постоянных веток: master, develop (может по разному называться), где проходит разработка и от нее выходят в ветки feature (для работы над фичами) release, где сначала код проходит тесты и уже потом вливается в master. Есть также hotfix ветка (понятно предназначение).

У TBD одна постоянная ветка - master, и мелкие side ветки, которые живут недолго. Такая модель быстрее, считается более современной. Также в этой модели можно включать и отключать различные фичи, используя feature flags. !!!Пока мне непонятно как это работает.


git