Skip to content

Latest commit

 

History

History
885 lines (597 loc) · 55.5 KB

File metadata and controls

885 lines (597 loc) · 55.5 KB

Лекция 7. Git. История системы контроля версий. Локальный репозиторий. Базовые команды управления репозиторием.

Оглавление курса

Блок 1 — Python Basic (1–6)
Блок 2 — Git (7–8)
Блок 3 — Python Advanced (9–14)
Блок 4 — SQL (15–17)
Блок 5 — Django (19–26)
Блок 6 — Django Rest Framework (27–30)
Блок 7 — Python async (31–33)
Блок 8 — Deployment (34–35)

drawing

Сегодня мы поговорим о системе контроля версий Git, одной из самых популярных и широко используемых систем для управления исходным кодом. В ходе лекции мы рассмотрим исторический контекст, который привёл к созданию Git, основные этапы его развития, а также причины появления необходимости в системах контроля версий.

Система контроля версий — что это и зачем? Была ли у вас ситуация, когда вы работаете над дипломом в университете или над каким-то файлом для своего проекта, и в какой-то момент у вас на компьютере уже несколько файлов с названиями вроде: финал.docx, финал_01.docx, финал_01_точно_финал.docx, финал_последний.docx, финал_последний_c_изображениями.docx? Так вот, когда вы работаете с кодом, файлов у вас может быть очень много, и людей, которые вносят новые правки, тоже может быть очень много. Для того чтобы всё это контролировать, нужна система контроля версий.

Зачем Git и VCS

Прежде чем перейти к истории создания Git, важно понять, почему вообще возникла необходимость в системах контроля версий. С развитием программного обеспечения и увеличением числа разработчиков, работающих над одним проектом, стали очевидны следующие проблемы:

  1. Отслеживание изменений: Когда несколько разработчиков работают над одним и тем же файлом, необходимо отслеживать, кто и какие изменения внес. Без этого легко запутаться в версиях и потерять важные правки.
  2. Совместная работа: В больших проектах требуется синхронизация работы множества разработчиков, распределение задач и объединение результатов их работы.
  3. История изменений: Важно иметь возможность вернуться к предыдущим версиям кода, чтобы понять, что было изменено и когда, а также для восстановления прежней рабочей версии в случае возникновения ошибок.
  4. Резервное копирование: Хранение различных версий кода помогает защититься от потери данных и обеспечить возможность восстановления после сбоев.
  5. Разработка новых функций: Возможность создания изолированных веток для разработки новых функций или исправления ошибок позволяет работать над новыми задачами, не нарушая основной код.

Начало истории

История системы Git начинается в начале 2000-х годов. До появления Git существовали различные системы контроля версий, такие как RCS, CVS и SVN. Эти системы помогали разработчикам отслеживать изменения в коде, работать совместно и управлять различными версиями проектов. Однако каждая из них имела свои недостатки и ограничения. Мы не будем в них углубляться — скорее всего, в современном мире вы никогда с ними и не пересечётесь.

Создание проекта Linux

Важной вехой в истории Git стало создание проекта Linux. Линус Торвальдс, создатель ядра Linux, изначально использовал для управления версиями исходного кода систему BitKeeper. BitKeeper была коммерческой системой контроля версий, предоставлявшей бесплатные лицензии для открытых проектов, таких как Linux.

Однако в 2005 году произошёл конфликт между сообществом разработчиков Linux и компанией, владеющей BitKeeper. Компания прекратила предоставление бесплатных лицензий, что создало необходимость в поиске новой системы контроля версий. Линус Торвальдс, осознав важность независимости от коммерческих решений, решил создать собственную систему контроля версий, которая бы соответствовала требованиям разработки ядра Linux.

Основные требования к новой системе

Перед началом разработки Линус Торвальдс выделил несколько ключевых требований к новой системе контроля версий:

  1. Скорость: Система должна быть быстрой и эффективной при работе с большими объемами данных.
  2. Распределенность: Возможность работы без центрального сервера, что позволяет каждому разработчику иметь свою копию репозитория.
  3. Простота: Простота в использовании и настройке.
  4. Защита данных: Надежное хранение и контроль версий, предотвращение потери данных.

