Skip to content

Latest commit

 

History

History
290 lines (242 loc) · 35.3 KB

GIT.md

File metadata and controls

290 lines (242 loc) · 35.3 KB

GIT

Основные понятия

  • Система контроля версий (Version Control System) — программное обеспечение, помогает управлять состоянием исходного кода на протяжение всей разработки.
    • система, которая записывает ваши изменения в файл и позже позволяет откатиться к более ранней версии проекта. Также помогает команде эффективно работать надо одними и теми же файлами и синхронизировать свои изменения.
    • бывают распределенные и централизованные (репозиторий хранится на сервере, вносить правки можно только в него, чреез спец. клиента). GIT - распределенный
  • GIT (Global Information Tracker) — разработан Линусом Торвальдсом для управления разработкой ядра Linux.
  • Принцип хранения в GIT — Git хранит полные копии файлов, только заменяя неизмененные файлы на ссылки (многие другие системы хранят только список изменения)
    • Т.е. Git является небольшой файловой системой.
    • Преимущества подхода — при восстановлении данных, работе с комитами и т.д.
    • Недостатки подхода — требует больше места.
  • Repository — место, где Git хранит метаданные и базу данных объектов вашего проекта.
    • Git хранит все изменения в скрытой папке .git, которая есть в каждом проекте, находящемся под контролем VCS.
  • Working Directory — извлечённая из базы копия определённой версии проекта.
  • Staging Area (index) — файл c информацией о том, что должно войти в следующий коммит.
    • Хранится в репозитории Git
    • когда я выполняю git add . — я добавляю данные в index/Staging Area
  • Tree — объект (бинарный файл), который представляет директорию.
    • Хранит ссылки к блобам и деревьям, также указывается SHA1 хэшом.
  • Commit — содержит текущее состояние репозитория.
    • Как и дерево или блоб, коммит хранится в виде SHA1 хэша.
    • Можно понимать коммит, как узел в связном листе.
    • Каждый коммит имеет указатель на своего предка-коммита.
    • Коммит может имет несколько указателей на несколько предков - это значит, что он был создан слиянием веток.
  • Branch — используется для создания новой ветки разработки.
  • Tag — обозначает значимое имя с указанной версией в репозитории.
    • Теги очень похожи на ветки, но отличие в том, что они неизменяемы. Если сделать тег для коммита, то даже если создать новый коммит от данного, то он не обновится.
  • HEAD - указатель/ссылка, обычно указывает на последний комит в текущей ветке.
    • Когда вы делаете комит, то HEAD перемещается на него.
    • HEAD можно переместить на любой другой объект кроме комита.
    • ORIG_HEAD - предыдущее состояние HEAD.
    • git reset - передвигает HEAD в указанное состояние
    • detached HEAD — состояние открепленного указателя HEAD.
      • Может возникнуть при git checkout, если переключиться на коммит.
      • При стандартном процессе разработки указатель HEAD обычно указывает на главную ветку main или другую локальную ветку. Но при переключении на предыдущий коммит HEAD указывает уже не на ветку, а непосредственно на сам коммит. Такая ситуация называется состоянием «открепленного указателя HEAD». Переход к старой версии файла не перемещает указатель HEAD. Он остается в той же ветке и в том же коммите, что позволяет избежать открепления указателя HEAD. После этого можно выполнить коммит старой версии файла в новый снимок состояния, как и в случае других изменений. Соответственно, такое использование команды git checkout применительно к файлу позволяет откатиться к прежней версии отдельного файла.
      • Переход к отдельному коммиту переведет репозиторий в состояние открепленного указателя HEAD. Работа при этом перестает принадлежать какой-либо из веток. При открепленном указателе HEAD все новые коммиты будут оставаться без родителя, пока вы не вернете ветки в положенное состояние. «Сборщик мусора» в Git удаляет коммиты без родителя. Этот сервис работает с определенными интервалами и удаляет такие коммиты без возможности восстановления. Чтобы такие коммиты не были удалены «сборщиком мусора», перед их выполнением нужно убедиться, что мы работаем в ветке.
      • Сообщение «detached HEAD» предупреждает о том, что вся текущая работа «откреплена» от остальной части вашего проекта. Если вы начнете разрабатывать функцию, находясь в состоянии открепленного указателя HEAD, у вас не будет ветки, которая позволила бы вам вернуться к этой функции. Когда вы неизбежно переключитесь на другую ветку (например, чтобы слить код своей функции), вы уже никак не сможете сослаться на свою функцию:


