Профессиональный setup: собираем рабочее окружение Git

Рейтинг: 59.6% · 10 голосов
Самый подробный курс по Git - от первого коммита до объектной базы и packfiles. Терминал и первый репозиторий, ветки и слияние, конфликты, удалённая работа и форджи (GitHub, GitLab), rebase и переписывание истории, спасение кода через reflog и fsck, stash и worktree, bisect и blame, подмодули и монорепо, хуки и подпись коммитов, внутреннее устройство и масштаб. Для новичков и профи. Актуально на 2026 (Git 2.54, дорожная карта 3.0).
Ответить
Аватара пользователя
Pavel_Git
Сообщения: 52
Зарегистрирован: 11 май 2026, 05:31

Профессиональный setup: собираем рабочее окружение Git

Сообщение Pavel_Git »

Оглавление курса (52)
  1. Что такое контроль версий и почему победил Git
  2. Установка Git на Windows, macOS и Linux и первая настройка
  3. Терминал и как спрашивать у Git: выживание в командной строке
  4. Ментальная модель Git: три состояния, коммит-снимок и граф
  5. Первый репозиторий: init, add, commit, status
  6. Просмотр изменений: status, diff и индексация по частям
  7. История проекта: git log, диапазоны и поиск
  8. .gitignore: что не должно попасть в репозиторий
  9. .gitattributes: окончания строк, бинарники и атрибуты
  10. Ветки как указатели: branch, switch и detached HEAD
  11. Слияние веток: fast-forward против трёхстороннего merge
  12. Конфликты слияния: анатомия и уверенное разрешение
  13. Практикум: твой первый день с Git от нуля до push
  14. Удалённые репозитории: remote, fetch, базовый pull и refspec
  15. git push: безопасная отправка и защита от перезаписи
  16. Клонирование: shallow, partial clone, bundle и backfill
  17. GitHub, GitLab и форки: pull request, rulesets и защита веток
  18. Рабочие процессы команды: GitFlow, GitHub Flow, trunk-based
  19. Merge queue и merge trains: безопасное вливание в trunk
  20. Культура code review и Conventional Commits
  21. git reset: три дерева и отмена индексации и коммитов
  22. git revert: безопасная отмена в общей истории
  23. Правка последнего коммита: git commit --amend
  24. git rebase: пересадка истории и золотое правило
  25. Интерактивный rebase: переписать серию коммитов
  26. git cherry-pick: перенос отдельных коммитов
  27. Stacked diffs: цепочка зависимых PR
  28. Массовое переписывание истории: git filter-repo и git replace
  29. git reflog: журнал, который помнит всё
  30. Восстановление утерянных коммитов, веток и файлов
  31. Откат опасных операций: reset --hard, сломанный rebase, плохой merge
  32. git stash: тайник для незавершённой работы
  33. git worktree: несколько рабочих деревьев одного репозитория
  34. git bisect: бинарный поиск регрессии
  35. git blame, mailmap и археология кода
  36. Теги, релизы, archive и bundle
  37. Подмодули: внешние репозитории внутри проекта
  38. Subtree, монорепозитории и sparse-checkout
  39. Git LFS и большие файлы
  40. Вспомогательные команды: clean, mv, rm, restore
  41. Псевдонимы и кастомизация .gitconfig
  42. Хуки Git: автоматизация на клиенте и сервере
  43. Подпись коммитов и тегов: SSH, GPG и Sigstore
  44. Внутреннее устройство I: объектная база Git
  45. Внутреннее устройство II: ссылки, HEAD, notes и reftable
  46. Внутреннее устройство III: индекс, packfiles, gc и обслуживание
  47. От SHA-1 к SHA-256: переход на новый хеш
  48. Огромные репозитории: partial clone, FSMonitor, Scalar
  49. Git в CI/CD: shallow, кеш, merge_group и безопасность
  50. Куда движется Git: дорожная карта 3.0 и экосистема
  51. Профессиональный setup: собираем рабочее окружение Git (вы здесь)
  52. 30+ типичных ошибок Git и как из них выбираться
Зачем нужна настройка Git, а не дефолты из коробки

