Entenda conceitos básicos sobre Git
Tags: git, beginners, programming, versioncontrol
Published: 2021-12-07 01:22:37

Cada vez mais as empresas investem em projetos de tecnologias para facilitar negócios, automatizar tarefas, difundir informações entre vários outros propósitos. Geralmente uma das primeiras etapas de desenvolvimento de projetos é definir como você irá controlar e manter as alterações que irão ocorrer ao longo do desenvolvimento. Existem algumas ferramentas de mercado com esta finalidade.

Neste artigo você irá aprender conceitos básicos sobre Git, uma ótima opção para este propósito. Entre os controles de versões disponíveis no mercado, o Git é o mais utilizado, principalmente em projetos _open source_. Esta ferramenta armazena todas as alterações ocorridas nos arquivos do seu projeto permitindo regressões para um estado anterior. Além disso, permite que várias pessoas trabalhem simultaneamente no mesmo projeto e até nos mesmos arquivos.

## CVCS x  DVCS 
Existem diversos sistemas de controle de versão no mercado. Há sistemas de controle de versão centralizado, o CVCS (_Centralized Version Control System_), como Subversion (SVN), CVS e Perforce. E há sistemas de controle de versão distribuído, o DVCS (_Distributed Version Control System_), como Git, Mercurial e Bazaar.

![CVCSxDVCS](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bvz23dv9rp92a7cw05vk.png)

O CVCS possui um repositório central do projeto, geralmente localizado em um servidor, que contém todo o histórico do projeto. Qualquer membro do projeto que desejar colaborar, precisará fazer um _checkout_ de uma versão do projeto. Essa operação irá baixar uma cópia da versão selecionada para a máquina do contribuidor, porém nesta máquina não existirá o histórico do projeto. O histórico só existe no repositório central e por isso, vários comandos são executados remotamente, o que gera uma dependência de conexão à internet e explica o motivo da maioria dos comandos serem mais lentos, dado que existe o overhead da rede.

O DVCS por outro lado não depende necessariamente de um repositório central. Isso porque os contribuidores podem clonar repositórios existentes ou criar seus próprios repositórios locais. Esse processo de clonagem baixa todo o conteúdo remoto e também o histórico completo do projeto. Por isso, a maioria das operações podem ocorrer localmente, sem depender de conexão com internet, o que resulta em uma velocidade maior comparado aos CVCSs. Pelo histórico estar distribuído, há uma quantidade maior de backups comparado a um CVCS, já que nesse, o histórico só existe no repositório central. Se o repositório central estiver localizado em um servidor interno vulnerável, isso poderia comprometer todo o histórico do projeto. 

## Local x remoto
No Git é possível criar o próprio repositório através do comando `git init`, que irá criar o diretório oculto ".git". Porém, é importante que esse repositório esteja armazenado remotamente, isso porque tal opção pode servir como backup do repositório. Para armazenamento remoto você pode considerar as plataformas de hospedagem para repositórios Git, como Bitbucket, GitLab e GitHub ou até mesmo um servidor próprio. Caso ocorra um problema irreparável em seu computador, você estará seguro pois o repositório também existe na opção que você está utilizando.

Além disso, é interessante que o projeto esteja disponível remotamente para possibilitar o trabalho colaborativo. Outras pessoas podem baixar uma cópia do repositório (_clone_), realizar modificações e enviar (_push_) tais alterações novamente para o repositório remoto. Quando for necessário atualizar o repositório porque outro contribuidor submeteu novas versões, basta atualizar o repositório local puxando as modificações envolvidas (_pull_).

## As três áreas 
O Git possui 3 áreas principais: a área de trabalho, a área de preparo e o repositório.


![As três áreas](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a7nht8x7u0z69utwd96j.png)

A área de trabalho (_Working Directory_) é o _checkout_ de uma versão do projeto. Corresponde aos arquivos e diretórios visíveis e alteráveis. 

Ao realizar qualquer alteração, seja mudança em arquivos existentes, como inclusão de novos arquivos, antes de gerar uma nova versão, você primeiramente deve adicionar tais alterações para a área de preparo (_Staging Area_). 

Por fim, você poderá executar um _commit_, que irá considerar todas as alterações que estiverem na área de preparo. Isso irá produzir uma nova versão no histórico do projeto.

## Commits
O histórico de versões no Git é formado por objetos de _commit_. Esse histórico é baseado em uma estrutura denominada DAG (_Directed Acyclic Graph_). Um _commit_ é uma imagem do atual estado do seu repositório. Ou seja, é uma "foto" de como está cada arquivo em um determinado momento. É possível retornar para qualquer _commit_ feito no passado.