Разработка Git

Проект разработки новой системы контроля версий, названный Git, был начат в апреле 2005 года. Линус Торвальдс в течение нескольких недель создал первоначальную версию Git, которая удовлетворяла всем вышеупомянутым требованиям. Впоследствии к разработке присоединились другие участники сообщества Linux, что позволило значительно улучшить и расширить функциональность системы.

Основные характеристики Git

Git обладает несколькими ключевыми особенностями, которые отличают его от других систем контроля версий:

  1. Система хранения данных: Git использует структуру данных, называемую Directed Acyclic Graph (DAG), для хранения коммитов и веток. Это позволяет эффективно отслеживать изменения и поддерживать целостность данных.
  2. Распределенность: Каждый разработчик имеет полную копию репозитория, что делает систему более устойчивой к сбоям и позволяет работать в автономном режиме.
  3. Работа с ветками: Git предоставляет мощные инструменты для создания и слияния веток, что упрощает работу над новыми функциями и исправлениями.
  4. Скорость: Высокая производительность при выполнении операций, таких как клонирование, коммит и слияние изменений.

Распространение и популяризация

После создания Git быстро завоевал популярность в сообществе разработчиков благодаря своим преимуществам. Многие крупные проекты, включая ядро Linux, начали использовать Git в качестве основной системы контроля версий. В 2008 году был запущен сервис GitHub, предоставляющий платформу для хостинга Git-репозиториев и совместной работы над проектами. Это значительно способствовало распространению Git среди разработчиков по всему миру.

Современное состояние Git

Сегодня Git является де-факто стандартом для управления исходным кодом в индустрии разработки программного обеспечения. Он используется миллионами разработчиков и компаниями по всему миру для управления проектами различного масштаба и сложности. Git продолжает активно развиваться и совершенствоваться, благодаря усилиям сообщества и корпоративных спонсоров.

Локальный репозиторий: базовый цикл

Установка и первичная настройка

Скачать Git: https://git-scm.com/downloads

Проверка версии и базовая настройка:

git --version
git config --global user.name "Ваше Имя"
git config --global user.email "you@example.com"
git config --global init.defaultBranch main

Что такое репозиторий?

Репозиторий Git — это место, где хранятся все файлы и история их изменений для проекта. Репозиторий может быть локальным (на вашем компьютере) или удалённым (на сервере или в облачном хранилище). Вся структура изменений и версий проекта хранится в скрытой папке .git.

Технически репозиторием является папка, в которой вы собираетесь работать и которой вы собираетесь делиться с другими разработчиками.

Инициализация репозитория

Первым шагом при работе с Git является инициализация нового репозитория. Это можно сделать в любой папке с помощью команды:

git init

Эта команда создаст скрытую папку .git, где будут храниться все данные репозитория.

Команды git будут доступны только после установки git на ваш компьютер.

При первом запуске очень вероятно, что система не запустится с первого раза, а сначала попросит предоставить ваше имя/email и, возможно, какие-либо другие данные. Следуйте инструкции из консоли, и после этого всё запустится.

Типы состояний файлов в Git

Это очень важная картинка, с которой нам нужно детально познакомиться.

С точки зрения локального репозитория файлы в нем могут находиться в 4 состояниях:

  1. untracked (неотслеживаемые) — состояние файлов, в котором изменения в файлах не отслеживаются Git, а значит, он не может сказать, были ли в этом файле изменения или нет.
  2. unmodified (неизменённые) — состояние файлов, когда файл отслеживается, но в него не были внесены никакие изменения.
  3. modified (изменённые) — состояние файлов, когда они отслеживаются и Git видит, что файлы были изменены по сравнению с последней версией.
  4. staged (подготовленные) — состояние файлов, когда они отслеживаются, изменены и готовы к тому, чтобы зафиксировать последние изменения в файле как новую, последнюю версию.

Основные наши действия с репозиторием локально — это изменение статусов файлов. Поэтому их очень важно понять.

Создали мы пустой репозиторий — и что с этим делать?

Создавать или модифицировать файлы! Все файлы в вашем репозитории уже будут находиться в одном из состояний, описанных выше.

