DEV Community

Alex Barros
Alex Barros

Posted on

O que o tio Lex (acha que) entende de GIT

Menuzinho xavoso

Um pouco sobre git, github e afins

O git é um excelente sistema de controle de versão (se não acredita, tente usar o SVN ou até mesmo o CVS, que foi quem deu origem ao git devido o ódio que o Torvalds sentiu dele e isso motivou a criação do git rsrsrsrs).

Utilizamos o git para controlar versões diferentes de código, tendo um histórico de suas alterações e diminuindo o risco de perder partes do código devido uma alteração incorreta que fizemos sem perceber.

Se você já fez algum trabalho em grupo tanto acadêmico quanto profissionalmente, em que você tem arquivos do office por exemplo, é muito provável que existiram cópias dos arquivos, como por exemplo "documento_1.doc" ou "documento_versão_do_fulano.doc", isso em desenvolvimento de código também ocorria antigamente, mas são épocas passadas. Se você ainda desenvolve assim, ou você ainda não foi apresentado ao git ou você precisa ser estudado.

É extremamente comum desenvolvedores de todos os níveis postarem links de seus repositórios do Github ou Gitlab (nunca vejo ninguém comentar nem a existência do bitbucket) em suas redes sociais. Esses sites são na verdade repositórios onde boa parte dos devs guardam uma cópia do seu código, mesmo você podendo hospedar em um HD ou até mesmo alguns serviços de nuvem com acesso mais restrito para outras pessoas. Sim, eu sei que tanto o github quanto o gitlab permitem criar repositórios privados, mas até quando eles estarão disponiveis para você? Os termos do github nos dizem que isso é um mistério, sabia? É, a gente não costuma ler os contratos (me incluo fortemente nessa parte), e podemos ser surpreendidos um dia.

Então só quero deixar claro que você não precisa de um repositório online para versionar seu código e também não precisa enviar uma cópia para lugar nenhum, você pode ter (por sua conta e risco) seu código apenas no seu HD e mesmo assim ter os benefícios da utilização do git.

Ajudando a simplificar o trabalho

Boa parte de criação de branchs e gerenciamento delas, vou me referir utilizando o git flow, porque eu sinceramente não sei usar o git sem o uso do git flow.
Minha vivência com git desde o inicio da minha carreira de dev, sempre foi utilizando essa ideia de fluxo de trabalho descrita em um artigo do Vincent Driessen em Janeiro de 2010, que uso como base mas que sinceramente aprendi pelo cheatsheet do Daniel Kummer.

Confere lá tanto o cheatsheet quanto o artigo para ver como o git flow pode te ajudar.

Criando uma nova branch a partir de develop

Você recebeu a tarefa de criar uma nova funcionalidade para uma determinada classe, por isso vai iniciar sua branch com base em develop, utilizando o comando:

git flow feature start nome-da-branch
Enter fullscreen mode Exit fullscreen mode

Exemplo:

Image description

Imagem 01 - Iniciando uma branch

Adicionando alterações em stage e fazendo o commit

Agora basta fazer as alterações necessárias e adicionar os arquivos alterados no stage para em seguida fazer o commit deles, com os comandos:

git add nome-do-arquivo
git commit -m "mensagem do commit"
Enter fullscreen mode Exit fullscreen mode

Exemplo:

Image description

Imagem 02 - Fazendo o commit

Corrigindo mensagem do commit

Você notou que cometeu um erro na mensagem, e agora? Deixa assim e tá tudo certo, não é mesmo? NÃO! Corrija isso, pelo amor hein.

git commit -m "mensagem correta do commit" --amend
Enter fullscreen mode Exit fullscreen mode

Exemplo:

Image description

Imagem 03 - Corrigindo a mensagem do commit com amend

Note que ao fazer isso, o hash de identificação do commit mudará, isso poderá causar problema para outras pessoas que já tenham esse commit em seu repositório local, então evite fazer esse tipo de alteração em branchs como master e develop que geralmente são as branchs principais de um projeto.

Fazendo um squash dos commits

Uma prática muito boa, é fazer um squash dos commits da sua branch, antes de mandar todas as suas alterações para develop.

Eu conheço duas formas de fazer o squash, então vou exemplificar cada uma delas.

Em ambos os casos, precisamos verificar quais os commits vamos unificar. No exemplo, faremos isso com todos os 4 commits feitos na nova branch.

Uma das formas de saber qual foi seu primeiro commit nessa nova branch, é verificar utilizando o log do git, qual o commit está na branch de origem, que no caso, é develop.

git log --oneline
Enter fullscreen mode Exit fullscreen mode

Image description

Imagem 04 - Vendo os logs de commits

Squash utilizando o reset soft

Vamos então, fazer o squash utilizando o reset soft.

git reset --soft HASH-DO-COMMIT-ANTERIOR-AO-NOSSO-PRIMEIRO-COMMIT
Enter fullscreen mode Exit fullscreen mode

Exemplo:

Image description

Imagem 05 - git reset --soft

Após o reset soft, todas as alterações feitas nos 4 commits da nossa branch, estarão em stage, prontas para um novo commit, e todos os commits não estarão mais em nosso log.

Image description

Imagem 06 - git rebase -i

Basta então fazer o commit com a mensagem que melhor descreve o que foi feito no código.

Squash utilizando o rebase -i

Vamos então, fazer o squash utilizando o rebase.

git rebase -i HEAD~4
Enter fullscreen mode Exit fullscreen mode

Isso fará com que o novo head da branch seja um commit com os 4 últimos commits juntos.

O comando nos leva para uma arquivo dentro do nosso editor padrão, onde são exibidos os commits que serão unificados.

Image description

Imagem 07 - Arquivo de seleção de commits para o squash