Популярные операции

  • git merge — соединяет две или более истории в одну.

    • объединяет две или более «историй разработки». Сохраняет историю в первозданном виде
  • git rebase — переносит локальные комиты в указанное положение в дереве.

    • повторно применяет коммиты поверх другой базовой ветки. Перезаписывает историю
  • git cherry-pick — переносит изменения, представленные в указанных комитах.

    • Если ведется сложная история разработки, с несколькими длинными ветками разработками, может возникнуть необходимость в применении изменений, внесенных отдельным коммитом одной ветки, к дереву другой (активной в настоящий момент).
  • git reset — передвигает HEAD в указанное состояние

    • позволяет откатить проект до определенной точки.
    • в зависимости от параметра прокидывает нас в истории проекта с соответствующими состояниями индекса.
    • можно использовать с тремя параметрами:
      • git reset --soft <commit>
        • Содержимое вашего индекса, а также рабочей директории, остается неизменным.
        • мы изменим ссылку указателя HEAD на указанный коммит и все изменения, которые были до этого внесены, окажутся в индексе.
      • git reset --mixed <commit>
        • мы изменим ссылку указателя HEAD, но все предыдущие изменения в индекс не попадут, а будут отслеживаться как не занесенные в индекс.
        • Дает возможность внести в индекс только те изменения, которые нам необходимы, что довольно удобно!
      • git reset --hard <commit>
        • мы изменим ссылку указателя HEAD, но все предыдущие изменения не попадут ни в индекс, ни в зону отслеживаемых файлов.
        • Мы полностью сотрем все изменения, которые вносили ранее.
  • git init — создание пустого репозитория или переинициализация существующего.

  • git clone — операция клонирования репозитория.

  • git add — операция индексирования файла (сообщаю Git какие изменения надо внести в историю).

    • Пока я не сделал git add — файл считается «неотслеживаемым». Изменения в нём не попадут в следюущий коммит
  • git commit — записывает изменения в репозиторий (в историю проекта).

  • git status — операция вывода статуса текущего working tree.

    • Показывает какие файлы в проекте отслеживаются Git и какие изменения будут включены в следующий коммит
  • git branch — выводит, создает или удаляет ветки.

  • git checkout — переключается между элементами или откатывает изменения в файлах в рабочей директории.

    • подразумевают переключение между различными версиями целевого объекта (файл, коммит или ветка)
    • откатывает изменения в файле.
    • переходит на указанный объект, например ветку
    • По сути дела просто обновляет указатель HEAD, чтобы он ссылался на указанную ветку или коммит.
    • detached HEAD — состояние открепленного указателя HEAD.
      • Может возникнуть при git checkout, если переключиться на коммит.
      • При стандартном процессе разработки указатель HEAD обычно указывает на главную ветку main или другую локальную ветку. Но при переключении на предыдущий коммит HEAD указывает уже не на ветку, а непосредственно на сам коммит. Такая ситуация называется состоянием «открепленного указателя HEAD». Переход к старой версии файла не перемещает указатель HEAD. Он остается в той же ветке и в том же коммите, что позволяет избежать открепления указателя HEAD. После этого можно выполнить коммит старой версии файла в новый снимок состояния, как и в случае других изменений. Соответственно, такое использование команды git checkout применительно к файлу позволяет откатиться к прежней версии отдельного файла.
      • Переход к отдельному коммиту переведет репозиторий в состояние открепленного указателя HEAD. Работа при этом перестает принадлежать какой-либо из веток. При открепленном указателе HEAD все новые коммиты будут оставаться без родителя, пока вы не вернете ветки в положенное состояние. «Сборщик мусора» в Git удаляет коммиты без родителя. Этот сервис работает с определенными интервалами и удаляет такие коммиты без возможности восстановления. Чтобы такие коммиты не были удалены «сборщиком мусора», перед их выполнением нужно убедиться, что мы работаем в ветке.
      • Сообщение «detached HEAD» предупреждает о том, что вся текущая работа «откреплена» от остальной части вашего проекта. Если вы начнете разрабатывать функцию, находясь в состоянии открепленного указателя HEAD, у вас не будет ветки, которая позволила бы вам вернуться к этой функции. Когда вы неизбежно переключитесь на другую ветку (например, чтобы слить код своей функции), вы уже никак не сможете сослаться на свою функцию.
      • Всегда ведите разработку на ветке, а не на открепленном указателе HEAD. Это гарантия того, что у вас всегда будет ссылка на ваши новые коммиты. Вместе с тем при просмотре предыдущего коммита состояние указателя HEAD не имеет значения: он может быть как откреплен, так и нет.
  • git stash — прячет, достает, очищает изменения в рабочей директории. Что-то вроде «буфера обмена»

  • git fetch — загружает историю из указанного репозитория. Обновит данные только по текущему бранчу.

  • git pull — загружает историю из указанного репозитория и сливает ее с локальной историей. Только для одного бранча. То же самое что git fetch + git merge

  • git push — загружает историю в удаленный репозиторий.

  • git remote — управляет набором отслеживаемых репозиториев.

  • git remote update — обновляет данные из удалённого репозитория по всем локальным бранчам.

  • git reflog — управляет reflog информацией.

    • Выводит упорядоченный список коммитов, на которые указывал HEAD. Отображает историю всех ваших перемещений по проекту.
    • Хранит свою информацию на вашей машине отдельно от коммитов, поэтому при удалении чего-либо в истории, в сможете это найти в git reflog.
    • Если вы вдруг случайно удалили часть истории или откатились назад, вы сможете проинспектировать момент утраты нужной вам информации и откатиться обратно.
  • git revert — отменяет существующие комиты.

  • git clean — удаляет неиндексированные файлы из рабочей директории.

  • Ссылки