O _commit_ está associado a uma _hash_ SHA-1, tal _hash_ possui metadados como autor, data de criação, mensagem e _commit_ pai. Todos esses metadados mais o conteúdo do arquivo formam o SHA-1 do _commit_, que é imutável. Ou seja, não pode ser alterado. Por isso, qualquer comando utilizado com o propósito de alterar algo relacionado ao commit, irá resultar em um novo SHA-1.

## _Branches_
Em teoria, uma _branch_ é uma ramificação de um projeto. Na prática, no Git, uma _branch_ é uma referência para um _commit_. A _branch_ principal de um projeto chama-se “_master_”. Porém, há iniciativas para alterar este nome a longo prazo, devido ao termo “_master_” ser considerado racista.

Há vários benefícios na utilização de _branches_ como:
- Rápido e fácil de ser criada: 1 arquivo que contém uma referência
- Permitem a experimentação: Os membros da equipe podem isolar seu trabalho para que ele não afete os outros até que o trabalho esteja pronto
- Suporte a várias versões: As ramificações permitem suporte a várias versões do projeto simultaneamente
- Permitem processos de revisão de arquivo: As ramificações permitem incluir processos de revisão de arquivos

Considere a imagem abaixo como um exemplo de um repositório com mais de uma ramificação


![Repositório com mais de uma branch](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qfrzm1wavf2o8q85ibvs.png)

Na imagem acima, uma ramificação do projeto é criado a partir da versão "_first commit_". Nesse instante, cada ramo terá seus próprios _commits_ enquanto não houver algum mecanismo de fusão entre os ramos. Os principais mecanismos de fusão são: _merge_ ou _rebase_.

## A referência HEAD
A HEAD é uma referência que normalmente vai apontar para a _branch_ corrente. Já uma _branch_, como visto anteriormente, é uma referência para um _commit_. Este _commit_ por sua vez, será a última versão de tal ramificação. Para um melhor entendimento, considere a sequência a seguir. 

Inicialmente existe somente uma _branch_ chamada _master_ que aponta para o _commit_ "_first commit_". Também existe uma referência chamada HEAD que aponta para a _branch master_, ou seja, indiretamente aponta para o _commit "first commit"_. Aqui existe uma referência simbólica, que ocorre quando uma referência aponta para outra referência.

![Referência Head etapa 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a11br4oplwvpufahqqx9.png)

É criado uma nova _branch_ chamada xpto a partir do _commit "first commit"_. 

![Referência Head etapa 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5bt823nwdcfryu903quw.png)

Ao realizar _checkout_ na nova _branch_, o Git altera a referência HEAD para apontar para a _branch_ xpto. Isso significa que qualquer novo _commit_ será aplicado na ponta dessa nova _branch_. Veja o resultado de um _commit "creating service"_ na _branch_ xpto.

![Referência Head etapa 3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9wtyy2nc8gzhlbwgdh3r.png)

Observe que se outro _commit_ for realizado, o rótulo da _branch_ xpto irá referenciar o novo _commit_. Para a referência HEAD não há mudanças, ela permanecerá apontando para a _branch_ corrente.

![Referência Head etapa 4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a25z2bje9jr4ceeun9gw.png)

Agora para gerar novos _commits_ na _branch_ principal, basta realizar primeiramente um _checkout_ na _branch_ _master_.

![Referência Head etapa 5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d42z1cf3aqdq7q96n93r.png)

Pronto, agora qualquer novo _commit_ será aplicado na _branch_ _master_. Veja o resultado de um _commit "hotfix"_ nesta situação.

![Referência Head etapa 6](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y9to2k6w280rg0ymupd1.png)

## _Tags_
Geralmente nos sistemas de controle de versão existe um recurso chamado _tags_ e com o Git não é uma exceção. As _tags_ são utilizadas para demarcar marcos importantes, tais marcos estão associados a um _commit_ específico. Geralmente, as pessoas utilizam esta funcionalidade para liberações de release em produção. Por exemplo, é possível marcar _commits_ com rótulos 1.0, 1.1, 1.2, 2.0 e assim por diante.

Além de trazer mais organização para o histórico, as _tags_ também são referências e podem ser usadas com qualquer comando que utiliza referências como entrada. Vale destacar que diferentemente de _branches_, que são referências mutáveis pois mudam conforme cada nova versão, as _tags_ são referências imutáveis, uma vez criadas associadas a um _commit_ elas não irão mudar.

## Conclusão
Como vimos, o Git é um sistema de controle de versão distribuído que possui diversos recursos para auxiliar na gestão de alterações. É uma ferramenta muito utilizada principalmente no contexto de software e que também permite que um grupo de pessoas possa trabalhar de forma colaborativa no mesmo projeto, editando e criando novos arquivos.

Quer aprender mais sobre esta ferramenta essencial para desenvolvedores de software? Aprenda no mais novo curso de [Git - Básico ao avançado] (https://www.udemy.com/course/git-basico-ao-avancado-2021/?referralCode=D1231C6B99B30C6EDF14)