Ты прошёл весь курс. Ты знаешь объектную модель, индекс, rebase, rerere, reflog, подписи, partial clone. Но между знанием и ежедневной скоростью стоит одна скучная вещь: настройка git. Сырой Git из коробки в 2026 году всё ещё ведёт себя консервативно - создаёт ветку master с подсказкой, не подчищает удалённые ветки, не переиспользует разрешения конфликтов, требует руками выставлять upstream при первом push. Каждый день ты теряешь по чуть-чуть: лишний флаг тут, забытый --set-upstream там, конфликт, который уже разруливал на прошлой неделе.

Этот урок - капстоун. Мы соберём профессиональный gitconfig, ssh, подпись, глобальные ignore/attributes, pre-commit и фоновое обслуживание в один готовый сетап. И положим всё в dotfiles, чтобы новая машина поднималась за десять минут, а не за день. Это не косметика. Хорошее git окружение убирает целый класс ошибок и делает дорогую операцию (force-push, чистка веток, разбор конфликта) дешёвой и привычной.

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

Код: Выделить всё

git config --show-origin --get core.editor
# file:/etc/gitconfig            system  (на всю машину)
# file:/Users/you/.gitconfig     global  (твой, главный)
# file:.git/config               local   (этот репозиторий)
# плюс worktree и командный -c
Когда непонятно, откуда взялось значение, не гадай:

Код: Выделить всё

git config --list --show-origin | grep pull.rebase
# file:/Users/you/.gitconfig  pull.rebase=true
Изображение

Профессиональный gitconfig: identity, поведение, алиасы

Сердце сетапа - твой глобальный ~/.gitconfig. Разберём по секциям, что в нём должно быть и почему именно так. Это и есть оптимальная настройка git для рабочего дня.

Код: Выделить всё

[user]
    name = Имя Фамилия
    email = you@example.com

[init]
    defaultBranch = main

[pull]
    rebase = true
[fetch]
    prune = true
    pruneTags = true
[push]
    autoSetupRemote = true
    followTags = true

[rerere]
    enabled = true
[branch]
    sort = -committerdate
[column]
    ui = auto

[diff]
    colorMoved = zebra
    algorithm = histogram
    mnemonicPrefix = true
    renames = copies
[merge]
    conflictStyle = zdiff3
[rebase]
    autosquash = true
    autostash = true
    updateRefs = true
Теперь почему каждая строка тут. init.defaultBranch=main - в ванильном Git на 2026 дефолт всё ещё master (встроенным main станет только в 3.0, в конце года), так что ставим руками, чтобы локальные репозитории совпадали с тем, что ждут GitHub и GitLab. pull.rebase=true превращает git pull из создателя мусорных merge-коммитов в чистую перемотку поверх - твоя история линейная, без "Merge branch main of origin" каждые полчаса. fetch.prune убирает локальные ссылки на ветки, которые уже удалили на сервере, - больше не надо вручную чистить origin/feature-старьё.

push.autoSetupRemote=true - маленькая, но очень приятная штука: с 2.37 она есть, но по умолчанию выключена. С ней первый push новой ветки сам создаёт upstream, и ты забываешь про git push -u origin HEAD навсегда. rerere.enabled=true - reuse recorded resolution: Git запоминает, как ты разрулил конфликт, и при повторе того же конфликта (типично при долгом rebase или регулярном слиянии) подставляет решение сам. rebase.updateRefs (с 2.38) - спасение для stacked-веток: при rebase нижней ветки автоматически двигаются и все промежуточные ярлыки. merge.conflictStyle=zdiff3 показывает в конфликте общего предка, а не только две стороны - в разы понятнее, что реально разошлось.

Дальше - алиасы. Не превращай конфиг в свалку, держи 5-7 рабочих лошадок:

Код: Выделить всё

[alias]
    s = status -sb
    lg = log --graph --abbrev-commit --decorate \
         --format=format:'%C(bold blue)%h%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(auto)%d%C(reset)'
    last = log -1 HEAD --stat
    undo = reset --soft HEAD~1
    unstage = restore --staged
    amend = commit --amend --no-edit
    cleanup = "!git branch --merged main | grep -vE '\\*|main|master' | xargs -r git branch -d"
    sync = "!git switch main && git pull && git fetch --prune"
