AUTONETOPS

Cover Image for Git Pt.2

Git Pt.2

·

5 min read

Comandos Avançados: Quando as Coisas Ficam Complicadas

O básico (add, commit, push, pull) resolve 90% dos casos. Mas os outros 10% são onde os problemas críticos acontecem. Dominar os comandos a seguir é o que diferencia um usuário iniciante de um expert.

git stash: Salvando seu Trabalho Temporariamente

Cenário: Você está no meio da configuração de uma nova política de BGP (feature/bgp-policy), mas um incidente urgente acontece e você precisa verificar o estado de uma configuração no branch main imediatamente. Seu trabalho está incompleto e você não quer fazer um commit "WIP" (Work in Progress).

O git stash salva suas modificações não commitadas em uma "pilha" temporária e limpa seu diretório de trabalho, deixando-o no estado do último commit (HEAD).

graph TD
    A[Diretório de Trabalho com Mudanças] -- git stash --> B(Pilha de Stash);
    B -- git stash pop --> C[Diretório de Trabalho Restaurado];

Cheatsheet do stash:

ComandoDescrição
git stashSalva as mudanças atuais na pilha de stash.
git stash listLista todos os stashes salvos.
git stash popAplica o stash mais recente e o remove da pilha.
git stash applyAplica o stash mais recente, mas o mantém na pilha.
git stash dropDescarta o stash mais recente.

Exemplo de fluxo:

# Você está no branch 'feature/bgp-policy' com trabalho não salvo
git status # Mostra arquivos modificados

# Salva o trabalho para atender a uma emergência
git stash

# Muda para o branch principal para investigar
git checkout main
# ... faz a investigação ...

# Volta para seu branch de feature
git checkout feature/bgp-policy

# Restaura seu trabalho não salvo
git stash pop

git status # Seus arquivos modificados estão de volta!

git revert vs git reset: A Batalha pela História do Git

Ambos os comandos desfazem mudanças, mas de maneiras fundamentalmente diferentes. A escolha errada aqui pode causar grandes problemas para sua equipe.

Característicagit revert <commit>git reset --hard <commit>
AçãoCria um novo commit que é o inverso do commit especificado.Move o ponteiro do branch para um commit anterior, descartando todos os commits posteriores.
HistóricoNão reescreve o histórico. Adiciona ao histórico. É seguro.Reescreve (destrói) o histórico. É perigoso.
Uso PrincipalReverter um commit que já foi compartilhado com a equipe (ex: já está no main).Desfazer commits locais que ainda não foram compartilhados.
ColaboraçãoSeguro para branches compartilhados.NUNCA use em branches compartilhados (como main).

Visualizando git revert:

Imagine que o commit C introduziu um bug em produção.

gitGraph
    commit id: "A"
    commit id: "B"
    commit id: "C" type: HIGHLIGHT
    commit id: "D"
    commit id: "C'" type: REVERSE msg: "Revert feat: Adiciona bug"

O git revert C cria um novo commit C' que desfaz as mudanças de C. O histórico é preservado e a mudança é transparente para todos.

Visualizando git reset:

Agora, imagine que C e D são commits ruins que você fez localmente e ainda não compartilhou.

gitGraph
    commit id: "A"
    commit id: "B"
    commit id: "C"
    commit id: "D"

Executar git reset --hard B moverá o HEAD do main de volta para B, e os commits C e D serão perdidos (ou, mais precisamente, se tornarão órfãos, aguardando para serem limpos pelo garbage collector do Git).

gitGraph
    commit id: "A"
    commit id: "B"

Regra de ouro: Se o commit está no repositório remoto (GitHub/GitLab), use git revert. Se o commit só existe na sua máquina local, git reset é uma opção.

git rebase: Reescrevendo a História para um Futuro Mais Limpo

Cenário: Você criou seu branch feature/nova-firewall-policy a partir do main. Enquanto você trabalhava, outros engenheiros mesclaram várias outras mudanças no main. Seu branch de feature agora está desatualizado, e um git merge main criaria um "merge commit" que polui o histórico.

O git rebase resolve isso. Ele pega todos os commits do seu branch e os reaplica "em cima" do estado mais recente do branch alvo (main).

graph TD
    subgraph "Antes do Rebase"
        A((A)) --> B((B)) --> C((C<br>main))
        B --> D((D)) --> E((E<br>feature))
    end
    subgraph "Depois de 'git rebase main'"
        A2((A)) --> B2((B)) --> C2((C<br>main)) --> D2((D')) --> E2((E'<br>feature))
    end
    style C fill:#f9f,stroke:#333
    style E fill:#f9f,stroke:#333
    style C2 fill:#f9f,stroke:#333
    style E2 fill:#f9f,stroke:#333

Fluxo de trabalho com rebase:

# No seu branch de feature
git checkout feature/nova-firewall-policy

# Busca as últimas mudanças do remoto
git fetch origin

# Rebase do seu branch em cima do 'main' mais recente
git rebase origin/main

# Agora seu branch está atualizado e pronto para um merge limpo (fast-forward)

Aviso: Assim como o reset, o rebase reescreve o histórico (os hashes dos commits D e E mudam para D' e E'). Nunca faça rebase de um branch que é compartilhado e usado por múltiplos desenvolvedores (como o main). É seguro para seus próprios branches de feature antes de abrir um PR.

git reflog e git bisect: As Ferramentas do Detetive

  • git reflog (Reference Log): Seu salva-vidas. O Git mantém um registro de quase tudo que você faz (commits, resets, checkouts). Se você usou git reset e acha que perdeu um commit para sempre, o git reflog mostrará o hash daquele commit perdido, e você pode recuperá-lo com git checkout <hash> ou git cherry-pick <hash>. É a sua rede de segurança pessoal.

  • git bisect: O caçador de bugs. Se você sabe que um bug foi introduzido em algum momento nos últimos 100 commits, mas não sabe onde, o git bisect automatiza a busca. Você informa um commit "bom" (onde o bug não existia) e um commit "ruim" (onde o bug existe). O Git então faz uma busca binária, fazendo checkout de commits no meio do caminho e perguntando a você se o bug está presente. Em poucos passos, ele aponta o commit exato que introduziu a regressão. Isso é incrível para encontrar qual mudança de configuração quebrou a conectividade.

;