Просмотр состояния репозитория

Для проверки состояния репозитория и отслеживания изменений используйте команду:

git status

Эта команда покажет, какие файлы были изменены, подготовлены или еще не отслеживаются.

По сути эта команда показывает все файлы в репозитории, которые находятся в любом отличном от unmodified состоянии. Полезно:

  • Краткий вывод: git status -s
  • Посмотреть, что именно попадёт в коммит: git diff --staged

Что делать при создании нового файла?

На самом деле, когда вы создаёте новый файл, он создаётся в состоянии untracked, и пока вы явно не скажете Git отслеживать этот файл, Git будет упорно его игнорировать.

Для добавления файла в систему контроля версий, используется команда

git add filename.txt

где filename.txt — это название файла.

Эта же команда очень часто используется для добавления к отслеживанию сразу всего, что вообще найдётся в этой папке. Для такого случая можно использовать символ ., и тогда Git добавит сразу все файлы, которые найдёт:

git add .

Обратите внимание: если файл был в состоянии untracked и мы применили к нему git add, то этот файл сразу перейдёт в состояние staged.

Если файл находится в состоянии unmodified, то для того чтобы он перешёл в состояние modified, достаточно просто внести в него любые изменения.

Чтобы файл из состояния modified перешёл в состояние staged, к модифицированным файлам необходимо применить ту же команду:

git add filename
git add .

Для одного файла или сразу для всех в папке соответственно.

Зачем были нужны все эти манипуляции, или git commit

Чтобы зафиксировать новые изменения и иметь возможность вернуться к любой версии кода, используется команда

git commit -m "commit_message"

git commit — это команда, которая все файлы из состояния staged переводит в состояние unmodified, при этом полностью сохраняя всю историю изменений под уникальным номером и с возможностью возвращаться к этой версии, если нам будет необходимо.

Команда commit требует указать какой-либо текст с описанием, что именно это за изменения. Их можно указать после флага -m, либо Git попросит указать этот текст интерактивно.

Первый совершённый в репозитории коммит называется инициализационным, и на его основе выполняются различные действия. Рекомендую сразу аккуратно к нему относиться и не вносить мусор уже в первый коммит.

А что после коммита?

Всё повторяется: изменяем существующие файлы или добавляем новые, через команду git add переводим файлы в состояние staged и при помощи команды git commit фиксируем изменения.

История и просмотр

Чтобы увидеть историю коммитов, используйте команду:

git log --oneline --graph --decorate --all
git log

Примечание (DAG): ключ --graph визуализирует ориентированный ациклический граф коммитов. Каждый коммит указывает на своих родителей; merge‑коммиты имеют нескольких родителей.

Эта команда покажет список всех коммитов с комментариями, датами, авторами изменений и их уникальными номерами.

Ветки и переключение

Когда мы делаем новый коммит, Git сохраняет историю изменений и, кроме этого, запоминает, какой коммит был предыдущим перед новым (помните, у них у всех есть номера).

Этим свойством можно пользоваться: раз каждый коммит помнит, кто был его родитель, значит, мы всегда, пройдя вверх по родителям, можем выйти на самый первый коммит. А это значит, что мы можем создавать разветвления и различные версии в нашем коде.

Примечание (DAG): история коммитов — ориентированный ациклический граф: вершины = коммиты, рёбра = ссылки на родителей. Циклов нет, потому что каждый коммит указывает на более ранние.

Зная это, мы можем после одного коммита сделать несколько разных, и у всех из них будет один и тот же родитель. Таким образом мы получим несколько различных версий кода, которые имеют только общего предка. Такой «набор» коммитов от изначального до какой-либо версии называется словом ветка, и мы можем их контролировать.

Ветка — это именованный указатель на вершину DAG (последний коммит). Перемещение указателя меняет «где мы на графе», не меняя прошлые узлы.

На самом деле ветка не содержит в себе «набор» — ветка это всего лишь ссылка на конкретный коммит. А уже сам коммит хранит в себе информацию о его родителях, за счёт чего и появляется возможность вычислить любого предка вплоть до самого первого initial commit.

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

