Git Контроль Версий: Полный Технический Справочник для Разработчиков
Git — это распределённая система контроля версий (DVCS), которая записывает снимки файлового дерева проекта с течением времени, позволяя любому количеству участников работать параллельно, не перезаписывая изменения друг друга. Каждый разработчик хранит полную копию репозитория — включая всю историю коммитов — на своём локальном компьютере, что исключает единую точку отказа и обеспечивает полноценную работу в офлайн-режиме.
Созданный Линусом Торвальдсом в апреле 2005 года для замены BitKeeper в разработке ядра Linux, Git был спроектирован с нуля на основе трёх обязательных требований: скорость, целостность данных и поддержка нелинейных распределённых рабочих процессов. Эти принципы по-прежнему определяют то, что принципиально отличает Git от предшественников, и объясняют, почему он остаётся доминирующей VCS уже более двух десятилетий.
Чем Git отличается от централизованных систем контроля версий
Понимание архитектуры Git требует прямого сравнения с централизованными системами, такими как Subversion (SVN) или CVS, где единственный авторитетный сервер хранит канонический репозиторий, а разработчики получают поверхностные рабочие копии.
| Параметр | Git (распределённый) | SVN (централизованный) |
|---|---|---|
| — | — | — |
| Модель репозитория | Полный клон на каждом узле | Тонкая рабочая копия, история хранится на сервере |
| Работа офлайн | Полный commit, branch, diff, log | Только чтение; коммиты требуют сервера |
| Стоимость ветвления | Почти нулевая (манипуляция указателями) | Дорогостоящее копирование директорий |
| Единая точка отказа | Отсутствует — любой клон может восстановить | Сбой сервера останавливает все коммиты |
| Стратегия слияния | Трёхстороннее слияние + rebase | Только трёхстороннее слияние |
| Целостность истории | Хеширование содержимого SHA-1/SHA-256 | Последовательные номера ревизий |
| Зависимость от сети | Только для push/pull/fetch | Почти для каждой операции |
| Частичное извлечение | Не поддерживается нативно | Поддерживается (sparse checkout) |
| Порог вхождения | Более крутая начальная кривая | Мягче для ветеранов SVN |
| Распространённость (2024) | ~95% профессиональных команд | Устаревшие корпоративные среды |
Распределённая модель означает, что даже если хостинговая платформа, такая как GitHub, испытывает сбой, локальный клон каждого разработчика является полной авторитетной резервной копией всей истории проекта.
Основная архитектура: что на самом деле хранит Git
Git не хранит диффы. Он хранит снимки. Каждый коммит указывает на объект дерева, представляющий полное состояние каждого отслеживаемого файла в данный момент. Если файл не изменился между двумя коммитами, Git хранит указатель на предыдущий blob, а не дублирует его — именно так Git достигает одновременно полноты и эффективности хранения.
Четыре фундаментальных типа объектов в хранилище объектов Git (.git/objects/):
- Blob — необработанное содержимое файла, адресуемое по SHA-хешу
- Tree — список директории, сопоставляющий имена файлов с хешами blob или поддеревьев
- Commit — указатель на дерево, ноль или более родительских коммитов, метаданные автора и сообщение
- Tag — аннотированный указатель на конкретный коммит, используемый для маркеров релизов
Каждый объект неизменяем и адресуется по содержимому. Изменение одного байта в любом файле порождает совершенно другой SHA-хеш, который каскадно распространяется вверх по объектам дерева и коммитов. Именно поэтому история Git криптографически защищена от подделки — невозможно незаметно изменить прошлый коммит, не изменив хеши всех последующих коммитов.
Область подготовки (также называемая индексом, хранится в .git/index) — это бинарный файл, содержащий предлагаемый следующий коммит. Эта трёхзонная модель — рабочая директория, индекс, репозиторий — является наиболее непонятой архитектурной особенностью Git и источником большинства затруднений у новичков.
Установка и настройка Git
Перед выполнением каких-либо команд проверьте установку и настройте свою идентификацию. Git встраивает информацию об авторе в каждый объект коммита, а неправильно настроенная идентификация — одна из наиболее распространённых причин запутанной истории коммитов в общих репозиториях.
# Verify installation
git --version
# Set global identity (stored in ~/.gitconfig)
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
# Set default branch name to 'main' (modern convention)
git config --global init.defaultBranch main
# Set preferred editor for commit messages
git config --global core.editor "vim"
# Enable colored output
git config --global color.ui auto
# Verify configuration
git config --listКонфигурация имеет уровни: --system (все пользователи, /etc/gitconfig), --global (текущий пользователь, ~/.gitconfig) и --local (репозиторий, .git/config). Более конкретные области переопределяют более широкие.
Основные команды Git: полный справочник
Инициализация и клонирование
git init создаёт новый репозиторий, записывая директорию .git/ в текущую папку. Коммиты при этом не создаются — репозиторий начинается пустым.
git init
git init my-project # Initialize into a new subdirectory
git init --bare repo.git # Bare repository (no working tree, used for servers)Голый репозиторий содержит только хранилище объектов и refs — без рабочей директории. Это правильный формат для удалённого репозитория, в который выполняют push несколько разработчиков. Если вы самостоятельно размещаете Git на сервере VPS Hosting, всегда инициализируйте общие репозитории как голые.
git clone создаёт полную локальную копию удалённого репозитория, включая все ветки, теги и историю.
git clone https://github.com/user/repo.git
git clone git@github.com:user/repo.git # SSH transport (preferred for auth)
git clone --depth 1 https://github.com/user/repo.git # Shallow clone (latest commit only)
git clone --branch develop https://github.com/user/repo.git # Clone specific branchПоверхностные клоны (--depth) полезны для CI/CD-конвейеров, где нужно только последнее состояние, а не полная история. Они значительно сокращают время клонирования больших репозиториев, но препятствуют некоторым операциям, зависящим от истории, например git bisect.
Проверка состояния
git status — наиболее часто выполняемая команда в любом рабочем процессе. Она показывает трёхзонное состояние вашего репозитория.
git status
git status -s # Short format: two-column status codes
git status -sb # Short format with branch infogit diff сравнивает содержимое между зонами или коммитами.
git diff # Working directory vs. index (unstaged changes)
git diff --staged # Index vs. last commit (what will be committed)
git diff HEAD # Working directory vs. last commit (all changes)
git diff main..feature # Compare tips of two branches
git diff abc123..def456 # Compare two specific commits
git diff --stat # Show changed files and line counts onlygit log обходит граф коммитов. Его параметры фильтрации — одни из наиболее мощных и недооценённых возможностей Git.
git log
git log --oneline --graph --decorate --all # Visual branch graph
git log -p # Show patch (diff) for each commit
git log --author="Jane" # Filter by author
git log --since="2 weeks ago" # Filter by date
git log --grep="fix:" # Filter by commit message pattern
git log -- path/to/file # History of a specific file
git log --follow -- path/to/file # Follow renamesКомбинация --graph --oneline --decorate --all настолько универсально полезна, что большинство инженеров создают для неё псевдоним:
git config --global alias.lg "log --oneline --graph --decorate --all"Подготовка и коммит
git add filename.py # Stage a specific file
git add src/ # Stage an entire directory
git add . # Stage all changes in current directory
git add -p # Interactive patch staging (stage hunks, not whole files)
git add -u # Stage modifications and deletions, but not new filesИнтерактивная подготовка (git add -p) — одна из наиболее мощных и недооценённых возможностей Git. Она позволяет просматривать и выборочно подготавливать отдельные фрагменты внутри файла, обеспечивая точные атомарные коммиты даже когда рабочая директория содержит несколько несвязанных изменений.
git commit -m "feat: add OAuth2 token refresh logic"
git commit --amend # Modify the most recent commit (message or content)
git commit --amend --no-edit # Amend content without changing the message
git commit -v # Open editor showing full diff of staged changesКритическое правило: никогда не изменяйте коммиты, которые уже были отправлены в общий удалённый репозиторий. Изменение перезаписывает хеш коммита, вынуждая коллег выполнять rebase или сброс своих локальных веток.
Push и Pull
git push origin main
git push origin feature/auth # Push a specific branch
git push -u origin feature/auth # Push and set upstream tracking
git push --force-with-lease # Safer force push (fails if remote has new commits)
git push origin --delete old-branch # Delete a remote branch
git push --tags # Push all local tagsПредпочитайте --force-with-lease вместо --force, когда необходимо перезаписать удалённую историю. Это проверяет, что никто другой не выполнял push с момента вашего последнего fetch, предотвращая случайную потерю данных.
git pull origin main
git pull --rebase origin main # Fetch and rebase instead of merge
git pull --ff-only # Only fast-forward; abort if a merge commit would be createdgit fetch загружает удалённые изменения, не затрагивая вашу рабочую директорию или текущую ветку. Это безопасный способ проверить изменения из upstream перед их интеграцией.
git fetch origin
git fetch --all # Fetch from all remotes
git fetch --prune # Remove remote-tracking branches that no longer exist upstreamВетвление и слияние: основной рабочий процесс
Модель ветвления Git — её наиболее архитектурно значимая особенность. Ветка — это просто именованный указатель (файл размером 41 байт в .git/refs/heads/) на хеш коммита. Создание ветки происходит мгновенно независимо от размера репозитория.
Управление ветками
git branch # List local branches
git branch -a # List all branches (local and remote-tracking)
git branch -v # List branches with last commit info
git branch feature/user-auth # Create a new branch
git branch -d feature/user-auth # Delete merged branch
git branch -D feature/user-auth # Force delete (even if unmerged)
git branch -m old-name new-name # Rename a branchПереключение веток
Современный Git (2.23+) разделяет функции git checkout на две специализированные команды:
git switch main # Switch to existing branch
git switch -c feature/payments # Create and switch in one step
git restore filename.py # Discard working directory changes to a file
git restore --staged filename.py # Unstage a file (remove from index)git checkout по-прежнему работает для всего этого, но git switch и git restore имеют более чёткую и однозначную семантику и должны предпочитаться в современных рабочих процессах.
Стратегии слияния
git merge feature/user-auth # Standard merge (creates merge commit if needed)
git merge --no-ff feature/user-auth # Always create merge commit (preserves branch topology)
git merge --squash feature/user-auth # Squash all branch commits into one staged change
git merge --abort # Abort an in-progress conflicted mergeСлияние с перемоткой вперёд (fast-forward) происходит, когда целевая ветка не расходилась с исходной — Git просто перемещает указатель вперёд. Коммит слияния при этом не создаётся. --no-ff принудительно создаёт коммит слияния даже в этом случае, что сохраняет визуальную историю веток функций в git log --graph.
Слияние со сжатием (squash merge) объединяет все коммиты из ветки функции в одно подготовленное изменение, которое затем фиксируется вручную. Это создаёт чистую линейную историю в main, но отбрасывает детальную историю коммитов ветки функции.
Rebase
git rebase воспроизводит коммиты из одной ветки поверх другой, перезаписывая их хеши для создания линейной истории.
git rebase main # Rebase current branch onto main
git rebase -i HEAD~5 # Interactive rebase: edit last 5 commits
git rebase --onto main server client # Transplant client branch onto main, excluding server
git rebase --abort # Abort a rebase in progress
git rebase --continue # Continue after resolving a conflictИнтерактивный rebase (-i) — профессиональный инструмент для поддержания чистоты коммитов. Он позволяет переупорядочивать, сжимать, редактировать, удалять или разделять коммиты перед их публикацией. Типичный сценарий использования: очистка запутанной ветки функции перед открытием pull request.
| Стратегия | История | Сценарий использования | Риск |
|---|---|---|---|
| — | — | — | — |
| Merge (по умолчанию) | Нелинейная, сохраняет ветки | Долгоживущие ветки функций | Зашумлённый `git log` |
| Merge `–no-ff` | Нелинейная, явные коммиты слияния | Принудительная топология веток | Аналогично предыдущему |
| Merge `–squash` | Линейная, один коммит на функцию | Чистая основная ветка | Теряется детальная история |
| Rebase | Линейная, без коммитов слияния | Личные ветки, очистка перед PR | Перезаписывает хеши; опасно на общих ветках |
| Cherry-pick | Выборочная, линейная | Бэкпортирование исправлений | Дублирование коммитов между ветками |
Золотое правило rebase: никогда не выполняйте rebase коммитов, существующих в публичной общей ветке. Rebase перезаписывает хеши коммитов. Если коллега основал свою работу на этих коммитах, его история разойдётся, и ему придётся болезненно согласовывать её вручную.
Разрешение конфликтов слияния
Конфликты возникают, когда две ветки изменяют одну и ту же область одного и того же файла. Git отмечает конфликт в файле стандартными маркерами конфликта:
<<<<<<< HEAD
const timeout = 30000;
=======
const timeout = 60000;
>>>>>>> feature/increase-timeoutРабочий процесс разрешения:
# After a conflicted merge or rebase
git status # Identify conflicted files (marked as "both modified")
# Edit each conflicted file, remove markers, keep correct content
git add resolved-file.js # Mark as resolved
git commit # Complete the merge (message is pre-populated)Для сложных конфликтов инструмент трёхстороннего слияния обеспечивает более наглядное представление:
git mergetool # Launch configured merge tool (vimdiff, meld, etc.)
git config --global merge.tool vimdiffОтмена изменений: матрица решений
Выбор неправильной команды отмены — один из наиболее распространённых способов потерять работу или повредить общую историю. Правильный выбор зависит от двух переменных: где находится изменение и было ли оно отправлено.
| Сценарий | Команда | Перезаписывает историю | Безопасно в общей ветке |
|---|---|---|---|
| — | — | — | — |
| Убрать файл из подготовки | `git restore –staged file` | Нет | Да |
| Отменить изменения в рабочей директории | `git restore file` | Нет | Да |
| Отменить последний коммит, сохранить изменения подготовленными | `git reset –soft HEAD~1` | Да | Нет |
| Отменить последний коммит, сохранить изменения неподготовленными | `git reset HEAD~1` | Да | Нет |
| Отменить последний коммит, удалить все изменения | `git reset –hard HEAD~1` | Да | Нет |
| Безопасно отменить отправленный коммит | `git revert <hash>` | Нет | Да |
| Удалить файл из всей истории | `git filter-repo` | Да | Нет |
git reset --soft HEAD~1 # Undo commit, keep changes in index
git reset HEAD~1 # Undo commit, keep changes in working dir
git reset --hard HEAD~1 # Undo commit, discard all changes permanently
git revert abc1234 # Create new commit that inverts abc1234
git revert HEAD~3..HEAD # Revert last 3 commits (creates 3 revert commits)
git revert -n HEAD~3..HEAD # Stage the reversals without committing (batch revert)git reset --hard необратим с помощью обычных команд Git. Если вы случайно выполнили его, единственный путь к восстановлению — git reflog, который записывает каждую позицию, на которую указывал HEAD, приблизительно в течение 90 дней.
git reflog # Show HEAD movement history with hashes
git checkout -b recovery abc1234 # Recover by creating a branch at the lost commitПродвинутые команды для производственных рабочих процессов
git stash
git stash сохраняет текущее состояние рабочей директории и индекса в стек, предоставляя чистое рабочее дерево для переключения контекста.
git stash # Stash tracked changes
git stash -u # Include untracked files
git stash push -m "WIP: auth refactor" # Stash with a descriptive name
git stash list # List all stash entries
git stash pop # Apply most recent stash and remove it from stack
git stash apply stash@{2} # Apply specific stash without removing it
git stash drop stash@{2} # Delete a specific stash entry
git stash branch feature/wip # Create a new branch from a stashgit cherry-pick
git cherry-pick abc1234 # Apply a single commit to current branch
git cherry-pick abc1234 def5678 # Apply multiple commits
git cherry-pick abc1234 --no-commit # Apply changes without committing
git cherry-pick main~3..main # Apply a range of commitsCherry-pick — стандартный механизм для бэкпортирования исправлений ошибок в ветки обслуживания. Если вы исправляете критическую уязвимость безопасности в main, вы выполняете cherry-pick этого коммита в v2.1-stable и v2.0-stable без слияния несвязанных функций.
git bisect
git bisect выполняет бинарный поиск по истории коммитов для нахождения точного коммита, в котором была введена ошибка. Это один из наиболее мощных и малоизвестных инструментов отладки Git.
git bisect start
git bisect bad # Mark current commit as broken
git bisect good v2.3.0 # Mark a known-good commit or tag
# Git checks out the midpoint commit automatically
# Test your code, then:
git bisect good # If this commit is fine
git bisect bad # If this commit is broken
# Repeat until Git identifies the first bad commit
git bisect reset # Return to original HEAD when doneВ репозитории с 1 000 коммитами между хорошей и плохой точками git bisect находит виновника не более чем за 10 шагов.
git tag
Теги отмечают конкретные коммиты как значимые — как правило, версии релизов.
git tag v1.4.2 # Lightweight tag (just a pointer)
git tag -a v1.4.2 -m "Release 1.4.2" # Annotated tag (recommended; stores metadata)
git tag -a v1.4.2 abc1234 # Tag a specific past commit
git push origin v1.4.2 # Push a specific tag
git push origin --tags # Push all tags
git tag -d v1.4.2 # Delete local tag
git push origin --delete v1.4.2 # Delete remote tagВсегда используйте аннотированные теги для релизов. Они хранят имя, email, дату и сообщение создателя тега, а также могут быть подписаны с помощью GPG. Лёгкие теги подходят только для временных локальных закладок.
git worktree
git worktree позволяет одновременно извлекать несколько рабочих директорий из одного репозитория — каждую на отдельной ветке. Это устраняет необходимость в stash или коммите незавершённой работы при переключении на hotfix.
git worktree add ../hotfix-branch hotfix/critical-auth-bug
git worktree list
git worktree remove ../hotfix-branchЭто особенно ценно на Dedicated Server, работающем с CI/CD-конвейером, где нескольким задачам сборки требуется одновременный доступ к разным веткам одного репозитория без взаимных помех.
Рабочие процессы Git для команд
Правильная стратегия ветвления зависит от частоты выпусков и размера команды. Существуют три доминирующие модели:
Рабочий процесс с ветками функций
Каждая функция или исправление живёт в собственной ветке. Разработчики открывают pull request для слияния в main. Простой и эффективный подход для большинства команд.
Gitflow
Определяет долгоживущие ветки main и develop, а также краткосрочные ветки feature/, release/ и hotfix/ со строгими правилами слияния. Подходит для программного обеспечения с явными версионированными релизами (библиотеки, упакованные приложения).
Разработка на основе trunk
Разработчики коммитят напрямую в main (или используют очень краткосрочные ветки, сливаемые в течение дня). В значительной мере опирается на флаги функций для скрытия незавершённой работы. Предпочтительна для высокоскоростных команд, практикующих непрерывное развёртывание.
| Рабочий процесс | Частота выпусков | Размер команды | Сложность CI/CD |
|---|---|---|---|
| — | — | — | — |
| Feature Branch | Гибкая | Любой | Низкая |
| Gitflow | Плановые релизы | Средний–Крупный | Средняя |
| Trunk-Based | Непрерывное развёртывание | Любой | Высокая |
Хостинг репозиториев Git: самостоятельный хостинг vs. управляемые платформы
Для команд, которым требуется суверенитет данных, соответствие нормативным требованиям или частная инфраструктура, самостоятельный хостинг Git-сервера является жизнеспособным и зачастую необходимым выбором. Варианты включают Gitea (лёгкий, на основе Go), GitLab CE (полная DevOps-платформа) и Forgejo (форк Gitea с управлением сообщества).
Минимальный самостоятельно размещённый экземпляр Gitea комфортно работает на плане VPS Hosting с 2 vCPU и 2 GB RAM. Для более крупных команд или GitLab CE с CI-раннерами практический минимум составляет 4–8 GB RAM.
При самостоятельном хостинге защитите свой Git-сервер с помощью:
- Аутентификации по SSH-ключу (полностью отключите аутентификацию по паролю)
- HTTPS с действительным сертификатом — SSL Certificates необходимы для защиты учётных данных при передаче
- Правил брандмауэра, ограничивающих доступ к Git-порту (22 или пользовательский SSH-порт, 443 для HTTPS)
- Регулярных автоматических резервных копий директорий голого репозитория
.git - Секретов webhook для интеграций CI/CD
Для команд, использующих конвейеры развёртывания на основе Git и управляющих веб-инфраструктурой, сочетание самостоятельно размещённого Git-сервера с VPS with cPanel даёт интегрированные хуки развёртывания наряду с привычными инструментами управления хостингом.
Git-хуки: автоматизация контроля качества
Git-хуки — это скрипты, которые автоматически выполняются в определённых точках жизненного цикла Git. Они находятся в .git/hooks/ и по умолчанию не фиксируются в репозитории (используйте такой инструмент, как pre-commit или husky, для их совместного использования).
Ключевые хуки для производственных рабочих процессов:
| Хук | Триггер | Типичное использование |
|---|---|---|
| — | — | — |
| `pre-commit` | Перед созданием коммита | Запуск линтеров, форматтеров, тестов |
| `commit-msg` | После написания сообщения коммита | Соблюдение формата conventional commit |
| `pre-push` | Перед push на удалённый сервер | Запуск полного набора тестов |
| `post-receive` | После получения push удалённым сервером | Запуск развёртывания, отправка уведомлений |
| `pre-rebase` | Перед началом rebase | Предотвращение rebase общих веток |
# Example pre-commit hook: reject commits with debug print statements
#!/bin/bash
if git diff --cached | grep -E '^+.*(console.log|debugger|print("DEBUG)'; then
echo "ERROR: Debug statement detected. Remove before committing."
exit 1
fiХук post-receive на голом серверном репозитории — основа простого развёртывания на основе Git: push на сервер, хук извлекает новый HEAD в корень веб-сервера, выполняет шаги сборки и перезапускает сервисы — без необходимости во внешней CI-платформе.
.gitignore: поддержание чистоты репозиториев
Файл .gitignore указывает Git, какие файлы и шаблоны оставлять неотслеживаемыми. Он должен быть зафиксирован в репозитории и тщательно поддерживаться.
# Dependencies
node_modules/
vendor/
# Build artifacts
dist/
build/
*.o
*.pyc
__pycache__/
# Environment and secrets — NEVER commit these
.env
.env.local
*.pem
*.key
config/secrets.yml
# IDE files
.idea/
.vscode/
*.swp
# OS files
.DS_Store
Thumbs.dbКритическая ловушка: если файл уже отслеживался до добавления в .gitignore, Git продолжит его отслеживать. Необходимо явно прекратить его отслеживание:
git rm --cached path/to/sensitive-file
git commit -m "chore: stop tracking secrets file"Никогда не фиксируйте учётные данные, API-ключи или приватные ключи в репозитории — даже в приватном. Используйте переменные окружения, менеджеры секретов (HashiCorp Vault, AWS Secrets Manager) или файлы .env, добавленные в .gitignore.
Настройка производительности для больших репозиториев
Стандартный Git деградирует на репозиториях с миллионами файлов или гигабайтами бинарных ресурсов. Стратегии смягчения:
- Git LFS (Large File Storage): заменяет большие бинарные файлы файлами-указателями в репозитории и хранит фактическое содержимое на отдельном LFS-сервере. Необходим для репозиториев, содержащих медиафайлы, веса ML-моделей или скомпилированные бинарные файлы.
- Частичное клонирование:
git clone --filter=blob:noneзагружает коммиты и деревья, но получает blob-объекты по требованию. Значительно уменьшает начальный размер клона для больших монорепозиториев. - Sparse checkout:
git sparse-checkout set path/to/subdirизвлекает только подмножество рабочего дерева. Полезно в монорепозиториях, где разработчик работает только в одной директории сервиса. - Файл commit-graph:
git commit-graph write --reachableпредварительно вычисляет граф коммитов, ускоряя такие операции, какgit log --graphи запросы достижимости в больших историях. git maintenance start: планирует фоновые задачи обслуживания (упаковка свободных объектов, обновление commit-graph, предварительная загрузка fetch) для поддержания быстрой работы репозитория со временем.
Технический контрольный список ключевых выводов
Прежде чем считать настройку Git готовой к производству, проверьте каждый из следующих пунктов:
- Идентификация настроена:
user.nameиuser.emailправильно установлены на соответствующем уровне конфигурации - Используются SSH-ключи: аутентификация по паролю к удалённым серверам заменена парами SSH-ключей или HTTPS на основе токенов
.gitignoreзафиксирован: секреты, артефакты сборки и файлы ОС исключены до первого коммита- Ветка по умолчанию называется
main:init.defaultBranchустановлен глобально во избежание устаревшего именованияmaster - Сообщения коммитов следуют соглашению: Conventional Commits (
feat:,fix:,chore:) или согласованный командой формат, соблюдаемый через хукcommit-msg git revertдля публичной истории:git reset --hardиспользуется только для локальных, неотправленных коммитов--force-with-leaseвместо--force: предотвращает случайную перезапись push коллег- Аннотированные теги для релизов:
git tag -aс сообщением, а не лёгкие теги - Хуки распространяются через
pre-commitилиhusky: контроль качества соблюдается единообразно во всей команде - Git LFS настроен, если репозиторий содержит бинарные ресурсы размером более 1 MB
- Голый репозиторий на сервере: самостоятельно размещённые удалённые серверы инициализированы с помощью
git init --bare - Регулярный
git fetch --prune: ветки удалённого отслеживания синхронизированы с фактическим состоянием удалённого сервера
Часто задаваемые вопросы
В чём разница между git fetch и git pull?
git fetch загружает коммиты, ветки и теги с удалённого сервера в локальные refs удалённого отслеживания (например, origin/main), не затрагивая рабочую директорию или текущую ветку. git pull — это git fetch, за которым немедленно следует git merge (или git rebase, если настроено). Используйте git fetch, когда хотите проверить изменения из upstream перед их интеграцией.
Когда следует использовать git rebase вместо git merge?
Используйте rebase для линеаризации локальной ветки функции перед открытием pull request, сохраняя читаемость истории проекта. Никогда не выполняйте rebase ветки, которую другие разработчики уже клонировали или на которой основали свою работу — перезапись опубликованных хешей коммитов вынуждает всех остальных вручную согласовывать расходящиеся истории.
Как навсегда удалить конфиденциальный файл, случайно зафиксированный в коммите?
Используйте git filter-repo (современная замена git filter-branch): git filter-repo --path secrets.env --invert-paths. Это перезаписывает всю историю репозитория, удаляя файл из каждого коммита. После перезаписи выполните принудительный push всех веток и тегов, затем немедленно смените скомпрометированные учётные данные — считайте их раскрытыми независимо от того, насколько быстро вы действуете.
Что такое состояние detached HEAD и как из него выйти?
Detached HEAD означает, что указатель HEAD ссылается непосредственно на конкретный хеш коммита, а не на имя ветки. Любые коммиты, которые вы делаете, не будут принадлежать ни одной ветке и станут недостижимыми после переключения. Для восстановления: git switch -c new-branch-name для присоединения коммитов к новой ветке или git switch main для их отмены.
Как Git обрабатывает бинарные файлы иначе, чем текстовые?
Git хранит бинарные файлы как непрозрачные blob-объекты — он не может вычислять значимые построчные диффы или выполнять автоматические слияния для них. Конфликты в бинарных файлах должны разрешаться путём выбора одной из версий целиком. Для репозиториев со значительными бинарными ресурсами настройте Git LFS для хранения бинарных файлов во внешнем хранилище, сохраняя сам репозиторий лёгким и быстрым.
