# Git: da pedra aos metais — parte 1

Um dos fatores mais importantes para mim ao aprender sobre um novo assunto é estudar a forma como o entendimento sobre ele evoluiu ao longo da história, pois acredito que, ao fazer isso, muito se revela sobre o contexto em que as pessoas passaram a estudá-lo e a utilidade que ele traz para a sociedade.

Nesse sentido, resolvi experimentar uma abordagem nova para mim, que consiste em criar minhas próprias versões de ferramentas de software comumente usadas. Meu intuito com isso não é apenas replicar cada ferramenta em sua "forma final", mas compreender as possíveis escolhas que as levaram a ser como são.

É exatamente esse processo que pretendo relatar na série "Git: da pedra aos metais", que se inicia com esta publicação. Nela, começarei criando a versão mais óbvia que eu conseguir pensar para o versionamento de código e, parte por parte, trarei novas melhorias até atingir um resultado semelhante ao próprio Git.

Ao mesmo tempo em que escrevo cada artigo, planejo realizar a implementação do sistema com a linguagem Rust e disponibilizar o código de cada versão juntamente às publicações. Até o final da série, minha expectativa é que o sistema implemente as funcionalidades a seguir:

* persistência e restauração de versões (commit);
    
* rastreamento de histórico (log);
    
* ramificações do histórico (branching);
    
* staging area (index).
    

Eu não recomendaria esta série para pessoas que nunca tiveram contato com o Git, pois pretendo implementar o sistema já levando em consideração alguns dos conceitos existentes em Git. Por outro lado, caso você já o tenha utilizado e queira aprender ainda mais sobre seu funcionamento, essa é a oportunidade!

## Primeira abordagem: cada versão é uma cópia completa do repositório

Inicialmente, optei por uma abordagem trivial e que, provavelmente, todos já utilizamos para fazer backup de algum projeto: para cada versão que precisamos guardar, todo o conteúdo presente atualmente no diretório de trabalho é copiado para um novo diretório.

Esse trabalho é automatizado por meio da interação com uma interface de linha de comando (CLI), de forma semelhante ao Git, e essa CLI, nomeada genericamente como `vcs`, conta com apenas três comandos: `init`, `commit <descricao>` e `restore <versao>`.

Conforme sugerido pelo nome, a responsabilidade do comando `init` é inicializar um repositório controlado pelo sistema no diretório atual, o que, ao menos por ora, consiste em criar um diretório oculto `.vcs` para abrigar todos os arquivos relacionados ao controle de versão, de forma análoga ao diretório `.git` do Git.

O comando `commit` é responsável por criar o backup do repositório, o que, como discutimos anteriormente, trata-se apenas de copiar todo o conteúdo para um diretório específico dentro de `.vcs`. Nesse caso, o diretório de cada backup recebe como nome um número sequencial, como 1, 2, 3 etc., indicativo de sua versão.

Para facilitar o trabalho de identificar qual é o número associado à versão atual, utilizei um arquivo `version` dentro de `.vcs`, que, a cada execução de `commit`, tem seu conteúdo substituído pelo número da nova versão.

Finalmente, cada diretório de versão abriga um arquivo extra com o nome `README`, cujo conteúdo é uma string informada pelo usuário durante o commit (`commit <descricao>`) para ajudar a identificar as alterações introduzidas por cada um deles.

O último comando, `restore <versao>`, recebe o encargo de restaurar o repositório para o exato estado em que se encontrava na versão informada, o que, na prática, consiste em apagar todo o conteúdo do diretório raiz do repositório, com exceção de `.vcs`, e criar uma cópia de todos os arquivos salvos no backup da versão desejada para o diretório atual, com exceção de `README`.

O conteúdo do diretório `.vcs` se assemelha ao seguinte:

```bash
ls .vcs/
1 2 3 version
```

O conteúdo do diretório de uma versão específica contém uma cópia de todos os arquivos do próprio repositório juntamente a um arquivo `README` com a descrição do commit:

```bash
ls .vcs/3/
README a.txt b.txt
```

Tudo o que fiz até aqui é basicamente o que já fazemos ao copiar backups de um projeto para a nuvem ou para um outro dispositivo de armazenamento local, com a única diferença sendo a automatização desse processo por meio da CLI.

Como já sabemos, essa abordagem é prática, mas carrega consigo alguns problemas. Na próxima parte desta série, vou enumerar e resolver alguns desses problemas para melhorar o sistema. Com isso, encerro a primeira parte por aqui! Até a próxima!

## Repositório

O código-fonte desta primeira versão pode ser consultado no [repositório do GitHub](https://github.com/fernandonagase/rust-vcs/tree/v1.0).

## Atribuições

* Fotografia da capa por [Azzedine Rouichi](https://unsplash.com/pt-br/@rouichi) em [**Unsplash**](https://unsplash.com/pt-br)
