10 вопросов
Merge создает merge-коммит, сохраняя историю веток. Rebase переносит коммиты своей ветки на конец целевой, линейная история. Rebase переписывает историю - не делать на общих ветках. В Go-проектах часто rebase перед merge в main (git pull --rebase), чтобы история была чище. При конфликтах разрешать при rebase по одному коммиту.
git checkout feature
git rebase main
# разрешить конфликты, git add, git rebase --continue
git checkout main
git merge featuregit stash сохраняет рабочие изменения и откатывает рабочую копию; git stash pop восстанавливает. Удобно при срочном переключении ветки без коммита. git stash list - список; git stash apply - применить без удаления из списка. В Go-проекте не коммитить go.sum и бинарники; при stash подтягиваются только отслеживаемые файлы (untracked можно stash -u).
git stash
git checkout other-branch
# ...
git checkout -
git stash popgit cherry-pick
git checkout release
git cherry-pick abc123git bisect start; помечают плохой коммит (git bisect bad) и хороший (git bisect good); Git проверяет средний коммит, вы помечаете good/bad; бинарный поиск до нахождения первого плохого. Автоматизация: git bisect run ./script (скрипт возвращает 0 - good, 1 - bad). В Go: скрипт может запускать go test и возвращать код выхода.
git bisect start
git bisect bad HEAD
git bisect good v1.0
git bisect run go test ./...Revert создает новый коммит, отменяющий изменения указанного коммита; история не переписывается, безопасно для общих веток. Reset перемещает указатель ветки (и опционально индекс/рабочую копию): soft - только коммит, mixed - коммит и индекс, hard - все откатить. Reset переписывает историю; не делать на уже запушенных коммитах без согласования. В Go-проекте revert часто для отката фичи в main.
git revert HEAD
git reset --soft HEAD~1git reflog хранит историю перемещений HEAD и других ссылок. После reset --hard или потерянного коммита можно найти хеш в reflog и восстановить: git checkout
git reflog
git reset --hard abc123Squash объединяет несколько коммитов в один. Варианты: интерактивный rebase (git rebase -i main), в списке заменить pick на squash для коммитов, которые нужно объединить; или merge с опцией --squash (один коммит со всеми изменениями ветки). В Go-проектах часто squash перед merge в main для чистой истории.
git rebase -i main
# в редакторе: pick первый, squash остальные
# или: git merge --squash feature && git commitgit push --force перезаписывает удаленную ветку. Опасно на общих ветках (main): другие могут потерять историю. Допустимо на своей feature-ветке после rebase (история изменилась). Более безопасно: push --force-with-lease - перезапишет только если удаленная ветка не изменилась. В Go при работе в команде избегать force push в main; для личных веток - осторожно после rebase.
git push --force-with-lease origin featureGit Flow: длинные ветки develop и release, feature-ветки от develop; сложнее. GitHub Flow: main всегда готов к деплою, feature-ветки короткие, merge в main. Trunk-Based: короткоживущие ветки, частые merge в main, возможно feature flags. В Go-проектах часто GitHub Flow или Trunk-Based; CI на main и на PR; теги для релизов.
Pre-commit хук выполняется перед коммитом; можно отменить коммит при ошибке. В Go типично: go fmt, golangci-lint, go test. Реализация: .git/hooks/pre-commit скрипт или pre-commit framework. Удобно запускать go vet и тесты только для измененных пакетов. В CI дублировать проверки для гарантии.
#!/bin/sh
# .git/hooks/pre-commit
go fmt ./...
go vet ./...
go test ./...