<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Troubleshooting on kenji.blog</title><link>http://kenji.blog/pt/tags/troubleshooting/</link><description>Recent content in Troubleshooting on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>pt</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 17:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/pt/tags/troubleshooting/index.xml" rel="self" type="application/rss+xml"/><item><title>Erros comuns de iniciantes no Git e comandos de solução (resolução de conflitos, etc.)</title><link>http://kenji.blog/pt/p/git-beginners-mistakes-and-solutions/</link><pubDate>Sat, 12 Sep 2026 17:00:00 +0900</pubDate><guid>http://kenji.blog/pt/p/git-beginners-mistakes-and-solutions/</guid><description>&lt;img src="http://kenji.blog/p/git-beginners-mistakes-and-solutions/img/eyecatch.jpg" alt="Featured image of post Erros comuns de iniciantes no Git e comandos de solução (resolução de conflitos, etc.)" />&lt;h1 id="erros-comuns-de-iniciantes-no-git-e-comandos-de-solução-resolução-de-conflitos-etc">Erros comuns de iniciantes no Git e comandos de solução (resolução de conflitos, etc.)
&lt;/h1>&lt;h2 id="1-introdução-por-que-cometemos-erros-no-git">1. Introdução: Por que cometemos erros no Git?
&lt;/h2>&lt;p>No desenvolvimento de software, o Git tornou-se tão indispensável quanto o ar ou a água. No entanto, para muitos iniciantes (e às vezes até para os mais experientes), o Git pode parecer uma &amp;ldquo;terrível caixa preta mágica&amp;rdquo;. Commits que desaparecem, grandes quantidades de alterações empurradas para a branch errada, ou mensagens de erro de conflito nunca vistas enchendo a tela&amp;hellip; Ao cair nessas &amp;ldquo;armadilhas do Git&amp;rdquo;, o progresso do trabalho é completamente interrompido e, no pior dos casos, você é tomado pelo medo de acabar destruindo o código-fonte.&lt;/p>
&lt;p>Por que o Git é tão difícil e propenso a erros? O maior motivo é que &amp;ldquo;as pessoas decoram comandos superficiais e os usam sem entender o que está acontecendo dentro do Git&amp;rdquo;. Embora o Git seja baseado em uma filosofia de design robusta como um sistema de controle de versão distribuído (DVCS), sua interface (CLI) nem sempre é intuitiva.&lt;/p>
&lt;p>Neste artigo, categorizamos muitos &amp;ldquo;deslizes (erros comuns)&amp;rdquo; que os iniciantes no Git frequentemente encontram na prática, e apresentamos os comandos específicos de solução para cada um deles. No entanto, não será apenas uma lista de comandos (cheat sheet). Iremos explorar a fundo, com um volume de mais de 10.000 caracteres, &amp;ldquo;por que esses erros ocorrem&amp;rdquo; e &amp;ldquo;como os dados se movem internamente no Git ao executar esse comando&amp;rdquo;, utilizando a estrutura do diretório &lt;code>.git&lt;/code>, a base matemática do algoritmo Diff em segundo plano e diagramas no Mermaid.&lt;/p>
&lt;p>Ao terminar de ler este artigo, você deverá estar livre do sentimento de &amp;ldquo;o Git assusta&amp;rdquo; e, em vez disso, estará convencido de que &amp;ldquo;não há parceiro mais confiável do que o Git&amp;rdquo;. Então, vamos mergulhar no mundo profundo do Git.&lt;/p>
&lt;hr>
&lt;h2 id="2-o-abismo-do-git-entendendo-a-estrutura-interna-do-diretório-git">2. O abismo do Git: Entendendo a estrutura interna do diretório &lt;code>.git&lt;/code>
&lt;/h2>&lt;p>O primeiro passo para facilitar muitas resoluções de problemas é saber como o Git armazena os dados. A pasta oculta &lt;code>.git&lt;/code> presente no diretório raiz do seu projeto é o próprio coração do Git. O Git não é apenas um sistema que registra sequencialmente as diferenças (patches) de arquivos, mas gerencia os dados como um &lt;strong>fluxo de snapshots&lt;/strong>.&lt;/p>
&lt;h3 id="21-modelo-de-objetos-blob-tree-commit">2.1 Modelo de objetos: Blob, Tree, Commit
&lt;/h3>&lt;p>O Git usa principalmente três objetos para representar o estado do repositório. Esses objetos são armazenados em &lt;code>.git/objects&lt;/code>.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Blob (Binary Large Object)&lt;/strong>
É o objeto que armazena o próprio conteúdo do arquivo. Informações como nome do arquivo ou permissões não estão incluídas aqui. Sequências de bytes puras são compactadas com zlib e identificadas por um valor de hash SHA-1 (40 caracteres hexadecimais).&lt;/li>
&lt;li>&lt;strong>Tree&lt;/strong>
É o objeto que representa a estrutura de diretórios. O objeto Tree contém ponteiros (valores de hash SHA-1) para outros objetos Tree (subdiretórios) ou objetos Blob (arquivos), bem como seus nomes de arquivos e permissões de acesso. Desempenha um papel semelhante a um diretório UNIX.&lt;/li>
&lt;li>&lt;strong>Commit&lt;/strong>
Mantém um ponteiro para o objeto Tree de nível superior do repositório em um determinado momento, metadados (autor, data e hora do commit, mensagem do commit) e um ponteiro para o commit imediatamente anterior (commit pai).&lt;/li>
&lt;/ol>
&lt;pre class="mermaid">
graph TD
Commit1[&amp;#34;Commit (Hash: 9f8a)&amp;#34;] --&amp;gt; Tree1[&amp;#34;Tree (Hash: 4b82)&amp;#34;]
Tree1 --&amp;gt; Blob1[&amp;#34;Blob (Hash: 8d7e) : index.js&amp;#34;]
Tree1 --&amp;gt; Tree2[&amp;#34;Tree (Hash: 3a2c) : src/&amp;#34;]
Tree2 --&amp;gt; Blob2[&amp;#34;Blob (Hash: 5f1b) : app.js&amp;#34;]
&lt;/pre>
&lt;h3 id="22-a-verdadeira-natureza-do-head-e-das-referências-refs">2.2 A verdadeira natureza do HEAD e das Referências (Refs)
&lt;/h3>&lt;p>Ao trabalhar com o Git, a palavra &lt;code>HEAD&lt;/code> é vista com frequência. Esta é uma &lt;strong>referência simbólica (Symbolic Reference)&lt;/strong> que aponta para a branch (ou commit) atualmente verificada (checked out).
Se você abrir o arquivo &lt;code>.git/HEAD&lt;/code> em um editor de texto, verá uma string escrita assim:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">ref: refs/heads/main
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Isso significa que &amp;ldquo;o estado atual está na ponta da branch &lt;code>main&lt;/code>&amp;rdquo;. E se você abrir &lt;code>.git/refs/heads/main&lt;/code>, encontrará um hash SHA-1 de 40 caracteres, que aponta para o objeto Commit mais recente.
A branch do Git é simplesmente um ponteiro leve (arquivo) que aponta para um commit específico. Sabendo desse fato, o medo de &amp;ldquo;se eu deletar a branch, todos os meus arquivos sumirão?&amp;rdquo; desaparece.&lt;/p>
&lt;hr>
&lt;h2 id="3-decifrando-o-git-com-matemática-algoritmo-diff-e-função-hash">3. Decifrando o Git com matemática: Algoritmo Diff e função Hash
&lt;/h2>&lt;p>Quando o Git detecta conflitos ou exibe diferenças em arquivos, algoritmos avançados estão em execução internamente.&lt;/p>
&lt;h3 id="31-algoritmo-diff-de-myers">3.1 Algoritmo Diff de Myers
&lt;/h3>&lt;p>O algoritmo de detecção de diferença padrão do Git é o algoritmo idealizado por Eugene W. Myers. Quando temos dois arquivos de texto $A$ e $B$, o problema de encontrar o &amp;ldquo;menor procedimento de edição (inserções e exclusões)&amp;rdquo; para transformar $A$ em $B$ pode ser modelado como o problema do caminho mais curto na teoria dos grafos.&lt;/p>
&lt;p>Deixe os comprimentos das strings serem $N, M$, respectivamente, e a soma seja $V = N + M$. No algoritmo de Myers, procuramos a distância de edição (Edit Distance) $D$. A complexidade de tempo desse algoritmo é expressa pela seguinte fórmula:&lt;/p>
$$ \mathcal{O}(V \cdot D) $$&lt;p>Aqui, se as diferenças entre os arquivos forem pequenas (ou seja, $D$ é pequeno), o algoritmo será executado muito rápido $\mathcal{O}(V)$. No entanto, se os arquivos forem completamente diferentes, teremos $D \approx V$, e a pior complexidade computacional será $\mathcal{O}(V^2)$.&lt;/p>
&lt;h3 id="32-patience-diff-e-histogram-diff">3.2 Patience Diff e Histogram Diff
&lt;/h3>&lt;p>Embora o algoritmo de Myers seja aprimorado, ele pode gerar diferenças que não são intuitivas (não fazem sentido) para os humanos quando, por exemplo, a ordem das funções ou classes for significativamente alterada. Para resolver isso, o Git implementou o &lt;code>Patience Diff&lt;/code> e o &lt;code>Histogram Diff&lt;/code>.&lt;/p>
&lt;p>O Patience Diff se concentra em &amp;ldquo;linhas únicas que aparecem apenas uma vez em ambos os arquivos&amp;rdquo; e encontra a maior subsequência comum (Longest Common Subsequence: LCS) delas. Se o número de elementos únicos for $U$, o cálculo da LCS pode ser resolvido com a seguinte complexidade computacional:&lt;/p>
$$ \mathcal{O}(U \log U) $$&lt;p>Quando você acha difícil resolver um conflito, usar &lt;code>git diff --histogram&lt;/code> ou especificar esse algoritmo na estratégia de merge (&lt;code>git merge -s recursive -X histogram&lt;/code>) é uma alternativa.&lt;/p>
&lt;h3 id="33-sha-1-e-a-probabilidade-de-colisão">3.3 SHA-1 e a probabilidade de colisão
&lt;/h3>&lt;p>O Git gerencia todos os objetos usando valores de hash SHA-1. O tamanho do espaço de hash é $2^{160}$. Aproximando a probabilidade de colisão de hash (conteúdos diferentes tendo o mesmo valor de hash) usando o Paradoxo do Aniversário (Birthday Paradox), o número de objetos $k$ necessário para que a probabilidade de colisão $p$ chegue a 50% é o seguinte:&lt;/p>
$$ k \approx \sqrt{2 \ln(2)} \cdot 2^{80} \approx 1.2 \times 2^{80} $$&lt;p>Esse é um número astronômico e, no desenvolvimento de software normal, a probabilidade de uma colisão não intencional é virtualmente zero. Portanto, o Git opera confiando no valor do hash como uma &amp;ldquo;ID única absoluta&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;h2 id="4-estudo-de-caso-1-fiz-o-commit-na-branch-errada">4. Estudo de caso 1: Fiz o commit na branch errada!
&lt;/h2>&lt;p>&lt;strong>[Situação]&lt;/strong>
Sem perceber que estava trabalhando na branch &lt;code>main&lt;/code>, você escreveu todo o código da nova funcionalidade e, para piorar, até executou um &lt;code>git commit&lt;/code>. A intenção original era criar uma branch chamada &lt;code>feature/login&lt;/code> e trabalhar lá!&lt;/p>
&lt;h3 id="solução-git-reset-e-criação-de-branch">Solução: &lt;code>git reset&lt;/code> e criação de branch
&lt;/h3>&lt;p>No Git, os commits são objetos independentes e as branches são apenas ponteiros. Portanto, o problema pode ser resolvido instantaneamente com a operação: &amp;ldquo;criar uma nova branch e retroceder o ponteiro da branch atual&amp;rdquo;.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. Crie uma nova branch apontando para o commit atual (o commit feito por engano)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git branch feature/login
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. Retroceda o ponteiro da branch main para o commit anterior (HEAD~1)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># O uso do --keep permite que você redefina de forma segura, mantendo as alterações não confirmadas no diretório de trabalho.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git reset --keep HEAD~1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 3. Mude para a branch correta&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git checkout feature/login
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="ilustração-o-que-aconteceu-internamente">Ilustração: O que aconteceu internamente?
&lt;/h3>&lt;p>Vamos visualizar o movimento do ponteiro da branch neste momento usando o &lt;code>gitGraph&lt;/code> do Mermaid.&lt;/p>
&lt;pre class="mermaid">
gitGraph
commit id: &amp;#34;Initial commit&amp;#34;
commit id: &amp;#34;Bugfix&amp;#34;
commit id: &amp;#34;Mistaken Commit&amp;#34; type: HIGHLIGHT
branch feature/login
checkout feature/login
checkout main
&lt;/pre>
&lt;p>Inicialmente, &lt;code>main&lt;/code> e &lt;code>HEAD&lt;/code> apontavam para &amp;ldquo;Mistaken Commit&amp;rdquo;, mas com &lt;code>git branch feature/login&lt;/code>, um novo ponteiro é criado lá. Após isso, apenas o ponteiro &lt;code>main&lt;/code> retorna à posição de &amp;ldquo;Bugfix&amp;rdquo; por causa do &lt;code>git reset&lt;/code>. Os objetos em si não foram excluídos.&lt;/p>
&lt;hr>
&lt;h2 id="5-estudo-de-caso-2-quero-desfazer-um-commit-já-feito-por-push">5. Estudo de caso 2: Quero desfazer um commit já feito por push!
&lt;/h2>&lt;p>&lt;strong>[Situação]&lt;/strong>
Você fez o commit de um código cheio de bugs escrito durante a madrugada e, além disso, publicou-o no repositório remoto com &lt;code>git push origin main&lt;/code>. Você percebe o bug grave e empalidece.&lt;/p>
&lt;h3 id="solução-1-cancelar-o-histórico-com-git-revert-recomendadoseguro">Solução 1: Cancelar o histórico com &lt;code>git revert&lt;/code> (Recomendado/Seguro)
&lt;/h3>&lt;p>No desenvolvimento em equipe, é estritamente proibido alterar o histórico de commits que já foram enviados usando &lt;code>git reset&lt;/code> ou afins. Isso causará inconsistência com os repositórios locais de outros desenvolvedores. A abordagem correta é &lt;strong>&amp;ldquo;criar um novo commit inverso que desfaça completamente as alterações do commit errado&amp;rdquo;&lt;/strong>. Este é o &lt;code>git revert&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Crie um commit que desfaça o commit mais recente&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git revert HEAD
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>main 7f3a8b2&lt;span class="o">]&lt;/span> Revert &lt;span class="s2">&amp;#34;Mensagem do commit incorreto&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="m">1&lt;/span> file changed, &lt;span class="m">1&lt;/span> insertion&lt;span class="o">(&lt;/span>+&lt;span class="o">)&lt;/span>, &lt;span class="m">10&lt;/span> deletions&lt;span class="o">(&lt;/span>-&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Faça o push para o remoto&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git push origin main
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;pre class="mermaid">
gitGraph
commit id: &amp;#34;Commit A&amp;#34;
commit id: &amp;#34;Commit B (Mistake)&amp;#34;
commit id: &amp;#34;Revert Commit B&amp;#34; type: REVERSE
&lt;/pre>
&lt;p>O histórico continua avançando e apenas o estado do código volta ao que era.&lt;/p>
&lt;h3 id="solução-2-alterar-o-histórico-com-git-push---force-with-lease">Solução 2: Alterar o histórico com &lt;code>git push --force-with-lease&lt;/code>
&lt;/h3>&lt;p>Se você acabou de fazer push para uma branch que só você usa, alterar o histórico pode ser tolerado.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Redefina o commit localmente e corrija&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git reset --hard HEAD~1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git add .
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git commit -m &lt;span class="s2">&amp;#34;Correct implementation&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Substituição forçada do histórico remoto&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git push origin feature/login --force-with-lease
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>O &lt;code>--force-with-lease&lt;/code> é um push forçado seguro para evitar o acidente de sobrescrever acidentalmente o trabalho de outras pessoas.&lt;/p>
&lt;hr>
&lt;h2 id="6-estudo-de-caso-3-quero-mudar-para-outra-branch-no-meio-do-trabalho-a-mágica-do-stash">6. Estudo de caso 3: Quero mudar para outra branch no meio do trabalho (A mágica do Stash)
&lt;/h2>&lt;p>&lt;strong>[Situação]&lt;/strong>
Durante a implementação de um novo recurso na branch &lt;code>feature/A&lt;/code>, o código-fonte ainda está pela metade e nem sequer compila. De repente, seu chefe ordena: &amp;ldquo;Há um bug crítico no ambiente de produção da branch &lt;code>main&lt;/code>, corrija-o agora mesmo!&amp;rdquo;&lt;/p>
&lt;h3 id="solução-salvar-o-trabalho-com-git-stash">Solução: Salvar o trabalho com &lt;code>git stash&lt;/code>
&lt;/h3>&lt;p>O &lt;code>git stash&lt;/code> é um comando que salva temporariamente as alterações não confirmadas (uncommitted) em uma área temporária.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. Salve o trabalho atual&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git stash push -m &lt;span class="s2">&amp;#34;WIP: feature A partially implemented&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. Torne possível mudar para a branch main&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git checkout main
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ... (Faça a correção do bug crítico, commit e push) ...&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 3. Volte para a branch original quando terminar o trabalho&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git checkout feature/A
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 4. Restaure as alterações salvas&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git stash pop
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ao executar o &lt;code>git stash&lt;/code>, o Git gera internamente dois objetos de commit especiais e os salva em uma referência chamada &lt;code>refs/stash&lt;/code>. Ou seja, o Stash, afinal de contas, é apenas &amp;ldquo;um commit temporário sem nome&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;h2 id="7-estudo-de-caso-4-o-estado-aterrorizante-de-detached-head">7. Estudo de caso 4: O estado aterrorizante de &amp;ldquo;Detached HEAD&amp;rdquo;
&lt;/h2>&lt;p>&lt;strong>[Situação]&lt;/strong>
Você executou &lt;code>git checkout 9f8a7b6&lt;/code> porque queria verificar o código em um ponto específico do passado. Então, apareceu &lt;code>You are in 'detached HEAD' state.&lt;/code>. Você fez um commit mesmo assim, mas quando mudou de branch, o commit desapareceu!&lt;/p>
&lt;h3 id="o-mecanismo-do-detached-head">O mecanismo do Detached HEAD
&lt;/h3>&lt;p>Normalmente, o &lt;code>HEAD&lt;/code> aponta para uma branch como &lt;code>refs/heads/main&lt;/code>. No entanto, se você fizer o checkout diretamente em um commit específico, o &lt;code>HEAD&lt;/code> passará a apontar diretamente para o objeto Commit. Isso é chamado de &lt;strong>Detached HEAD (HEAD separado)&lt;/strong>.&lt;/p>
&lt;pre class="mermaid">
graph TD
A[&amp;#34;Commit A&amp;#34;] --&amp;gt; B[&amp;#34;Commit B&amp;#34;]
B --&amp;gt; C[&amp;#34;Commit C&amp;#34;]
C --&amp;gt; D[&amp;#34;Commit D&amp;#34;]
BranchMain[&amp;#34;Branch: main&amp;#34;] --&amp;gt; D
HEAD[&amp;#34;HEAD&amp;#34;] --&amp;gt; B
style HEAD fill:#f9f,stroke:#333,stroke-width:4px
&lt;/pre>
&lt;p>Mesmo que você adicione commits neste estado, nenhuma branch rastreará esse novo commit. No instante em que você mudar para outra branch, o novo commit se perderá.&lt;/p>
&lt;h3 id="solução-salvar-como-uma-nova-branch">Solução: Salvar como uma nova branch
&lt;/h3>&lt;p>Pode ser resolvido criando uma nova branch no local onde você está agora.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Crie uma nova branch na posição atual do HEAD e mude para ela&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git checkout -b feature/recovered-work
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h2 id="8-estudo-de-caso-5-resolução-de-conflitos-em-merge-e-rebase">8. Estudo de caso 5: Resolução de conflitos em Merge e Rebase
&lt;/h2>&lt;p>&lt;strong>[Situação]&lt;/strong>
Ao executar &lt;code>git merge&lt;/code> ou &lt;code>git rebase&lt;/code>, foi exibido &lt;code>CONFLICT (content)&lt;/code> e o processo foi interrompido.&lt;/p>
&lt;h3 id="a-diferença-entre-merge-e-rebase">A diferença entre Merge e Rebase
&lt;/h3>&lt;ol>
&lt;li>&lt;strong>Merge&lt;/strong>
Executa um merge de 3 vias (3-way merge) usando os commits mais recentes de duas branches e seu ancestral comum, criando um commit de merge.&lt;/li>
&lt;li>&lt;strong>Rebase&lt;/strong>
Salva temporariamente os commits da branch atual e os reaplica na ponta do alvo. O histórico se torna uma linha reta.&lt;/li>
&lt;/ol>
&lt;pre class="mermaid">
gitGraph
commit id: &amp;#34;M1&amp;#34;
commit id: &amp;#34;M2&amp;#34;
branch feature
checkout feature
commit id: &amp;#34;F1&amp;#34;
commit id: &amp;#34;F2&amp;#34;
checkout main
commit id: &amp;#34;M3&amp;#34;
merge feature
&lt;/pre>
&lt;h3 id="método-para-resolução-de-conflitos">Método para resolução de conflitos
&lt;/h3>&lt;p>Marcadores como os abaixo são inseridos nos arquivos em que ocorreu um conflito.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/span> &lt;span class="nx">HEAD&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">apiUrl&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://api.production.example.com&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">=======&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">apiUrl&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://api.staging.example.com&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="nx">feature&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="k">new&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nx">api&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>O procedimento de resolução é extremamente simples.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Exclua os marcadores e corrija para o código correto.&lt;/strong>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">apiUrl&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">process&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">env&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">NODE_ENV&lt;/span> &lt;span class="o">===&lt;/span> &lt;span class="s1">&amp;#39;production&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">?&lt;/span> &lt;span class="s2">&amp;#34;https://api.production.example.com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;https://api.staging.example.com&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>&lt;strong>Adicione os arquivos resolvidos à área de staging (preparação).&lt;/strong>
&lt;code>git add&lt;/code> tem o papel de &amp;ldquo;informar ao Git que o conflito foi resolvido&amp;rdquo;.
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">$ git add index.js
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;li>&lt;strong>Conclua o processo.&lt;/strong>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># No caso de um merge&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git commit -m &lt;span class="s2">&amp;#34;Resolve merge conflict in index.js&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># No caso de um rebase&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git rebase --continue
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/li>
&lt;/ol>
&lt;p>Se você entrar em pânico, poderá cancelar a qualquer momento com &lt;code>$ git merge --abort&lt;/code> ou &lt;code>$ git rebase --abort&lt;/code>.&lt;/p>
&lt;hr>
&lt;h2 id="9-estudo-de-caso-6-o-histórico-de-commits-está-uma-bagunça-git-rebase--i">9. Estudo de caso 6: O histórico de commits está uma bagunça! &lt;code>git rebase -i&lt;/code>
&lt;/h2>&lt;p>&lt;strong>[Situação]&lt;/strong>
Muitos commits pequenos ocorreram, como &amp;ldquo;Correção de erro de digitação&amp;rdquo;, &amp;ldquo;Correção novamente&amp;rdquo;, &amp;ldquo;Adição de testes&amp;rdquo;. Se você mesclar com &lt;code>main&lt;/code> assim mesmo, o histórico ficará sujo.&lt;/p>
&lt;h3 id="solução-rebase-interativo">Solução: Rebase Interativo
&lt;/h3>&lt;p>Usando &lt;code>git rebase -i&lt;/code> (interactive), você pode alterar a ordem dos commits anteriores, mesclar (squash) vários commits em um só ou corrigir mensagens de commit.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Organize os últimos 3 commits&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git rebase -i HEAD~3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>O editor será aberto e as seguintes informações serão exibidas.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">pick 1a2b3c4 Correção de erro de digitação
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pick 2b3c4d5 Correção novamente
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">pick 3c4d5e6 Adição de testes
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Reescreva isto da seguinte forma.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">pick 1a2b3c4 Implementação do recurso X
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">squash 2b3c4d5 Correção novamente
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">squash 3c4d5e6 Adição de testes
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ao salvar e fechar, esses três commits serão lindamente consolidados em um só.&lt;/p>
&lt;hr>
&lt;h2 id="10-estudo-de-caso-7-não-sei-quando-o-bug-foi-introduzido-git-bisect">10. Estudo de caso 7: Não sei quando o bug foi introduzido! &lt;code>git bisect&lt;/code>
&lt;/h2>&lt;p>&lt;strong>[Situação]&lt;/strong>
Há um bug na branch &lt;code>main&lt;/code> atual, mas estava normal durante a versão lançada um mês atrás. Quero identificar em qual commit o bug foi introduzido, mas há mais de 100 commits e é impossível fazer isso manualmente!&lt;/p>
&lt;h3 id="solução-identificação-de-bugs-usando-busca-binária">Solução: Identificação de bugs usando busca binária
&lt;/h3>&lt;p>O Git possui uma ferramenta embutida para encontrar o commit no qual um bug foi introduzido usando a busca binária matemática (Binary Search). A complexidade computacional é $\mathcal{O}(\log N)$, portanto, mesmo que você tenha 1000 commits, você pode identificá-lo em cerca de 10 testes.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Inicie a busca&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git bisect start
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># O commit atual tem o bug (bad)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git bisect bad
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1 mês atrás (por exemplo, o hash a1b2c3d) estava normal (good)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git bisect good a1b2c3d
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># O Git automaticamente verificará o commit intermediário, então execute os testes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Se o teste for bem-sucedido:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git bisect good
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Se o teste falhar:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ git bisect bad
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Repetindo isso, o Git informará com precisão &amp;ldquo;Este é o primeiro commit Bad&amp;rdquo;. Ao terminar, reverta ao estado original com &lt;code>$ git bisect reset&lt;/code>.&lt;/p>
&lt;hr>
&lt;h2 id="11-a-rede-de-segurança-definitiva-git-reflog">11. A rede de segurança definitiva: &lt;code>git reflog&lt;/code>
&lt;/h2>&lt;p>O trunfo final contra qualquer &amp;ldquo;deslize&amp;rdquo; no Git é o &lt;code>git reflog&lt;/code>. O Git registra todo o histórico de operações locais (histórico de movimentos do HEAD) por um determinado período de tempo. Mesmo que você exclua uma branch ou faça um reset incorreto, você pode recuperar a situação encontrando o hash antigo com &lt;code>git reflog&lt;/code> e executando &lt;code>git reset --hard&lt;/code> para ele.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">$ git reflog
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">9f8a7b6 &lt;span class="o">(&lt;/span>HEAD -&amp;gt; main&lt;span class="o">)&lt;/span> HEAD@&lt;span class="o">{&lt;/span>0&lt;span class="o">}&lt;/span>: commit: Add new feature
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">1a2b3c4 HEAD@&lt;span class="o">{&lt;/span>1&lt;span class="o">}&lt;/span>: reset: moving to HEAD~1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="12-conclusão">12. Conclusão
&lt;/h2>&lt;p>Explicamos detalhadamente os erros comuns de iniciantes no Git, os mecanismos do Git por trás deles e suas soluções. Fazer commit na branch errada, desfazer commits já enviados (pushed), utilizar o Stash, sobreviver ao Detached HEAD e resolver conflitos. O mais importante em tudo isso é imaginar &amp;ldquo;que objetos e ponteiros o Git está manipulando nos bastidores&amp;rdquo;.&lt;/p>
&lt;p>As diferenças dos arquivos são calculadas por algoritmos Diff rigorosos expressos em fórmulas matemáticas, e a consistência histórica é garantida por funções hash criptográficas. Se você entender essa bela filosofia de design, descobrirá que o Git não é de forma alguma uma &amp;ldquo;caixa preta indescritível&amp;rdquo;, mas sim o escudo mais forte para proteger seu código-fonte.&lt;/p>
&lt;p>Na próxima vez que você pensar &amp;ldquo;Fiz besteira!&amp;rdquo;, não se apresse em fechar o terminal; respire fundo e digite &lt;code>git status&lt;/code>. O Git sempre fornecerá dicas de recuperação.&lt;/p></description></item></channel></rss>