Основы GIT
Git — распределённая система контроля версий. Локальный репозиторий содержит историю и позволяет делать commits, branches и merges без постоянного соединения с сервером.
Три состояния
working tree --git add--> index --git commit--> repository
^ |
+------ git restore ------+- working tree — файлы, которые редактируются;
- index / staging area — точный набор изменений следующего commit;
- repository — сохранённый граф объектов и ссылок.
git status отвечает, где находится каждое изменение. git diff показывает working tree против index, git diff --staged — index против текущего commit.
Commit
Commit хранит ссылку на snapshot дерева, metadata и родительские commits. Его hash зависит от содержимого объекта. Git умеет переиспользовать одинаковые blobs, поэтому snapshot не означает полную физическую копию каталога на каждый шаг.
git add src/main/java/Example.java
git diff --staged
git commit -m "fix: handle empty response"Хороший commit содержит одно связное изменение и объясняет намерение. Секрет, попавший в commit, остаётся в истории после обычного удаления файла.
Ветки и HEAD
Branch — изменяемая ссылка на commit. HEAD обычно указывает на текущую branch.
A---B---C main
\
D---E featuregit switch -c feature
git switch main
git branch -vvDetached HEAD означает, что HEAD указывает прямо на commit. Новые commits не потеряны сразу, но для продолжения работы на них нужно создать branch.
Merge
Merge объединяет истории.
- fast-forward — текущая branch просто перемещается вперёд;
- three-way merge — создаётся commit с двумя родителями;
- конфликт возникает, когда Git не может однозначно совместить изменения.
git switch main
git merge featureПосле конфликта редактируют файлы, проверяют результат, выполняют git add и завершают merge commit. Маркеры конфликта нельзя удалять механически без понимания обеих версий.
Rebase
Rebase повторяет commits поверх нового основания:
до: A---B---C main
\
D---E feature
после: A---B---C---D'---E' featuregit switch feature
git rebase mainHashes меняются, потому что меняются parents. Не следует переписывать общую опубликованную историю без договорённости: другим участникам придётся согласовывать свои ветки с новыми commits.
Remote
origin/main — локальная remote-tracking ссылка на последнее известное состояние remote branch.
git fetch origin
git log --oneline --graph --decorate --all
git push -u origin featurefetch загружает объекты и обновляет remote-tracking refs, но не меняет working tree. pull обычно объединяет fetch с merge или rebase согласно настройке.
Отмена изменений
git restore file— убрать незастейдженные изменения файла;git restore --staged file— убрать файл из index, сохранив working tree;git revert <commit>— создать обратный commit, безопасно для общей истории;git reset— переместить ref и, в зависимости от режима, index/working tree;git reflog— найти прежние положения локальных refs.
Перед reset --hard, clean и force push нужно точно понимать область потери. Для опубликованной ветки предпочтительнее revert. Если force push необходим после согласованного rebase, --force-with-lease проверяет, что remote не ушёл вперёд незаметно.
Полезный цикл
git status
git diff
git add -p
git diff --staged
git commit
git fetch
git log --oneline --graph --decorate --allgit add -p позволяет собрать осмысленный commit из отдельных hunks одного файла.
На собеседовании
Чем merge отличается от rebase? Merge сохраняет обе линии истории и добавляет merge commit; rebase создаёт новые commits на другом основании.
Что хранит branch? Имя и ссылку на один commit; история достигается по parent-ссылкам.
Связанные заметки: Что такое Git, Файл gitignore.