Introdução

editar

Esta wiki procura introduzir alguns conceitos básicos do git e como utilizar algumas de suas funcionalidades. O Git é um sistema de controle de versão desenvolvido por Linus Torvalds para ser utilizado como ferramenta de versionamento do Linux. Ele possui uma série de vantagens, por exemplo:

  • Suporte forte ao desenvolvimento não-linear: facilita a criação de múltiplas linhas de desenvolvimento e a integração entre elas.
  • Desevolvimento distribuído (descentralizado): o Git permite que cada desenvolvedor possua um repositório local para realizar seu trabalho sobre o projeto.
  • Compatível com diversos protocolos de comunicação: HTTP, SSH, FTP, etc.

Gerenciamento de Arquivos

editar

O primeiro passo para utilizar o git é a criação de um repositório no interior do diretório que será versionado, que basicamente cria todo o diretório de trabalho do git (o local que ele utilizará para realizar o versionamento de um conjunto de arquivos), o comando para isso é:

 $ git init

Após a criação do repositório Git, é possível versionar os arquivos à sua escolha que se encontram no diretório submetido à versionamento. O Git considera quatro estados possíveis para um arquivo:

  • Untracked: o arquivo ainda não está sendo monitorado pelo git.
  • Tracked: o arquivo está sendo versionado pelo git.
  • Modified: o arquivo foi modificado desde a última versão registrada pelo git.
  • Staged: o arquivo fará parte do próximo commit.

É possível visualizar o estado atual dos arquivos de um diretório utilizando o comando:

 $ git status

Para selecionar um arquivo para participar do próximo commit e para começar a ser versionado pelo git, basta utilizar o comando:

 $ git add <nome_do_arquivo>

Para registrar uma versão de um arquivo, basta realizar um commit dos arquivos que estão no estado "staged" (já foram adicionados com o comando git add):

 $ git commit

O editor padrão será aberto para que você escreva uma mensagem descrevendo o commit que acabou de ser feito.

Gerenciamento de branches

editar

Um projeto sendo submetido à controle de versão geralmente possuí múltiplas linhas de desenvolvimento, devido à existência de trabalhos paralelos e a criação de versões experimentais do projeto.

O Git facilita a criação de múltiplas linhas de desenvolvimento e o mecanismo básico para isso é a criação de branches. Uma branche é a abstração construída pelo git para representar uma linha de desenvolvimento. Geralmente, várias branches são criadas e cada uma está associada a um trabalho específico que agrega algum valor ao projeto. Em algum momento, quando estes trabalhos forem finalizados e estiverem estáveis, eles devem ser integrados. O git fornece dois mecanismos básicos para a integração de branches: o merge e o rebase. Seguem abaixo alguns comandos do git para utilizar as funcionalidades comentadas neste tópico:

Cria uma nova branch:

 $ git branch <nome_da_branch>

Seleciona uma branch para uso

 $ git checkout <nome_da_branch>

Cria e acessa uma nova branch

 $ git checkout -b <nome_da_branch>

Fornece uma lista de branches e a branch atual (apontada por um asterisco)

$ git branch

Integra a branch especificada com a branch atual

 $ git merge <nome_da_branch>

Integra a branch atual com a branch especificada

 $ git rebase <nome_da_branch>

Merge vs Rebase

editar

Para entender a diferença entre merge e rebase, é necessário compreender as estratégias de integração utilizadas pelo Git. Todas as versões de um projeto formam um grafo, que se ramifica à medida que vão sendo criadas novas linhas de desenvolvimento e que convergem quando uma integração é realizada. Quando uma integração é realizada, o Git seleciona uma de duas abordagens possíveis: Fast-forward e merge recursivo.

 

O Fast-forward é selecionado quando um dos commits é um descendente direto do commit sendo integrado, neste caso, o Git apenas avança a referência de uma das branches para o commit mais atual.

O merge recursivo ocorre quando existe uma divergência entre as linhas de desenvolvimento sendo integradas. Neste caso, o git identifica o primeiro ancestral em comum entre as branches e realiza a integração se baseando neste ancestral compartilhado pelas versões. Durante uma integração baseada na estratégia fast-forward, o resultado de um merge e um rebase são idênticos, porém, se o merge recursivo for selecionado, existem algumas diferenças.

