GIT por dentro: introdução (tradução)

Olá Habr! Apresento a você a tradução do artigo "Git for Computer Scientists", de Tommi Virtanen.


GIT Inside Out: Uma Introdução


De mim mesmo: li periodicamente artigos sobre como várias tecnologias populares são organizadas sob o capô, me deparei com esse material . O artigo parecia interessante pela presença de esquemas simples e compreensíveis, percebidos muito melhor do que as folhas de um texto sem graça. Eu decidi traduzir para o russo. Imagens tiradas do original.


Quem estará interessado e possivelmente será útil: pessoas que trabalham com Git todos os dias (ou seja, a cada segundo, se não o primeiro desenvolvedor de software) e que desejam entender melhor o mecanismo de seu trabalho.


Nota: para uma melhor compreensão do artigo, deve-se ter uma idéia de uma fera como um gráfico acíclico direcionado (DAG) .


Armazenamento de objetos


O repositório de objetos Git é, grosso modo, um DAG contendo vários tipos de objetos. Os objetos são armazenados na forma compactada e identificados pelos hashes SHA-1 (NÃO é um hash do conteúdo do arquivo que representa o objeto, mas de sua apresentação no Git).


Blob


imagem


Blob é um objeto simples, apenas uma coleção de bytes. Pode ser um arquivo, um link simbólico ou qualquer outra coisa. A semântica é determinada pelo objeto que aponta para esse blob.


Árvore


imagem


Objetos do tipo "árvore" descrevem diretórios (diretórios). Eles podem apontar para blobs que armazenam o conteúdo dos arquivos, bem como para outras árvores, criando assim uma estrutura de subdiretório.


Se um nó aponta para outro nó no DAG, eles dizem que depende desse nó, ou seja, não pode existir sem ele. Os nós apontados ao nó podem ser excluídos usando a coleta de lixo (comando git gc ) ou restaurados usando o comando git fsck --lost-found .


Confirmar


imagem


A confirmação refere-se a uma árvore que representa o estado dos arquivos no Git no momento em que a confirmação foi criada. Além disso, commit pode se referir a outros commits que são seus pais:


  • Se a confirmação tiver mais de 1 pai, isso significa que descreve a operação de mesclagem (mesclagem)
  • Se o commit não tiver pais, esse é o chamado commit inicial (inicial) (ou seja, o primeiro no repositório)
  • Também pode haver casos em que há mais de 1 confirmação inicial no repositório - isso geralmente significa mesclar dois repositórios separados

O corpo do objeto de confirmação é a mensagem de confirmação .


Refs (links)


imagem


Os links (ou títulos ou ramificações) são semelhantes aos adesivos com notas coladas nos nós do DAG, algum tipo de nota ou marcador - "Eu trabalho aqui". Diferentemente dos nós do DAG, que não podem ser alterados e só podem ser adicionados, os links podem ser movidos como você desejar. Eles não são armazenados no histórico e não são transferidos diretamente entre repositórios.


O comando git commit adiciona um novo nó ao DAG e move um marcador para ele para a ramificação atual.


Os links estão no espaço de nomes heads / branchname , mas parte dos heads pode ser omitida.


O link HEAD se destaca - não aponta para um nó, mas para outro link - este é um ponteiro para o ramo ativo atual.


Refs remotas


imagem


São, grosso modo, adesivos de uma cor diferente. A diferença é que os links remotos estão em um espaço para nome diferente e também são gerenciados por um servidor remoto. Para atualizá-los, use o comando git fetch .


Tag



Uma tag é uma combinação de um nó DAG e um adesivo (outra cor). A tag aponta para confirmação e inclui uma mensagem opcional e assinatura GPG. Um adesivo (link) é uma maneira simples de acessar o tag e, em caso de perda, pode ser restaurado com o comando git fsck --lost-found .


Assim, um repositório Git é uma combinação de DAG e links.


A história


Agora, sabendo como o Git armazena o histórico de versões, vamos tentar descrever várias operações, bem como entender como o Git difere dos sistemas que representam o histórico como mudanças lineares para cada ramificação.


imagem


O repositório mais simples. Nós apenas copiamos ( git clone ) o repositório remoto com um único commit.


imagem


Aqui lemos ( git fetch ) o repositório remoto e obtivemos 1 novo commit, mas ainda não o mesclamos com nosso ramo.


imagem


Aqui está o que acontece depois de executar o comando git merge remotes / MYSERVER / master . Como a mesclagem foi realizada com avanço rápido (não houve confirmações locais em nossa filial local), aconteceu o seguinte: os arquivos da nossa cópia de trabalho foram alterados e o ponteiro para a ramificação também foi movido.


imagem


Execute o git commit localmente e, em seguida, git fetch . Agora temos confirmação local e remota. Obviamente, você precisa de uma mesclagem .


imagem


Este é o resultado do comando git merge remotes / MYSERVER / master . Como tivemos uma consolidação local, isso não é rápido e uma consolidação separada é criada para a mesclagem no DAG. Aviso - ele tem 2 pais confirmados.


imagem


É assim que nossa árvore cuidará de vários commit-s, nos dois ramos (local e remoto) + mesclagem. Você pode ver claramente como o Git DAG captura todo o histórico de nossas ações.


imagem


No entanto, é difícil ler essa história. Se você ainda não publicou sua filial, ou concordou com outros membros da equipe que eles não devem desenvolver isso em seu trabalho, você tem uma alternativa: você pode fazer uma nova recuperação para sua filial. Nesse caso, seu commit é substituído por outro commit, com um pai diferente, para o qual o link para o branch também se move.


Nesse caso, seus commit-s antigos permanecerão no DAG até a coleta de lixo. Em princípio, este é um tipo de seguro, caso algo dê errado. Se você ainda tiver links para confirmação antiga, eles serão salvos enquanto os links existirem.


Você NÃO deve fazer uma nova reformulação para ramificações nas quais outras pessoas criaram commit. Você pode restaurá-los (e nem mesmo muito difícil), mas isso adiciona confusão e muito trabalho inútil.


imagem


Aqui está como ele cuida da coleta de lixo (ou ignora as confirmações inacessíveis) e cria uma nova confirmação na parte superior da ramificação à qual a rebase foi aplicada.


imagem


Além disso, com o rebase, você pode mover vários commit s ao mesmo tempo.


Só isso. Espero que o material seja útil.

Source: https://habr.com/ru/post/pt468205/


All Articles