O staging area: entendendo o índice do Git
O que é o staging area (índice)?
O staging area, também conhecido como índice ou cache, é uma área intermediária no Git que fica entre o diretório de trabalho (working directory) e o repositório local. Ele funciona como uma "mesa de preparação" onde você organiza e revisa as mudanças antes de confirmá-las no histórico do projeto.
O Git trabalha com três árvores principais:
- Working Directory — seus arquivos reais no disco, onde você edita o código
- Staging Area (Índice) — uma área de preparação armazenada no arquivo
.git/index - Repositório Local — o banco de dados de objetos do Git (commits, árvores, blobs)
O arquivo .git/index é o coração do staging area. Ele contém metadados sobre cada arquivo rastreado, incluindo o nome, modo de permissão, timestamp e, mais importante, o hash SHA-1 do blob que representa o conteúdo do arquivo naquele momento.
# Estrutura simplificada do .git/index
# Cada entrada contém:
# - Metadados (ctime, mtime, dev, ino, mode, uid, gid, size)
# - SHA-1 do blob
# - Nome do arquivo
Por que o staging area existe?
O staging area resolve um problema fundamental no controle de versão: como separar mudanças logicamente independentes que você fez simultaneamente.
Imagine que você está trabalhando em um arquivo e fez duas alterações não relacionadas: uma correção de bug e uma melhoria de desempenho. Sem o staging, você seria forçado a commitá-las juntas. Com o staging, você pode:
- Selecionar partes específicas de arquivos para commit
- Criar commits lógicos e atômicos sem misturar alterações não relacionadas
- Revisar e validar mudanças antes de confirmá-las no histórico
# Exemplo: duas alterações no mesmo arquivo
# Arquivo: app.js
# Linha 10: Correção de bug
# Antes: const result = calculate(x, y) // bug: ordem errada
# Depois: const result = calculate(y, x)
# Linha 25: Melhoria de desempenho
# Antes: for(let i=0; i<data.length; i++) { ... }
# Depois: data.forEach(item => { ... })
Operações básicas com o staging area
git add — Movendo arquivos para o staging
# Adicionar um arquivo específico
$ git add index.html
# Adicionar todos os arquivos modificados e não rastreados
$ git add .
# Adicionar múltiplos arquivos específicos
$ git add src/main.js src/utils.js
git status — Visualizando o estado atual
$ git status
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: index.html
new file: src/utils.js
Changes not staged for commit:
modified: style.css
Untracked files:
README.md
git restore --staged — Removendo do staging
# Remover um arquivo do staging (mantendo as alterações no working directory)
$ git restore --staged index.html
# Remover todos os arquivos do staging
$ git restore --staged .
Inspecionando o staging area
git diff --cached — Diferenças entre staging e último commit
$ git diff --cached
diff --git a/index.html b/index.html
index e69de29..d95f3ad 100644
--- a/index.html
+++ b/index.html
@@ -0,0 +1,3 @@
+<html>
+ <body>Hello World</body>
+</html>
git diff — Diferenças entre working directory e staging
$ git diff
diff --git a/style.css b/style.css
index 4b825dc..a3f5a6b 100644
--- a/style.css
+++ b/style.css
@@ -1 +1,2 @@
body { margin: 0; }
+.highlight { color: red; }
git ls-files --stage — Listando o conteúdo detalhado do índice
$ git ls-files --stage
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 index.html
100644 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 0 src/main.js
100644 3b18e512dba79e4c8300dd08aeb37f8e728b8dad 0 src/utils.js
Gerenciamento avançado do staging
git add -p — Adicionando partes específicas
O modo patch permite selecionar partes específicas (hunks) de um arquivo modificado:
$ git add -p style.css
diff --git a/style.css b/style.css
index 4b825dc..a3f5a6b 100644
--- a/style.css
+++ b/style.css
@@ -1 +1,3 @@
body { margin: 0; }
+.header { background: blue; }
+.footer { color: gray; }
Stage this hunk [y,n,q,a,d,/,s,e,?]? y
@@ -3,0 +5,2 @@
+.highlight { color: red; }
+.warning { color: orange; }
Stage this hunk [y,n,q,a,d,/,s,e,?]? n
git add -i — Modo interativo
$ git add -i
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> 1
staged unstaged path
1: unchanged +4/-0 index.html
2: unchanged +2/-1 src/main.js
.gitignore e o staging
Arquivos listados no .gitignore não aparecem como untracked e não podem ser adicionados ao staging acidentalmente:
# .gitignore
node_modules/
*.log
.env
dist/
Staging e o fluxo de trabalho diário
Ciclo típico vs. git commit -a
# Ciclo explícito (recomendado)
$ git add src/main.js
$ git add tests/main.test.js
$ git commit -m "Adiciona validação de entrada"
# Ciclo abreviado (menos controle)
$ git commit -a -m "Adiciona validação de entrada"
Staging parcial para commits atômicos
# Situação: você editou três arquivos para duas tarefas diferentes
# Tarefa 1: Correção de bug no login
$ git add src/login.js
$ git commit -m "Corrige validação de email no login"
# Tarefa 2: Nova funcionalidade de relatório
$ git add src/report.js src/utils.js
$ git commit -m "Adiciona geração de relatório mensal"
Erros comuns e como corrigir
# Erro: adicionou arquivo grande acidentalmente
$ git add bigfile.zip
$ git restore --staged bigfile.zip
$ echo "*.zip" >> .gitignore
# Erro: adicionou arquivo com senhas
$ git add .env
$ git restore --staged .env
$ echo ".env" >> .gitignore
O staging area em operações de merge e reset
Staging durante conflitos de merge
Quando ocorre um conflito de merge, o índice armazena até três versões do arquivo:
$ git ls-files --stage -u
100644 2a7d6... 1 conflicted.txt # versão base (ancestral comum)
100644 8c3f2... 2 conflicted.txt # versão do branch atual (HEAD)
100644 4e9b1... 3 conflicted.txt # versão do branch sendo mesclado
git reset e o staging
# --soft: move HEAD apenas, staging e working directory intactos
$ git reset --soft HEAD~1
# --mixed (padrão): move HEAD e staging, working directory intacto
$ git reset HEAD~1
# --hard: move HEAD, staging e working directory
$ git reset --hard HEAD~1
git checkout e git switch
# Trocar de branch atualiza o staging com os arquivos do novo branch
$ git switch feature-branch
# Se houver mudanças não commitadas no staging, o Git pode impedir a troca
$ git switch main
error: Your local changes to the following files would be overwritten...
Boas práticas e dicas finais
-
Commits atômicos: Use o staging para separar mudanças lógicas. Cada commit deve representar uma única mudança coesa.
-
Revise antes de commitar: Sempre execute
git statusegit diff --cachedantes de fazer commit. -
Evite
git commit -aem projetos complexos: O staging explícito comgit adddá controle total sobre o que entra em cada commit. -
Use
git add -ppara commits cirúrgicos: Quando você fez várias alterações no mesmo arquivo, o modo patch permite selecionar apenas as partes relevantes. -
Mantenha o staging limpo: Se você mudar de ideia sobre uma alteração, use
git restore --stagedpara removê-la do staging antes do commit.
# Fluxo recomendado para commits limpos
$ git status # Verificar o que foi modificado
$ git diff # Revisar mudanças não staged
$ git add -p src/feature.js # Adicionar partes específicas
$ git diff --cached # Revisar o que será commitado
$ git commit -m "Mensagem descritiva"
O staging area é uma das ferramentas mais poderosas do Git para manter um histórico limpo e compreensível. Dominá-lo transforma seu fluxo de trabalho de "commits bagunçados" para "commits que contam uma história clara do seu projeto".
Referências
- Documentação oficial do Git - git-add — Documentação completa do comando
git adde suas opções interativas - Pro Git Book - Recording Changes to the Repository — Capítulo fundamental sobre staging area e operações básicas
- Git SCM - Staging Area Explained — Explicação oficial do Git sobre o propósito do staging area
- Atlassian Git Tutorial - Staging in Git — Tutorial prático sobre staging com exemplos interativos
- Git Documentation - git-reset — Documentação do
git resete seu impacto nos três estados (soft, mixed, hard) - Git Documentation - git-ls-files — Referência para inspecionar o conteúdo do índice com
git ls-files --stage - GitHub Git Cheat Sheet — Resumo visual dos comandos Git incluindo staging area