O merge integra a última versão da branch especificada no comando com a última versão da branch atual gerando um novo commit dessa integração. O rebase aplica as versões distintas da branch atual sobre a pilha das versões da branch especificada, neste caso, não há um commit adicional de integração, o que faz aparentar que o histórico foi resultado de um trabalho linear (sequencial), ao invés de paralelo, como de fato ocorreu. O rebase fornece um histórico mais "limpo" do que o merge.

Conflitos

editar

Durante a integração de linhas de desenvolvimentos distintas, é possível que alguns conflitos ocorram. Um conflito é uma situação em que duas versões distintas do projeto alteraram exatamente os mesmos trechos de um arquivo. Neste caso, não há como o git inferir qual versão deve ser selecionada e o desenvolvedor terá que analisar o arquivo manualmente para resolver o conflito.

O processo é bastante simples, basta que o desenvolvedor identifique quais arquivos possuem conflitos utilizando o comando git status. Uma mensagem será exibida indicando que um arquivo possui conflitos ("Both modified", ambas as versões modificaram o arquivo). Após a identificação, o desenvolvedor precisa abrir o arquivo e analisá-lo, o git terá inserido no arquivo as duas versões que conflitaram e o desenvolvedor terá que selecionar as partes que fizerem sentido de acordo com o contexto da situação.

Gerenciamento de repositórios remotos

editar

O git possui repositórios remotos e locais, os repositórios locais estão localizados nos computadores dos desenvolvedores e os repositórios remotos são hospedados por serviços de repositório como GitLab e o GitHub. É possível adicionar um repositório remoto e nomeá-lo com o seguinte comando:

$ git remote add <nome_do_repositório_remoto> <url_do_repositório_remoto>

Para baixar um repositório remoto para sua máquina local, é possível usar o seguinte comando:

$ git clone <url_do_repositório_remoto>

Para listar os repositórios remotos já adicionados, utilize o seguinte comando:

$ git remote -v

O git mantêm branches locais que mantêm versões locais de uma determinada branch, por exemplo: master e branches remotas que espelham as branches hospedadas no repositório remoto, por exemplo: origin/master. Para atualizar as branches que espelham o repositório remoto, basta utilizar o comando:

$ git fetch <repositório_remoto>

Após a atualização das branches remotas, basta integrá-las às branches locais correspondentes (utilizando merge ou rebase) para que você possa trabalhar sobre a última versão do projeto mantida no repositório remoto. Existe um comando que automatiza este processo:

$ git pull <repositório_remoto> <branch>

O git pull atualiza as branches remotas com a última versão mantida no repositório remoto e as integra automaticamente às branches locais. Ele utiliza por padrão o merge para realizar a integração, mas é possível utilizar o rebase passando uma flag como parâmetro para o comando:

$ git pull --rebase <repositório_remoto> <branch>

Para atualizar o repositório remoto com a versão contida no seu repositório local, basta utilizar o comando git push para realizar o upload da sua versão para o remoto:

$ git push <repositório_remoto> <branch>

Em casos que o desenvolvedor não é um contribuidor oficial do projeto e queira contribuir de forma colaborativa é necessário realizar um fork que funciona como uma cópia do repositório. No fork, é criado um repositório espelho do repositório original (upstream) e um repositório local para que seja possível o desenvolvimento de forma que os repositórios mantenham um relacionamento.

 

Para realizar um fork no GitLab, basta estar logado em seu usuário, entrar na página do projeto desejado e apertar o botão circulado em vermelho na imagem abaixo.

 

Merge request

editar

Após realizar o fork e alterações no projeto, para que essas alterações possam ser integradas no upstream é necessário realizar um merge request, ou seja, um pedido de contribuição para algum mantenedor do projeto original. Assim que o mantenedor receber o merge request, ele irá analisar as suas alterações e possivelmente integra-las ao projeto. Para realizar um merge request no GitLab, basta estar logado em seu usuário, apertar o botão circulado em vermelho na imagem abaixo e preencher as informações requeridas.