Git
Controle de versão distribuído. Cada clone é um repositório completo com histórico inteiro.
Conceitos Fundamentais
1
Working Tree
arquivos no disco
→
git add
git add
2
Staging Area
índice / próximo commit
→
git commit
git commit
3
Repository
.git/ — histórico permanente
Objetos Git
commit
tree → (raiz)
parent → abc123
author
message
→
tree
blob → src/
tree → subdir/
→
blob
conteúdo de
um arquivo
tag
object → commit
tagger
message
Cada objeto = SHA-1 do conteúdo. Git é um banco de dados endereçável por conteúdo.
HEAD
HEAD→main→abc1234(normal — attached)
HEAD→abc1234(detached HEAD — aponta direto para commit)
Configuração
git config --global user.name "Alfredo Petri"
git config --global user.email "alfredo_petri@hotmail.com"
git config --global core.editor nvim
git config --global init.defaultBranch main
git config --global push.default current
git config --global pull.rebase true
# aliases
git config --global alias.st status
git config --global alias.lg "log --oneline --graph --decorate --all"
git config --global alias.undo "reset HEAD~1 --mixed"
git config --global alias.pushf "push --force-with-lease"
git config --list --global
Iniciar Repositório
# novo repo local
git init
git init meu-projeto && cd meu-projeto
# clonar
git clone https://github.com/user/repo.git
git clone git@github.com:user/repo.git # SSH
git clone https://... meu-nome-local # renomear
git clone --depth=1 https://... # shallow (sem histórico)
Fluxo Básico
# status
git status
git status -s # compacto: M modified, A added, ? untracked
# staging
git add arquivo.txt
git add .
git add -p # interativo — escolher hunks
# commit
git commit -m "feat: adicionar login"
git commit -am "fix" # add tracked + commit (sem untracked)
# histórico
git log --oneline --graph --decorate --all
git log -n 5
git log -- arquivo.txt
git log --author="Alfredo" --since="2 weeks ago"
# diff
git diff # working tree vs staging
git diff --staged # staging vs último commit
git diff main..feature # entre branches
Branches
main: A ── B ── C ── F
└── feature/auth: D ── E ← HEAD
# listar
git branch # locais
git branch -r # remotas
git branch -a # todas
git branch -v # com último commit
# criar e trocar
git switch -c feature/login # criar + trocar (moderno)
git checkout -b feature/login # equivalente antigo
# renomear / deletar
git branch -m feature/login feature/auth
git branch -d feature/auth # só se mergeada
git branch -D feature/auth # forçar
Merge
git switch main
# fast-forward (padrão quando possível — sem commit extra)
git merge feature/auth
# sempre criar commit de merge
git merge --no-ff feature/auth
# abortar se tiver conflito
git merge --abort
Fast-forward ocorre quando main não divergiu desde que a branch foi criada. Histórico fica linear. --no-ff preserva a evidência de que uma branch existiu.
Rebase
# rebase feature em cima de main (move os commits)
git switch feature/auth
git rebase main
# rebase interativo — editar histórico
git rebase -i HEAD~3 # últimos 3 commits
git rebase -i main # todos commits exclusivos da branch
Comandos dentro do editor de rebase interativo:
| Comando | Ação |
|---|---|
| pick | manter commit sem mudança |
| reword | manter, editar mensagem |
| squash | juntar com commit anterior, editar mensagem |
| fixup | juntar com anterior, descartar mensagem |
| drop | remover commit |
| edit | pausar para amend |
git rebase --abort # cancelar
git rebase --continue # continuar após resolver conflito
Regra de ouro: nunca rebase commits já pushados em branch compartilhada. Reescreve história — quebra o repo dos outros.
Remotos
# ver remotos
git remote -v
# adicionar
git remote add origin git@github.com:user/repo.git
git remote add upstream git@github.com:original/repo.git
# remover / renomear
git remote remove origin
git remote rename origin old-origin
# fetch — baixar sem merge
git fetch origin
git fetch --all
# pull
git pull # fetch + merge/rebase
git pull origin main
git pull --rebase origin main
# push
git push -u origin main # define upstream + push
git push # push para upstream configurado
git push --tags # push tags
git push origin --delete feature/auth # deletar branch remota
git push --force-with-lease # force seguro (falha se remoto mudou)
Desfazer Mudanças
--soft
Mais seguro
Commit removidosim
Staging mantidosim
Arquivos mantidossim
--mixed
Padrão
Commit removidosim
Staging limpolimpo
Arquivos mantidossim
--hard
Destrutivo
Commit removidosim
Staging limpolimpo
Arquivos perdidosperdidos
# descartar mudanças no working tree (não staged)
git restore arquivo.txt
# tirar do staging (mantém mudanças)
git restore --staged arquivo.txt
# desfazer último commit — manter staging
git reset --soft HEAD~1
# desfazer último commit — manter working tree
git reset --mixed HEAD~1 # (padrão)
# desfazer último commit — DESCARTAR TUDO
git reset --hard HEAD~1
# reverter commit (cria commit inverso — seguro para branches públicas)
git revert abc123
# corrigir último commit
git commit --amend -m "mensagem corrigida"
git add esquecido.txt && git commit --amend --no-edit
# limpar untracked
git clean -n # dry run — mostrar o que seria deletado
git clean -fd # deletar arquivos e diretórios
Stash
Guarda mudanças temporariamente sem commitar. Útil ao trocar de branch com trabalho inacabado.
git stash # guardar working tree + staging
git stash push -m "wip: auth" # com nome descritivo
git stash -u # incluir untracked files
git stash list # listar
git stash show # diff do último
git stash show stash@{1} # diff de stash específico
git stash pop # aplicar e remover último
git stash apply # aplicar sem remover
git stash apply stash@{2} # stash específico
git stash drop # remover último
git stash clear # remover todos
# criar branch a partir de stash
git stash branch feature/nova stash@{0}
Inspecionar Histórico
# buscar texto em commits
git log -S "funcaoXYZ" # commits que adicionaram/removeram
git log -G "regex" # commits cujo diff bate com regex
git log --grep="fix" # mensagens contendo
# conteúdo de arquivo em commit específico
git show abc123:caminho/arquivo.txt
# quem escreveu cada linha
git blame arquivo.txt
git blame -L 10,30 arquivo.txt
# encontrar commit que introduziu um bug
git bisect start
git bisect bad # commit atual tem o bug
git bisect good v1.0.0 # esta tag estava boa
# git testa commits binariamente, para cada:
# git bisect good / git bisect bad
git bisect reset
# ver referências (inclui deletadas — último recurso)
git reflog
git reflog show main
Cherry-pick
Aplica commits específicos de outra branch sem mergear tudo.
git cherry-pick abc123 # um commit
git cherry-pick abc123..def456 # range
git cherry-pick abc123 --no-commit # aplicar sem commitar
git cherry-pick --abort
git cherry-pick --continue
.gitignore
# extensões e arquivos
*.log
*.env
.DS_Store
Thumbs.db
# diretórios
node_modules/
dist/
.next/
build/
# exceção
!important.log
# qualquer nível de profundidade
**/build/
# apenas na raiz
/config.local.js
# ignorar arquivo já rastreado
echo "config.local.js" >> .gitignore
git rm --cached config.local.js
git commit -m "chore: untrack config.local.js"
# diagnóstico
git status --ignored
git check-ignore -v arquivo.txt
Templates prontos:
github.com/github/gitignore — Node, Python, macOS, etc.Mensagens de Commit — Conventional Commits
():
[corpo — o porquê, não o quê]
[rodapé — BREAKING CHANGE: ..., Closes #123]
feat
nova funcionalidade
fix
correção de bug
docs
documentação
style
formatação sem lógica
refactor
sem feat nem fix
test
adicionar testes
chore
build, config, deps
ci
CI/CD pipelines
git commit -m "feat(auth): add JWT refresh token rotation"
git commit -m "fix(api): handle null user on session expiry"
git commit -m "chore: upgrade vite to 5.4.0"
git commit -m "docs: add docker compose examples to README"
Regras: linha de assunto ≤ 72 chars · verbo imperativo (add, fix, remove) · sem ponto final · corpo separado por linha em branco.
Workflows
Feature Branch (padrão)
Feature Branch Workflow
1
git switch main && git pull
2
git switch -c feature/minha-feature
3
git commit -m "feat: ..." (vários)
4
git push -u origin feature/minha-feature
5
gh pr create → code review → merge
6
git switch main && git pull && git branch -d feature/minha-feature
Squash antes do PR
# juntar últimos 4 commits em 1 limpo
git rebase -i HEAD~4
# trocar pick → squash em todos exceto o primeiro
# editar mensagem consolidada
git push --force-with-lease
Hotfix
git switch main
git switch -c hotfix/critical-bug
# corrigir e commitar
git switch main
git merge --no-ff hotfix/critical-bug
git tag -a v1.0.1 -m "Hotfix: description"
git branch -d hotfix/critical-bug
git push && git push --tags
Aliases
# ~/.gitconfig
[alias]
st = status
co = checkout
sw = switch
br = branch
lg = log --oneline --graph --decorate --all
ll = log --oneline -20
last = log -1 HEAD
undo = reset HEAD~1 --mixed
unstage = restore --staged
aliases = config --get-regexp alias
pushf = push --force-with-lease
gone = !git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -D
Comandos de Emergência
# recuperar commit deletado (até 90 dias)
git reflog
git switch -c recover-branch abc123
# arquivo deletado antes do commit
git restore arquivo-deletado.txt
# desfazer reset --hard
git reflog
git reset --hard abc123 # SHA antes do reset
# ver as 3 versões num conflito de merge
git show :1:arquivo.txt # ancestral comum
git show :2:arquivo.txt # nossa versão (HEAD)
git show :3:arquivo.txt # versão deles
# force push acidental em branch compartilhada
git reflog show origin/main
git push origin SHA_ANTES:main
git reflog é a rede de segurança final. Guarda todos os movimentos de HEAD pelos últimos 90 dias, mesmo commits "deletados".
GitHub CLI
# autenticar
gh auth login
# PRs
gh pr create --title "feat: login" --body "..."
gh pr list
gh pr view 42
gh pr checkout 42
gh pr merge 42 --squash
gh pr merge 42 --rebase
# Issues
gh issue create --title "Bug: ..."
gh issue list
gh issue close 10
# Repo
gh repo clone user/repo
gh repo fork user/repo --clone
# Actions
gh run list
gh run view 123
gh run watch 123
Referência Rápida
| Situação | Comando |
|---|---|
| Desfazer último commit, manter mudanças | git reset HEAD~1 |
| Descartar mudanças em arquivo | git restore arquivo |
| Tirar arquivo do staging | git restore --staged arquivo |
| Guardar trabalho sem commitar | git stash |
| Buscar commit que quebrou algo | git bisect start |
| Aplicar commit de outra branch | git cherry-pick abc123 |
| Ver quem escreveu linha | git blame arquivo |
| Recuperar algo deletado | git reflog |
| Limpar arquivos não rastreados | git clean -fd |
| Comparar branches | git diff main..feature |
| Force push seguro | git push --force-with-lease |
| Histórico visual | git log --oneline --graph --all |
| Ver conteúdo de arquivo em commit | git show abc123:path/file |
| Ignorar arquivo já rastreado | git rm --cached arquivo |