Как отменять изменения

  • git checkout

    • перехожу на нужный коммит (git checkout a1e8fb5)
    • создаю от него новую ветку с этими данными, работаю в ней (git checkout -b new_branch_without_some_commit)
    • Теперь репозиторий находится на новой временной шкале, где коммита 872fa7e не существует. На этом этапе мы можем продолжить работу в новой ветке, где коммита 872fa7e не существует и его можно считать «отмененным».
    • К сожалению, если вам нужна предыдущая ветка (возможно, это главная ветка main), такая стратегия не подходит.
  • git revert — Git создаст новый коммит с операцией, обратной последнему коммиту.

    • В текущую историю ветки будет добавлен новый коммит
    • В отличие от нашей предыдущей стратегии переключения с помощью команды checkout, мы можем продолжить работать с этой же веткой, поэтому данная стратегия является удовлетворительной. Это идеальный способ отмены при работе в открытых общих репозиториях, однако если у вас есть требование вести минимальную «очищенную» историю Git, эта стратегия может не подойти.
  • git reset

    • Если мы выполним команду git reset --hard a1e8fb5, история коммитов будет сброшена до указанного коммита.
    • Этот метод отмены изменений оставляет историю максимально чистой.
    • Отлично подходит для локальных изменений, но при работе в общем удаленном репозитории создает сложности.
    • Если у нас есть общий удаленный репозиторий, в котором с помощью команды push опубликован коммит 872fa7e, и мы попытаемся выполнить команду git push для ветки, в которой с помощью команды reset была сброшена история, система Git обнаружит это и выдаст ошибку. Git будет считать, что публикуемая ветка не была обновлена, поскольку в ней отсутствуют коммиты. В таких случаях лучше использовать отмену с помощью команды git revert.
  • git commit --amend — внести правки в последний коммит

  • Ссылки

  • atlassian — Отмена коммитов и изменений


Remote udate, Fetch и Pull

  • git remote update

    • Обновляет данные из удалённого репозитория по всем локальным бранчам.
    • При этом локальные бранчи никак не обновляются и не меняютс
  • git fetch (получать)

    • Обновляет данные только по текущему бранчу.
    • Не вмержит новые изменения, если таковые были в репозитории, в локальный бранч. Локальный бранч не изменит свою историю!
  • git pull

    • Обновляет данные по локальному бранчу + вмержит изменения из репозитория (если они есть).
    • Равносильно выполнению git fetch + git merge
  • Ссылки


Merge и Rebase

Merge (слияние)

  • объединяет две или более историй разработки
  • Сохраняет историю в первозданном виде
  • на графике истории репозитория будет видна другая ветка — история нелинейная

Rebase (перебазирование)

  • повторно применяет коммиты поверх другой базовой ветки.
  • Перезаписывает историю
  • графике истории выглядит одной линией

Способ объединить изменения, сделанные в одной ветке, с другой веткой.
Альтернатива merge.