Marcamos como 'pick' o commit que será usado e marcamos como 'squash' os commits que serão "mesclados".

Image description

Imagem 08 - Alterando os commits que irão apra squash

Após salvar as alterações, um novo arquivo será apresentado, onde colocaremos a mensagem do novo commit.

Image description

Imagem 09 - Exibindo a mensagem do novo commit

Podemos apagar todos os comentários (é o que costumo fazer) e adicionar a nova mensagem.

Image description

Imagem 10 - Alterando a mensagem do novo commit

O resultado de tudo isso, é um commit com todas as alterações unificadas.

Image description

Imagem 11 - Resultado do rebase

Publicando a branch

Com tudo pronto, em um fluxo saudável de desenvolvimento, publicamos a branch para um code review ou testes, então os comandos seriam:

git flow feature publish nome-da-branch
Enter fullscreen mode Exit fullscreen mode

Exemplo:

Image description

Imagem 12 - git flow feature publish

Finalizando a branch/mergeando em develop

Finalizado os testes/reviews e as alterações feitas na branch sendo aprovadas, é hora de finalizar a branch.

git flow feature finish nome-da-branch
Enter fullscreen mode Exit fullscreen mode

Exemplo:

Image description

Imagem 13 - git flow feature finish

Sempre que uma branch do tipo feature (lembre de ver mais detalhes no cheatsheet mencionada lá no começo do artigo) for finalizada, seus commits são enviadas para develop, agora é só dar push de tudo.

git push origin develop
Enter fullscreen mode Exit fullscreen mode

Exemplo:

Image description

Imagem 14 - push de develop

Remover alterações de stage

Uma vez ou outra, acabamos adicionando um arquivo novo sem necessidade, ou alterando arquivos que não eram para ter sido alterados, mas por falta de atenção, acabamos adicionando tudo no stage (para de usar o "git add ." caramba!), e nada melhor do que um simples reset -- do arquivo alterado erroneamente.

git reset -- nome-do-arquivo
Enter fullscreen mode Exit fullscreen mode

Exemplo:

Image description

Imagem 15 - Retirando alterações do stage

SIM, é um hífen duas vezes, seguido por um espaço em branco, só depois adiciona-se o nome do arquivo.

Colocando o nome do arquivo, ele sairá do stage, se não inserir nome do arquivo após os dois hifens, todos os arquivos que estão prontos para serem comitados, irão sair do stage.

Outros fluxos do git flow

Não vou focar em outras partes do git flow tão detalhadamente (acredite, o flow merece mais atenção, então novamente, olhe o cheatsheet), então vamos para um resumo de outros comandos que utilizo com certa frequência, incluindo o fluxo deles.

  • Fluxo de um release
    Ocorre quando tudo que fizemos em develop, precisa ser enviado para a branch principal.

    • git flow release start v1.0.0 Inicia uma nova branch com base em develop e cria a tag de versão.

    O v1.0.0, é a tag que identificará a versão da release. Leia sobre o versionamento semântico.

    • git add nome-do-arquivo e git commit -m "mensagem do commit" Adicionamos os arquivos no stage e adicionamos a mensagem do commit.
    • git flow release finish v1.0.0 Finaliza a branch de release e todos os commits que estavam em develop, vão para 3 branchs que são:
      • develop
      • v1.0.0 (tag criada com a versão 1.0.0 do projeto)
      • master
  • Fluxo de um hotfix
    Ocorre quando descobrimos que existe um problema em produção/branch principal que não pode aguardar para ser corrigido.

    • git flow hotfix start v1.0.1 Inicia uma branch com base em master/branch de produção.
    • git add nome-do-arquivo e git commit -m "mensagem do commit" Após corrigir o que for necessário, adicione o arquivo com o git add e faça o commit com git commit -m
    • git flow hotfix finish v1.0.1 Finaliza a branch hotfix e todos os commits do hotfix serão enviados para:
      • develop
      • v1.0.1
      • master

Considerações finais

A idéia do artigo era guardar para meu próprio uso e consultas futuras (caso precise), e compartilhar com algumas pessoas próximas que usam o git, porém, acredito que o resultado ficou até que legal (levando em consideração quem escreveu hahahaha), então decidi compartilhar.

O artigo do Vincent Driessen em Janeiro de 2010, já tem uma nota de reflexão de março de 2020, sugerindo o uso do GitHub flow, mas no meu uso atual, o git-flow ainda me atende MUITO bem, analise o que é melhor para você e sua equipe, não procure a resposta pronta, o que é melhor para você e sua equipe pode ser diferente do que funciona para a minha equipe ou para a equipe do seu amiguinho dev.

Obs.: Este artigo foi revisado pela mesma pessoa que escreveu, porém com sono. Tudo escrito aqui foi baseado na MINHA EXPERIÊNCIA como dev pleno de 2 anos (huehuebr), não leve possíveis erros para o coração, envie sugestão que podemos fazer um hotfix do artigo :-)

Dicionário de termos

  • Stage

    É a área onde ficam as alterações que estão prontas para o commit

  • Commit

    É o ponto onde tornamos "permanentes" um conjunto de alterações, como se estivesse salvando um documento do word com um nome para consulta futura daquelas alterações.

  • Squash

    É quando você junta diversos commits em um único novo commit para que o log do git fique mais organizado e mais simples de entender ou de voltar em um conjunto de alterações específica.

  • Reset

    É quando voltamos a branch para um estado específico

    • git reset --soft

    É a opção onde tudo que foi alterado permanece em stage pronto para ser comitado, desconsiderando apenas os commits em si.

    • git reset --hard

    É a opção onde tudo que foi alterado é ignorado/jogado fora.

  • HEAD

É a última versão de uma branch, o último commit, o mais recente, the major rsrsrsrs

Top comments (0)