Entenda a simplificação do histórico do Git

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

A simplificação do histórico do Git pode ser uma confusão. 99% das vezes você nem saberá que ele existe, mas ocasionalmente ele pode sair do Git e pegar você. Neste artigo, analisaremos o que é a simplificação de histórico e como ela pode causar confusão ao examinar o histórico de arquivos.

Vamos começar com um cenário comum:

  1. Você envia por push uma alteração para um arquivo e, em seguida, mescla a alteração no principal.
  2. Alguns de seus colegas também mesclam seus branches para principal.
  3. Você volta algum tempo depois e percebe que suas alterações estão faltando.
  4. Em busca do culpado, você olha o histórico do arquivo e observa... suas alterações nem estão listadas!?

O histórico de commit do Git é uma árvore. Às vezes, o histórico cronológico não é o mesmo que o histórico de árvore de arquivo real. Essa situação ocorre com mais frequência quando um commit de mesclagem reverte um arquivo para seu estado original. Nesse caso, a exibição de histórico padrão não mostra todas as alterações, pois tecnicamente o arquivo não foi alterado. Nesse cenário, o Git percebe que pode simplificar o histórico e as "alterações", que você provavelmente está procurando, são removidas do log.

A menos que você tenha enfrentado isso antes, pode ficar frustrado, imaginando para onde foram minhas alterações?

Simplificação do histórico: ativado por padrão

Por padrão, a execução do comando de log em um arquivo: git log file.txt simplifica automaticamente o histórico, possivelmente ocultando alguns commits de sua saída. Para obter mais informações, consulte a página do git log man.

A confusão fica maior quando a simplificação do histórico não acontece se você apenas executar git log, porque está examinando todas as alterações e não há nada a simplificar.

Para desativar a simplificação do histórico, você precisa usar a opção de --full-history alternar linha de comando .

Um exemplo de simplificação de histórico

Para entender melhor como funciona a simplificação, criamos nosso próprio exemplo. Primeiro, vamos examinar um diagrama do histórico que criamos:

Branches do Git

Como você pode ver, vamos:

  1. Crie um arquivo.
  2. Adicionar uma linha a esse arquivo em um branch (animais).
  3. Adicionar uma linha diferente a esse arquivo em outro branch (fruta).
  4. Mesclar animais de ramificação novamente no principal.
  5. Mesclar a fruta de branch novamente no principal e escolher a cópia inteira do arquivo do branch de frutas.
  6. Exiba o histórico do arquivo.

O Git simplifica o histórico para nós. A etapa 5 é a principal. Ignoramos todas as alterações do ramo animal. O Git observa que nosso arquivo essencialmente não foi alterado entre as etapas 1 e 5 e, portanto, só nos mostra duas entradas de histórico.

Primeiro, criamos o arquivo e o adicionamos ao nosso repositório:

> cd sample
> git init
> echo "some content" > test.txt
> git add test.txt
> git commit -m "Initial commit"

Agora decidimos acrescentar o texto "macacos" ao arquivo em um branch animal:

> git checkout -b animals
> echo "donkeys" >> test.txt
> git commit -am "We have added an animal"

Enquanto experimentamos, decidimos que talvez queiramos usar frutas em nosso arquivo, portanto, criamos um branch diferente e acrescentamos o texto "bananas" no final do arquivo:

> git checkout main -b fruit
> echo "bananas" >> test.txt
> git commit -am "We have added a fruit"

Satisfeitos com nossas mudanças, decidimos mesclar nossa branch animal de volta no principal:

> git checkout main
> git merge animals

Agora, vamos examinar o log do nosso arquivo test.txt:

> git log test.txt
    
    commit 6b33d99b996c430a60c9552b79245d1aa8320339
        Date:   Mon Feb 15 10:45:33 2016 -0500

        We have added an animal

    commit 206613ccd9a54b055b184c7b6c16f2ece8067e51
        Date:   Mon Feb 15 10:44:18 2016 -0500

        Initial commit

Até agora tudo bem, certo? Nada parece fora do comum em nosso registro de log. Agora vamos dizer que mudamos de ideia e decidimos mesclar nosso branch de frutas:

>git merge fruit
    
    Auto-merging test.txt
    CONFLICT (content): Merge conflict in test.txt
    Automatic merge failed; fix conflicts and then commit the result.

Uau, um conflito de mesclagem. Após pensar um pouco, decidimos usar todo test.txt o arquivo de nossa branch de frutas. Normalmente, você usaria algum tipo de editor de texto ou ferramenta de mesclagem, mas recriaremos todo o arquivo, já que são apenas duas linhas:

> echo "some content" > test.txt
> echo "bananas" >> test.txt
> git commit -am "Fixed merge conflict"

Agora vamos dar uma olhada no histórico do nosso arquivo test.txt:

> git log test.txt
    
    commit fdd4dfd816c4efebc5bdb240f49e934e299db581
        Date:   Mon Feb 15 10:51:06 2016 -0500

        We have added a fruit

    commit 206613ccd9a54b055b184c7b6c16f2ece8067e51
        Date:   Mon Feb 15 10:44:18 2016 -0500

        Initial commit

Com certeza, não detectamos nenhuma alteração do nosso primeiro experimento no log, nem vemos nossa mesclagem! Ainda estão lá? O Git eliminou totalmente as alterações?

> git log --full-history test.txt

Como é possível ver, embora tenha simplificado o log sem o sinalizador full-history, o Git manteve todas as nossas alterações:

> commit 5d0bb77a24e265dc154654fb3b5be331b53bf977
    Merge: 6b33d99 fdd4dfd
        Date:   Mon Feb 15 10:59:34 2016 -0500

        Fixed merge conflict

    commit fdd4dfd816c4efebc5bdb240f49e934e299db581
        Date:   Mon Feb 15 10:51:06 2016 -0500

        We have added a fruit

    commit 6b33d99b996c430a60c9552b79245d1aa8320339
        Date:   Mon Feb 15 10:45:33 2016 -0500

        We have added an animal

    commit 206613ccd9a54b055b184c7b6c16f2ece8067e51
        Date:   Mon Feb 15 10:44:18 2016 -0500

        Initial commit

Resumo de simplificação do histórico do Git

A questão sobre a simplificação da história é que na maioria das vezes você nunca vai perceber. Mas quando um conflito de mesclagem não dá certo e você quer saber o que aconteceu, você pode olhar para o histórico de logs do git e se questionar para onde foram suas alterações.

Agora, em vez de entrar em pânico, você sabe que:

  • A simplificação do histórico para arquivos é ativada por padrão
  • O sinalizador --full-history fornecerá um histórico de arquivos mais abrangente

Atualização: desde que escrevi este artigo, Azure DevOps Services introduziu várias opções incríveis de visualização de histórico na Web. Assim, se você não quiser fazer logon pela linha de comando, pode simplesmente efetuar pull do arquivo para que deseja exibir o histórico em nosso explorer e o filtro de histórico abaixo está presente, no qual você pode especificar exibições de histórico simples ou não simples:

Filtros de Git

(c) 2016 Microsoft Corporation. Todos os direitos reservados. Este documento é fornecido como foi escrito. As informações e opiniões apresentadas neste documento, incluindo URLs e outras referências a sites da Web, podem ser alteradas sem aviso prévio. Você assume o risco de usá-las.

Este documento não fornece direitos legais e nenhuma propriedade intelectual sobre qualquer produto da Microsoft. Você pode copiar e usar este documento para fins de referência interna.