Разберём два самых полезных. undo делает reset --soft HEAD~1: откатывает последний коммит, но оставляет изменения в индексе - идеально, когда закоммитил рано или не то сообщение. Это не потеря работы, файлы на месте. cleanup - это shell-алиас (префикс ! означает запуск в шелле): берёт ветки, уже влитые в main, фильтрует main/master и текущую (звёздочку), и удаляет остальное через git branch -d (безопасный, с маленькой d - не удалит невлитое). Вот его живой вывод:

Код: Выделить всё

$ git cleanup
Deleted branch feature/login (was 3a4f1c2).
Deleted branch hotfix/typo (was 9b2e8d1).
Если ветка не влита, -d откажется удалять, и ты увидишь предупреждение - это защита, а не баг.

Один конфиг, две личности: includeIf для work и personal

Типичная боль: на рабочих репозиториях надо коммитить с корпоративной почтой и подписывать корпоративным ключом, а на пет-проектах - личной. Раньше люди забывали переключиться и пушили в рабочий монорепо под gmail. Решение - условное включение includeIf по пути каталога. Раскладываешь репозитории по папкам и Git сам подхватывает нужную identity.

Код: Выделить всё

# ~/.gitconfig  (общий хвост)
[includeIf "gitdir:~/work/"]
    path = ~/.gitconfig-work
[includeIf "gitdir:~/personal/"]
    path = ~/.gitconfig-personal

# ~/.gitconfig-work
[user]
    email = you@company.com
    signingkey = ~/.ssh/id_work.pub
Косая черта в конце gitdir:~/work/ обязательна - иначе условие не сматчит подкаталоги. Проверить, что сработало, внутри рабочего репо:

Код: Выделить всё

$ cd ~/work/api && git config user.email
you@company.com
$ cd ~/personal/blog && git config user.email
you@gmail.com
SSH-ключи, host-алиасы и SSH-подпись коммитов

Подключение и подпись - вторая половина сетапа. Генерим современный ed25519-ключ (отдельный на работу и на личное - так удобнее ротировать):

Код: Выделить всё

ssh-keygen -t ed25519 -C "you@company.com" -f ~/.ssh/id_work
ssh-keygen -t ed25519 -C "you@gmail.com"   -f ~/.ssh/id_personal
Дальше ~/.ssh/config с host-алиасами. Зачем: один ключ для GitHub-работы, другой для GitHub-личного - но хост у обоих github.com. Алиас разводит их по разным ключам:

Код: Выделить всё

Host github-work
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_work
    IdentitiesOnly yes

Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_personal
    IdentitiesOnly yes
Теперь рабочий репозиторий клонишь как git@github-work:company/api.git, и Git подставит рабочий ключ. IdentitiesOnly yes критично: без него ssh-агент переберёт ВСЕ загруженные ключи и сервер примет первый подходящий - получишь push не от того аккаунта.

Подпись 2026 - это SSH-подпись, простой рекомендуемый дефолт (GPG остался для корпоративного легаси, Sigstore/gitsign - для CI-ботов). Никакой возни с keyserver, подписываешь тем же ключом, которым пушишь:

Код: Выделить всё

[gpg]
    format = ssh
[gpg "ssh"]
    allowedSignersFile = ~/.config/git/allowed_signers
[user]
    signingkey = ~/.ssh/id_work.pub
[commit]
    gpgsign = true
[tag]
    gpgSign = true
Файл allowed_signers связывает почту с публичным ключом - без него Git подпишет, но не сможет проверить (покажет статус, что подписант неизвестен):

Код: Выделить всё

# ~/.config/git/allowed_signers
you@company.com ssh-ed25519 AAAAC3NzaC1lZDI1...work
you@gmail.com   ssh-ed25519 AAAAC3NzaC1lZDI1...personal
Проверяем, что подпись реально легла и валидируется:

Код: Выделить всё

$ git commit -m "feat: setup signing"
$ git log --show-signature -1
commit 7f2a9c1 (HEAD -> main)
Good "git" signature for you@company.com with ED25519 key SHA256:abcd...
Строка Good signature - то, ради чего всё затевалось. На GitHub такой коммит получит бейдж Verified, если публичный ключ добавлен в Signing keys аккаунта (это отдельный список от authentication keys, частая путаница).