Последовательно берет все коммиты из выбранной ветки и заново применяет их к новой ветке.

Результат:

  • Переприменяя коммиты, Git создает новые коммиты. Даже если они содержат те же изменения, то рассматриваются Git как новые и независимые коммиты.
  • Git rebase переприменяет коммиты и не удаляет старые. После выполнения rebase ваши старые коммиты продолжат храниться в .git.

Отличие от merge

  • rebase - повторно применяет коммиты поверх другой базовой ветки. Перезаписывает историю
  • merge - объединяет две или более «историй разработки». Сохраняет историю в первозданном виде

Ссылки


Squash

  • Берём серию коммитов и «уплотняем», сжимаем ее.

  • Серию из N коммитов преобразуем в один коммит.

  • Так легче отслеживать историю Git.

  • Повзоляет превратить большое число малозначимых коммитов в небольшое число значимых.

  • Часто используют при объединении ветвей

    • Многие советуют всегда сжимать коммиты и выполнять перебазирование с родительской ветвью (например, master или develop).
    • В таком случае история главной ветки будет содержать только значимые коммиты, без ненужной детализации.
  • Ссылки


Методологии работы с GIT (workflow)

  • Central Workflow
    • Репозиторий содержит только одну главную ветку master. Все изменения комитятся в нее.
    • Репозиторий может быть локальным, без удаленных копий или храниться удаленно, где он может быть клонирован или запушен.
  • Developer Branch Workflow
    • У каждого разработчика есть своя личная ветка или несколько, в которые он пушит. Все его изменения, опубликованные в удаленном репозитории будут в этой ветке.
    • Вся работа может быть выполнена на разных ветках, но потом должна будет слита(merged) в одну главную ветвь.
  • Feature Branch Workflow
    • В своей простейшей форме репозиторий мог бы иметь основную ветку со стабильным, доступным кодом и другими ветками для разных фич (или багов, или улучшений), которые можно бы было интегрировать в главную ветку.
    • То есть репозиторий будет иметь второстепенную основную ветку (dev) которая будет хранить тестируемый стабильный код для отправки пользователям, когда он будет слит с master.
    • В этом случае ветка с фичами будет слита с dev, а не с master.
  • Issue Branch Workflow
    • Очень похожа на предыдущую модель с одним лишь различием. Ветки создаются из заданий в проектном трекере. Ветки могут иметь одинаковые названия id заданий. И здесь только одна ветка на задание и одно задание на ветку.
  • Forking Workflow
    • Благодаря этой модели, дополнения проекта осуществляются путем создания разветвления его репозитория. Все изменения фиксируются в любой ветке репозитория, а затем возвращаются в исходное хранилище с pull запросом. Разработчики будут иметь доступ только к чтению в удаленном репозитории.
  • Patch Workflow
    • Используя этот подход, разработчики добавляют изменения в репозиторий вместе с патчем - файлом, который содержит все изменения в репозитории. Этот патч применяется кем-то, кто может напрямую писать в репозиторий, например maintainer/owner.
  • Git Flow
    • Есть две фиксированные ветви, «стабильный» master и «развивающийся» develop.
    • ветка отпочковывается от develop, если это внесение функционала или подготовка к выпуску новой версии,
    • ветка отпочковывается прямо от master, если это исправление ошибки.
    • После окончания работ тематическая ветвь вливается в её родителя, а в ряде случаев — и в master.
  • GitHub Flow
    • То же, что и Git Flow, но фиксированная ветка всего одна — master; всё остальное принадлежит тематическим ветвям.
    • Тематические ветви создаются в форках — клонированных копиях репозитория. Центральный репозиторий тематических веток не содержит. В том числе и после слияния, так как метки веток при этом снимаются и их головы становятся анонимными.
  • GitLab Flow
    • Как и в GitHub Flow, фиксированная ветка всего одна — master; всё остальное принадлежит тематическим ветвям. Однако, если в том случае релизы размещались в коммитах master-a, то здесь для каждого релиза создаётся своя, отдельная ветка. Причём никакого слияния этих веток с родителем не производится. Если ветка отпочковалась, значит она будет жить своей жизнью, получая исправления ошибок в виде отдельных коммитов (возможно, портированных из головы мастера с учётом накопившейся разницы в функционале между ветками).

Ссылки


Про текстовый редактор для коммитов

  • Я использую nano

Ссылки




*[Legmo, 2019-2023](https://github.com/Legmo/notes/)*