Git

Git LFS

Git LFS
Git se tornou o sistema de controle de versão de fato para desenvolvedores de software em todo o mundo. Este sistema de controle de versão distribuído de código aberto é mais rápido do que seus concorrentes. É fácil de usar para ramificar e mesclar código. No entanto, ele tem um problema de desempenho com grandes arquivos binários. Git Large File Storage (LFS) foi desenvolvido para resolver este problema.

O problema de arquivos grandes no Git

Tradicionalmente, certas empresas e instituições se afastaram do Git devido à ineficiência no manuseio de grandes arquivos binários. Os desenvolvedores de videogames e empresas de mídia precisam lidar com texturas complexas, vídeos full-motion e arquivos de áudio de alta qualidade. Os institutos de pesquisa precisam acompanhar grandes conjuntos de dados que podem ser gigabytes ou terabytes. Git tem dificuldade em manter esses arquivos grandes.

Para entender o problema, precisamos dar uma olhada em como o Git rastreia os arquivos. Sempre que há um commit, Git cria um nó de objeto com um ponteiro para seu pai ou vários pais. O modelo de dados Git é conhecido como o gráfico acíclico direcionado (DAG). O modelo DAG garante que o relacionamento pai-filho nunca possa formar nenhum ciclo.

Podemos inspecionar o funcionamento interno do modelo DAG. Aqui está um exemplo de três commits em um repositório:

$ git log --oneline
2beb263 Commit C: adicionada imagem 1.JPEG
866178e Compromisso B: adicionar b.TXT
d48dd8b Commit A: adicione um.TXT

No Commit A e B, adicionamos o arquivo de texto a.txt e b.TXT. Em seguida, no Commit C, adicionamos um arquivo de imagem chamado image1.JPEG. Podemos visualizar o DAG da seguinte forma:

Commit C Commit B Commit A
2beb263 -> 866178e -> d48dd8b

Se inspecionarmos o último commit com o seguinte comando:

$ git cat-file -p 2beb263
árvore 7cc17ba5b041fb227b9ab5534d81 relevant36183a4e3
pai 866178e37df64d9f19fa77c00d5ba9d3d4fc68f5
autor Zak H 1513259427 -0800
committer Zak H 1513259427 -0800
Commit C: imagem adicionada 1.JPEG

Podemos ver que o Commit C (2beb263) tem o Commit B (866178e) como pai. Agora, se inspecionarmos o objeto de árvore do Commit C (7cc17ba), podemos ver os blobs (objetos binários grandes):

$ git cat-file -p 7cc17ba
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 a.TXT
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 b.TXT
100644 blob a44a66f9e06a8faf324d3ff3e11c9fa6966bfb56 image1.JPEG

Podemos verificar o tamanho do blob da imagem:

$ git cat-file -s a44a66f9e
871680

Git está acompanhando as mudanças nesta estrutura de árvore. Vamos fazer uma modificação na imagem1.jpeg e verifique o histórico:

$ git log --oneline
2e257db Commit D: imagem modificada 1.JPEG
2beb263 Commit C: adicionada imagem 1.JPEG
866178e Compromisso B: adicionar b.TXT
d48dd8b Commit A: adicione um.TXT

Se verificarmos o objeto Commit D (2e257db):

$ git cat-file -p 2e257db
árvore 2405fad67610acf0f57b87af36f535c1f4f9ed0d
pai 2beb263523725e1e8f9d96083140a4a5cd30b651
autor Zak H 1513272250 -0800
committer Zak H 1513272250 -0800
Commit D: imagem modificada 1.JPEG

E a árvore (2405fad) dentro dela:

$ git cat-file -p 2405fad
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 a.TXT
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 b.TXT
100644 blob cb4a0b67280a92412a81c60df36a15150e713095 image1.JPEG

Observe que o hash SHA-1 para a imagem1.jpeg mudou. Significa que criou um novo blob para a imagem1.JPEG. Podemos verificar o tamanho do novo blob:

$ git cat-file -s cb4a0b6
1063696

Esta é uma maneira de visualizar a estrutura do DAG acima:

Commit D Commit C Commit B Commit A
| | | |
2e257db -> 2beb263 -> 866178e -> d48dd8b
| | | |
Tree4 Tree3 Tree2 Tree1
| | | |
Blobs Blobs Blobs Blobs

Cada objeto commit mantém sua própria árvore. Blobs são mantidos dentro dessa árvore. Git otimiza o espaço certificando-se de que armazena apenas as diferenças e usa compressão para armazenamento. Mas, para mudanças em arquivos binários, o Git precisa armazenar arquivos inteiros nos blobs porque é difícil determinar as diferenças. Além disso, os arquivos de imagem, vídeo e áudio já estão compactados. Como resultado, para cada instância de um arquivo binário modificado, a árvore termina com um grande blob.

Vamos pensar em um exemplo em que fazemos várias alterações em um arquivo de imagem de 100 MB.