Зачем нам вообще нужны ветки? Ветки позволяют проводить работу изолировано от всего остального. Например, мы разрабатываем какую-то новую функциональность.

Самый правильный подход при выполнении любой разработки — создавать новую ветку под новую функциональность и выполнять коммит в любом месте, где изменения в коде уже работают и имеют хоть какой-то законченный вид. В реальности чаще всего любое новшество создаётся в новой ветке, и дальше всё зависит от размера этого новшества, но обычно такие ветки содержат от 1 до 20 коммитов.

А к какой ветке относится initial commit и все остальные, которые мы уже делали?

Отличный вопрос!

На самом деле, когда мы инициализировали Git, он за нас автоматически создал ветку. У такой ветки обычно может быть одно из двух названий: master или main.

На заре Git все базовые ветки всегда назывались master, но так как в 2010-х годах был скандал, связанный с толерантностью, во многих местах пришлось переименовать всё, где использовались слова master и slave, ведь они переводятся как «господин» и «раб» соответственно. Хотя всё ещё в огромном количестве мест вы можете увидеть именно эти слова.

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

Для создания новой ветки используется команда git branch branch_name, где branch_name — это название новой ветки:

git branch new-feature

Как только вы это сделали, у вас ничего не поменялось, кроме того, что на текущий коммит была сделана ещё одна ссылка. Но если вы сделаете ещё один коммит, он всё ещё будет связан с веткой master, потому что для того чтобы выполнять изменения в новой ветке, нужно не только её создать, но и переключиться на новую ветку.

Чтобы переключиться на новую ветку, выполните:

git checkout new-feature

Также существует сокращённая запись, когда мы хотим создать и переключиться на новую ветку одновременно:

git checkout -b newone

Современная альтернатива:

git switch -c newone   # создать и переключиться
git switch my-branch   # переключиться на существующую

где newone — это название новой ветки, которую мы хотим создать и сразу в неё переключиться.

Слияние веток (merge)

После завершения работы над новой функцией или исправлением необходимо слить ветку с основной — ради этого мы всё и затевали.

Примечание (DAG): merge создаёт новый узел в графе с несколькими родителями. Точка слияния вычисляется относительно общего предка (см. git merge-base).

Переключитесь на основную ветку и выполните команду слияния:

git checkout main
git merge new-feature

Эта команда выполнит слияние указанной ветки с той веткой, в которой вы в этот момент находитесь.

Что значит слияние? Это значит, что Git найдёт первый коммит, который для двух веток является общим, после чего попытается «наложить» коммиты из вашей ветки поверх основной и создать ещё один коммит под названием merge-commit. Он создаётся при слиянии.

Перебазирование веток (rebase)

Очень полезная команда. Выполняет подстановку коммитов из другой ветки в текущую, начиная с места разветвления.

Посмотрите на рисунок. Если ваша текущая ветка отстаёт от другой ветки, вы всегда можете «подровнять» ветки путём вызова команды git rebase:

git rebase master

Обратите внимание: в отличие от merge действие выполняется в обратном порядке. Хотя технически всегда действие выполняется от указанной ветки к текущей.

Примечание (DAG): rebase переписывает часть графа — «переподвешивает» цепочку коммитов на новый базовый узел. Создаются новые коммиты с новыми хешами; старые могут стать недостижимыми (см. также git reflog).

Важно: не выполняйте rebase веток, которые уже опубликованы или используются другими, — это переписывает историю и может сломать работу коллег.

Интерактивная игра

У Git существует ещё огромное количество команд, мы не будем изучать их все. Но в качестве домашнего задания к этому занятию я хочу, чтобы вы прошли вот ЭТУ игру.

Она знакомит нас с основными командами и понятиями Git.

В дальнейшем я предполагаю, что этот материал пройден, так что как минимум ознакомиться крайне рекомендую.

Конфликты

Самая неприятная вещь при работе с Git — это конфликты. Предположим, в одной ветке мы изменили какую-то функцию, а потом в другой ветке изменили её же и пытаемся слить обе ветки в третью. В таком случае у нас обязательно возникнет конфликт, потому что Git не может понять, какой именно вариант кода мы считаем правильным.

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

git add conflict-file.txt
git commit -m "Resolved merge conflict"