Глобальный .gitignore, .gitattributes и pre-commit

Мусор не должен попадать в каждый репозиторий по отдельности. Заведи глобальный ignore для машинно-специфичных вещей (артефакты ОС, файлы IDE), которым не место в проектном .gitignore:

Код: Выделить всё

git config --global core.excludesFile ~/.config/git/ignore

Код: Выделить всё

# ~/.config/git/ignore
.DS_Store
Thumbs.db
.idea/
.vscode/
*.swp
.env.local
.direnv/
Тонкость: глобальный ignore - для того, что специфично для ТВОЕЙ машины и инструментов. Артефакты сборки проекта (node_modules, vendor) кладут в проектный .gitignore, потому что они общие для всей команды. Не тащи их в глобальный.

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

Код: Выделить всё

git config --global core.attributesFile ~/.config/git/attributes

Код: Выделить всё

# ~/.config/git/attributes
* text=auto eol=lf
*.png binary
*.pdf binary
*.lock -diff
package-lock.json -diff linguist-generated
text=auto eol=lf означает: храним всё в репозитории с LF, нормализуем при коммите - это убивает войну CRLF/LF между Windows и Unix раз и навсегда. Пометка -diff на лок-файлах скрывает их гигантские бесполезные диффы из вывода.

Фреймворк pre-commit - это ловушка ошибок до того, как они попадут в историю. Кладёшь .pre-commit-config.yaml в репозиторий и ставишь один раз хуки:

Код: Выделить всё

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v5.0.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-merge-conflict
      - id: check-added-large-files
      - id: detect-private-key

Код: Выделить всё

$ pre-commit install
pre-commit installed at .git/hooks/pre-commit
$ git commit -m "wip"
trailing-whitespace.................Failed
- files were modified by this hook
detect-private-key..................Passed
Хук detect-private-key - дешёвая страховка от классической катастрофы: случайно закоммиченного приватного ключа. check-added-large-files ловит толстый бинарь, который ты не собирался класть в Git. Failed означает, что коммит остановлен и часть проблем уже автоматически исправлена - просто добавляешь правки и коммитишь снова.

Фоновое обслуживание и dotfiles-репозиторий

Раньше все вручную дёргали git gc. В 2026 это легаси-путь. Современное - git maintenance, который сам по расписанию делает лёгкое обслуживание (с 2.54 дефолтная стратегия ручного обслуживания - geometric repacking, без полной сборки мусора):

Код: Выделить всё

$ git maintenance start
$ git config --get-regexp maintenance
maintenance.auto false
maintenance.strategy incremental
maintenance start регистрирует репозиторий и ставит фоновые задачи (через launchd на macOS, systemd-таймеры на Linux, Task Scheduler на Windows). Он подтягивает свежие объекты в фоне, поддерживает commit-graph для быстрого git log --graph и упаковывает прирост геометрически - твой git status и fetch остаются быстрыми даже на крупном репо. maintenance.auto false отключает старое автоматическое gc, которое могло замораживать тебя посреди работы.

И финальный аккорд - dotfiles git. Весь сетап выше бесполезен, если живёт только на одной машине. Превращаем конфиги в версионируемый репозиторий. Чистый способ без симлинков - bare-репозиторий поверх домашней папки:

Код: Выделить всё

git init --bare $HOME/.dotfiles
alias dot='git --git-dir=$HOME/.dotfiles --work-tree=$HOME'
dot config status.showUntrackedFiles no
dot add ~/.gitconfig ~/.ssh/config ~/.config/git/
dot commit -m "dotfiles: git setup"
dot remote add origin git@github-work:you/dotfiles.git
dot push -u origin main
Хитрость с showUntrackedFiles=no обязательна: иначе dot status завалит тебя всем содержимым домашней папки. Внимание к безопасности: в dotfiles кладёшь ПУБЛИЧНЫЕ ключи и конфиги, приватные ключи (~/.ssh/id_*) - НИКОГДА. Для секретов - отдельный приватный механизм или менеджер.