Commit C -> Commit B -> Commit A
| | |
Tree3 Tree2 Tree1
| | |
Blob3 Blob2 Blob1
300 MB 200 MB 100 MB

Cada vez que mudamos o arquivo, o Git precisa criar um blob de 100 MB. Portanto, somente após 3 confirmações, o repositório Git tem 300 MB. Você pode ver que o tamanho do repositório Git pode explodir rapidamente. Como o Git é um controle de versão distribuído, você vai baixar todo o repositório para sua instância local e trabalhar muito com branches. Portanto, os grandes blobs se tornam um gargalo de desempenho.

O Git LFS resolve o problema substituindo os blobs por arquivos de apontadores leves (PF) e criando um mecanismo para armazenar os blobs em outro lugar.

Commit C -> Commit B -> Commit A
| | |
Tree3 Tree2 Tree1
| | |
PF3 PF2 PF1

Localmente, o Git armazena os blobs no cache Git LFS e remotamente os armazenará na loja Git LFS no GitHub ou BitBucket.

PF1 -> Blob1
PF2 -> Blob2
PF3 -> Blob3

Agora, quando você estiver lidando com o repositório Git, os arquivos PF leves serão usados ​​para as operações de rotina. Os blobs serão recuperados apenas quando necessário. Por exemplo, se você verificar o Commit C, o Git LFS irá procurar o ponteiro PF3 e baixar o Blob3. Portanto, o repositório de trabalho será mais enxuto e o desempenho será melhor. Você não precisa se preocupar com os arquivos de ponteiro. Git LFS irá gerenciá-los nos bastidores.

Instalando e executando o Git LFS

Houve tentativas anteriores de resolver o problema de arquivos grandes do Git. Mas o Git LFS teve sucesso porque é fácil de usar. Você apenas tem que instalar o LFS e dizer a ele quais arquivos rastrear.

Você pode instalar o Git LFS usando os seguintes comandos:

$ sudo apt-get install software-properties-common
$ curl -s https: // packagecloud.io / install / repositories / github / git-lfs / script.deb.sh | sudo bash
$ sudo apt-get install git-lfs
$ git lfs install

Depois de instalar o Git LFS, você pode rastrear os arquivos que deseja:

$ git lfs track "*.jpeg "
Monitorando "*.jpeg "

A saída mostra que o Git LFS está rastreando os arquivos JPEG. Quando você começar a monitorar com o LFS, você encontrará um .arquivo gitattributes que terá uma entrada mostrando os arquivos rastreados. O .O arquivo gitattributes usa a mesma notação que .arquivo gitignore. Aqui está como o conteúdo de .gitattributes parece:

$ cat .gitattributes
*.filtro jpeg = lfs diff = lfs merge = lfs -texto

Você também pode descobrir quais arquivos são rastreados usando o seguinte comando:

trilha $ git lfs
Listando padrões rastreados
*.jpeg (.gitattributes)

Se quiser parar de rastrear um arquivo, você pode usar o seguinte comando:

$ git lfs untrack "*.jpeg "
Desvendando "*.jpeg "

Para operações gerais do Git, você não precisa se preocupar com o LFS. Ele cuidará de todas as tarefas de backend automaticamente. Depois de configurar o Git LFS, você pode trabalhar no repositório como qualquer outro projeto.


Um estudo mais aprofundado

Para tópicos mais avançados, examine os seguintes recursos:

  • Movendo repositório Git LFS entre hosts
  • Excluindo arquivos Git LFS locais
  • Removendo arquivos Git LFS remotos do servidor
  • Site Git LFS
  • Documentação Git LFS

Referências:

  • git-lfs.github.com: repositório GitHub
  • github.com / git-lfs / git-lfs / tree / master / docs: Documentação GitHub para Git LFS
  • atlassiano.com / git / tutorials / git-lfs: Atlassian Tutorials
  • YouTube.com: O que é Git LFS
  • YouTube.com: Rastreando arquivos enormes com Git LFS por Tim Pettersen, Atlassian
  • YouTube.com: Gerenciando arquivos enormes no armazenamento certo com Git LFS, YouTube
  • YouTube.com: Git Large File Storage - Como trabalhar com Big Files, YouTube
  • Askubuntu.com / questions / 799341: how-to-install-git-lfs-on-ubuntu-16-04
  • github.com / git-lfs / git-lfs / blob / master / INSTALANDO.md: Guia de instalação
Como baixar e jogar Sid Meier's Civilization VI no Linux
Introdução ao jogo Civilization 6 é uma versão moderna do conceito clássico introduzido na série de jogos Age of Empires. A ideia era bastante simples...
Como instalar e jogar Doom no Linux
Introdução ao Doom A série Doom teve origem nos anos 90 após o lançamento do Doom original. Foi um sucesso instantâneo e, a partir desse momento, a sé...
Vulkan para usuários de Linux
A cada nova geração de placas gráficas, vemos os desenvolvedores de jogos ultrapassarem os limites da fidelidade gráfica e se aproximarem mais do foto...