Работа с файлами

Просмотр различий

Чтобы увидеть различия между текущими изменениями и последним коммитом, используйте команду:

git diff

Эта команда покажет, какие строки были добавлены или удалены.

Восстановление изменений (restore)

Современная команда для отката незакоммиченных правок и снятия из индекса:

git restore <file>          # убрать незастейдженные изменения в рабочей копии
git restore --staged <file> # снять файл из индекса, оставить правки в рабочей копии

Раньше для восстановления часто использовали git checkout -- <file>, сейчас рекомендуется git restore.

Удаление файлов

Чтобы удалить файл из репозитория и системы, используйте команду:

git rm example.txt

Для удаления файла только из индекса, оставив его в файловой системе, выполните:

git rm --cached example.txt

Игнорирование файлов (.gitignore)

Иногда (почти всегда) необходимо игнорировать определённые файлы или директории. Для этого создайте файл .gitignore в репозитории и добавьте в него шаблоны для игнорируемых файлов. Например:

*.log
node_modules/
.DS_Store

Пример для Python-проектов:

__pycache__/
*.py[cod]
*.pyo
*.pyd
venv/
.env
*.env
.coverage
.dist/
dist/
build/
.idea/
.vscode/

Глобальный .gitignore (для всех репозиториев на машине):

git config --global core.excludesfile ~/.gitignore_global

Что такое HEAD?

HEAD — это указатель на текущую ветку и последний коммит в этой ветке. Проще говоря, HEAD показывает, где вы находитесь в дереве изменений вашего репозитория в данный момент.

Представьте HEAD как закладку в книге. Когда вы переключаетесь между ветками или коммитами, HEAD меняет своё положение, указывая на соответствующий коммит.

Как работает HEAD?

Модель DAG: HEAD через ветку указывает на текущую вершину графа (коммит). В режиме detached HEAD указывает прямо на вершину без имени ветки.

В Git HEAD обычно указывает на ветку, а ветка, в свою очередь, указывает на коммит. В файле .git/HEAD содержится ссылка на файл, представляющий текущую ветку. Если вы откроете этот файл, то увидите что-то вроде:

ref: refs/heads/main

Это означает, что HEAD указывает на ветку main. Когда вы делаете новый коммит, указатель HEAD автоматически перемещается на этот новый коммит.

Типы HEAD

В Git существует два состояния HEAD:

  • Указывает на ветку (обычное состояние):

В этом случае HEAD указывает на ветку, и любое действие, которое вы совершаете, будет относиться к этой ветке. Например, при коммите HEAD и указатель ветки будут двигаться вперёд.

  • Отсутствие привязки к ветке (detached HEAD):

Это состояние, когда HEAD указывает непосредственно на коммит, а не на ветку. Обычно это происходит, когда вы переключаетесь на конкретный коммит с помощью команды git checkout <commit-hash>. В таком состоянии любые изменения и коммиты не будут привязаны к какой-либо ветке.

Основные команды работы с HEAD.

Проверка текущего состояния HEAD:

git log --oneline --decorate

Эта команда покажет список коммитов и укажет, на каком из них находится HEAD.

Переключение между ветками:

git checkout <branch-name>

Эта команда переместит HEAD на указанную ветку.

Переключение на конкретный коммит (detached HEAD):

git checkout <commit-hash>

Это переместит HEAD на указанный коммит без привязки к ветке.

Создание новой ветки и переключение на неё:

git checkout -b <new-branch-name>

Эта команда создаст новую ветку и переместит HEAD на неё.

reset / revert / restore

Что такое git reset?

git reset — это мощная команда в Git, которая позволяет перемещать указатель текущей ветки и опционально изменять состояние индекса (staging area) и рабочего каталога. Основная цель этой команды — отменить изменения или переместить HEAD на другой коммит.

Примечание (DAG): reset перемещает указатели (ветку/HEAD) по графу и может «оторвать» часть истории от текущей ветки. revert не меняет прошлые узлы DAG — он создаёт новый коммит, отменяющий изменения, сохраняя историю целостной.

Синтаксис команды git reset

git reset [<mode>] [<commit>]