Типичные грабли
  • push.autoSetupRemote включён, но ты на отделившейся ветке с чужим именем - push создаст upstream не туда. Проверяй git status -sb перед первым пушем новой ветки.
  • includeIf не срабатывает: забыл косую черту в конце gitdir-пути или репозиторий лежит вне ожидаемой папки. Диагностика - git config user.email из самого репо.
  • SSH-подпись стоит, а GitHub пишет Unverified: публичный ключ добавлен в Authentication keys, но не в Signing keys - это РАЗНЫЕ списки.
  • allowedSignersFile не настроен - git log --show-signature ругается на неизвестного подписанта, хотя подпись валидна. Это про верификацию, не про создание подписи.
  • Положил приватный SSH-ключ в публичный dotfiles-репозиторий. Если случилось - немедленно ротируй ключ, удаления из истории мало.
  • core.excludesFile задан, но игноришь там node_modules - на другой машине у коллеги их не игнорит. Машинно-специфичное в глобальный, общекомандное в проектный.
Мини-лаба: собери окружение с нуля
  • Создай ~/.gitconfig с секциями user, init (defaultBranch=main), pull.rebase, fetch.prune, push.autoSetupRemote, rerere.enabled и алиасами undo, cleanup, lg.
  • Сгенерируй ed25519-ключ, добавь его публичную часть в Signing keys аккаунта, включи gpg.format=ssh и commit.gpgsign=true.
  • Сделай тестовый репозиторий, закоммить и проверь подпись через git log --show-signature -1 - убедись, что видишь Good signature.
  • Заведи глобальные ignore и attributes в ~/.config/git/, проверь, что .DS_Store больше не попадает в git status.
  • Запусти git maintenance start в репозитории и убедись через git config --get-regexp maintenance, что задачи зарегистрированы.
  • Инициализируй bare dotfiles-репозиторий, добавь туда ~/.gitconfig (но НЕ приватные ключи) и сделай первый коммит.
Контрольные вопросы
  • Чем reset --soft HEAD~1 (алиас undo) отличается от reset --hard HEAD~1 и почему для отмены последнего коммита берут именно soft?
  • Почему в ~/.ssh/config критичен IdentitiesOnly yes, когда у тебя два ключа для одного хоста github.com?
  • В чём разница между Authentication keys и Signing keys на GitHub и как она проявляется в бейдже Verified?
  • Почему node_modules кладут в проектный .gitignore, а .DS_Store - в глобальный core.excludesFile?
Итог

Профессиональный сетап - это не магия, а дисциплина: один продуманный gitconfig (identity, поведение, алиасы), SSH с host-алиасами и подписью, глобальные ignore/attributes, pre-commit как ловушка ошибок, git maintenance в фоне и всё это в dotfiles под версией. Собрав это один раз, ты разворачиваешь готовое git окружение на новой машине за десять минут, а не настраиваешь по крупицам неделями. Это финальный кирпич курса: теперь знание объектной модели и rebase подкреплено инструментом, который не даёт ошибиться в рутине.
👍3 ❤️1 🔥 😄 🤔
Аватара пользователя
mrivero
Сообщения: 1
Зарегистрирован: 28 май 2026, 16:23

Re: Профессиональный setup: собираем рабочее окружение Git

Сообщение mrivero »

Спасибо за includeIf, реально пушил в рабочий монорепо под личной почтой раза три. Теперь папки work и personal все разруливают сами.
👍 ❤️1 🔥 😄 🤔
Аватара пользователя
nixosmaster
Сообщения: 1
Зарегистрирован: 05 июн 2026, 10:33

Re: Профессиональный setup: собираем рабочее окружение Git

Сообщение nixosmaster »

Вопрос: а если у меня уже есть .gitconfig на машине и куча всего в нём - как аккуратно перетащить в bare dotfiles, чтобы ничего не затереть при clone на новой машине?
👍1 ❤️1 🔥 😄 🤔
Ответить
← Предыдущая глава
Куда движется Git: дорожная карта 3.0 и экосистема
Следующая глава →
30+ типичных ошибок Git и как из них выбираться

Все главы курса «Git профессионально: от первого коммита до внутреннего устройства»

Поделиться темой: ✈ Telegram VK
Похожие запросы: Настройка Git: git config и .gitconfig

Вернуться в «Git профессионально: от первого коммита до внутреннего устройства»

Кто сейчас на конференции

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