Где <mode> — это один из трёх режимов работы команды, а <commit> — это ссылка на коммит, к которому вы хотите переместить HEAD.

Режимы работы git reset

  1. --soft:

    • Перемещает HEAD к указанному коммиту.
    • Индекс и рабочий каталог остаются неизменными.
    • Используется для отмены последних коммитов, сохраняя изменения для повторного коммита.
    git reset --soft <commit>
  2. --mixed (по умолчанию):

    • Перемещает HEAD к указанному коммиту.
    • Индекс сбрасывается до состояния указанного коммита.
    • Рабочий каталог остаётся неизменным.
    • Используется для отмены коммитов и удаления изменений из индекса, оставляя их в рабочем каталоге.
    git reset --mixed <commit>
  3. --hard:

    • Перемещает HEAD к указанному коммиту.
    • Индекс и рабочий каталог сбрасываются до состояния указанного коммита.
    • Используется для полной отмены коммитов и всех изменений в рабочем каталоге и индексе.
    git reset --hard <commit>

Примеры использования git reset

  1. Отмена последнего коммита, сохраняя изменения для повторного коммита:

    git reset --soft HEAD~1
    # HEAD перемещается на один коммит назад, изменения сохраняются в индексе
  2. Отмена последнего коммита и удаления изменений из индекса:

    git reset --mixed HEAD~1
    # HEAD перемещается на один коммит назад, изменения остаются в рабочем каталоге
  3. Полная отмена последнего коммита и всех изменений:

    git reset --hard HEAD~1
    # HEAD перемещается на один коммит назад, все изменения отменяются
  4. Перемещение HEAD на конкретный коммит:

    git reset --hard <commit-hash>
    # HEAD перемещается на указанный коммит, состояние репозитория возвращается к этому коммиту
  5. Отмена нескольких последних коммитов:

    git reset --hard HEAD~3
    # HEAD перемещается на три коммита назад, все изменения отменяются

Важные замечания при использовании git reset

  • Режим --hard: Будьте особенно осторожны при использовании этого режима, так как он удаляет все несохранённые изменения в рабочем каталоге и индексе, и их нельзя будет восстановить.
  • Резервное копирование: Перед выполнением git reset --hard рекомендуется создать резервную копию текущего состояния репозитория или создать новую ветку для сохранения изменений.

Альтернативы git reset

В некоторых случаях другие команды могут быть более подходящими для вашей задачи:

  • git revert: Используйте для отмены конкретных коммитов, создавая новые коммиты с противоположными изменениями. Это сохраняет историю изменений.

    git revert <commit>
  • git checkout: Используйте для переключения веток или возврата к определённому коммиту в состоянии detached HEAD.

    git checkout <commit>
  • git restore: Используйте для восстановления файлов из коммита или индекса без изменения состояния ветки или истории.

    git restore --source=<commit> --staged --worktree <file>

Команда git reset — это мощный инструмент для управления историей коммитов и состоянием репозитория в Git. Понимание различных режимов работы этой команды и их правильное использование поможет вам эффективно управлять изменениями и сохранять чистую историю вашего проекта. Всегда помните о последствиях использования git reset и выбирайте наиболее подходящий инструмент для вашей задачи.

Cherry-pick

Что такое git cherry-pick?

git cherry-pick — это команда Git, которая позволяет перенести изменения из одного или нескольких коммитов в текущую ветку. Эта команда создаёт новые коммиты в текущей ветке с теми же изменениями, что и в выбранных коммитах, сохраняя их идентичность.

Синтаксис команды git cherry-pick

Примечание (DAG): cherry‑pick «копирует» изменения из одного узла графа в другой — создаётся новый коммит в текущей ветке.

git cherry-pick [options] <commit-hash>...

где <commit-hash> — это идентификаторы коммитов, которые вы хотите перенести.

Основные опции git cherry-pick

  • -e или --edit: Открыть редактор для изменения сообщения коммита перед созданием нового коммита.
  • -n или --no-commit: Применить изменения, но не делать новый коммит автоматически.
  • -x: Добавить строку в сообщение коммита, указывающую на оригинальный коммит.
  • --continue: Продолжить выполнение cherry-pick после разрешения конфликтов.
  • --abort: Прервать операцию cherry-pick и вернуть ветку в исходное состояние до начала операции.
  • --skip: Пропустить коммит, вызвавший конфликт, и продолжить выполнение cherry-pick.

Примеры использования git cherry-pick

  1. Применение одного коммита в текущую ветку:

    git cherry-pick abc123
    # Применить изменения из коммита abc123 в текущую ветку
  2. Применение нескольких коммитов в текущую ветку:

    git cherry-pick abc123 def456 ghi789
    # Применить изменения из коммитов abc123, def456 и ghi789 в текущую ветку
  3. Применение диапазона коммитов:

    git cherry-pick abc123..def456
    # Применить изменения из всех коммитов в диапазоне от abc123 до def456 (исключая abc123)
  4. Применение коммита с редактированием сообщения:

    git cherry-pick -e abc123
    # Применить изменения из коммита abc123 и открыть редактор для изменения сообщения коммита
  5. Применение коммита без автоматического создания нового коммита:

    git cherry-pick -n abc123
    # Применить изменения из коммита abc123, но не делать новый коммит автоматически
  6. Применение коммита с добавлением ссылки на оригинальный коммит:

    git cherry-pick -x abc123
    # Применить изменения из коммита abc123 и добавить строку в сообщение коммита с ссылкой на оригинальный коммит

Разрешение конфликтов при git cherry-pick

Иногда при выполнении команды git cherry-pick могут возникать конфликты. В таких случаях Git остановит выполнение и предоставит возможность вручную разрешить конфликты.

  1. Разрешение конфликтов:

    • Откройте файлы с конфликтами и внесите необходимые изменения.
    • Добавьте исправленные файлы в индекс с помощью команды git add.
  2. Продолжение выполнения cherry-pick:

    git cherry-pick --continue
    # Продолжить выполнение cherry-pick после разрешения конфликтов
  3. Прерывание выполнения cherry-pick:

    git cherry-pick --abort
    # Прервать операцию cherry-pick и вернуть ветку в исходное состояние

Примеры ситуаций для использования git cherry-pick

  1. Перенос фикса ошибок в другие ветки:

    • Вы обнаружили ошибку в основной ветке и исправили её, создав коммит. Теперь вы хотите перенести это исправление в релизную ветку.
  2. Выборочное применение изменений:

    • Вы работаете над несколькими задачами в одной ветке, но хотите перенести только некоторые из них в другую ветку.
  3. Слияние отдельных изменений:

    • Вы хотите объединить только определённые изменения из одной ветки в другую, без выполнения полного слияния веток.

Команда git cherry-pick — мощный инструмент для выборочного применения изменений из одного или нескольких коммитов в текущую ветку. Понимание работы этой команды и её правильное использование помогут вам эффективно управлять изменениями в вашем проекте и поддерживать чистую историю коммитов.

Домашнее задание

Всё ещё пройдите вот это.

Практика

  • Инициализируйте репозиторий: git init
  • Настройте имя и email: git config --global user.name "Ваше Имя", git config --global user.email you@example.com
  • Создайте файл, пройдите путь untracked → staged → committed: echo hello > readme.txt, git add readme.txt, git commit -m "init"
  • Внесите изменения и изучите их: git diff, затем заиндексируйте и закоммитьте: git add -p, git commit -m "update readme"
  • Посмотрите историю компактным графом: git log --oneline --graph --decorate --all
  • Создайте ветку и переключитесь: git switch -c feature; измените файл и закоммитьте.
  • Смоделируйте конфликт: вернитесь в main, измените ту же строку, закоммитьте; затем попробуйте git merge feature и разрешите конфликт, завершив слияние (git add …, git commit).
  • Попробуйте отменить один коммит: git revert <hash> (или git revert HEAD)
  • Аккуратно продемонстрируйте перепривязку коммита: git reset --soft HEAD~1 (коммит «снимется», изменения останутся в индексе), затем сделайте новый коммит.

← Лекция 6: Алгоритмы и структуры данных | Лекция 8: Git. Удаленный репозиторий. Remote, push, pull. GitHub, Bitbucket, GitLab, etc. Pull request. →