Um pouco sobre Git

Breno Souza | 13 Nov 2024

Todos os anos sou convidado pelo professor Rogério Diogines para lecionar sobre Git para a turma de Telemática do Instituto Federal de Educação, Ciência e Tecnologia do Ceará, e este post tem como objetivo sintetizar o que apresento aos alunos.

Aqui abordaremos as principais características, conceitos e comandos do Git necessários para todo iniciante no vasto mundo do desenvolvimento de software. E aí, vamos nessa?

Definição

Git nada mais é que um Sistema de Controle de Versão Distribuído, criado pelo engenheiro de software que desenvolveu o kernel (núcleo do sistema operacional) do Linux, o grandessíssimo Linus Torvalds.

Linus Torvalds

Mas afinal, o que é um Sistema de Controle de Versão Distribuído? Para melhor entendimento, vamos dividir a definição em duas partes:

  • Sistema de Controle de Versão: É um sistema cuja função é registrar quaisquer alterações feitas em um código, de modo a facilitar seu compartilhamento com o time de desenvolvimento. Ele armazena esse código e seu histórico de mudanças, permitindo, caso necessário, regredir a versões anteriores da aplicação de forma simples e rápida.

  • Distribuído: Em vez de ter um único local contendo o histórico completo da versão, o Git possibilita que a cópia de trabalho de todo desenvolvedor também seja um repositório que contém o histórico completo com todas as alterações.

    De forma simples, um sistema distribuído é um conjunto de computadores independentes que trabalham juntos para executar tarefas de forma coordenada, como se fossem um único sistema.

Principais Termos

O Git possui vários termos e conceitos para diferentes fluxos de trabalho ou ações do cotidiano do desenvolvedor, mas aqui irei listar os principais e, por que não dizer, essenciais para programadores iniciantes.

  • Branch: É o nome dado a uma versão (ramificação) do projeto. Isso é útil porque possibilita gerenciar múltiplas alterações acontecendo simultaneamente.

    Todo projeto deve possuir branches padrões como a master ou main e a develop. O objetivo de cada uma será apresentado mais adiante. Cada nova funcionalidade ou correção de bug deve ter sua própria branch derivada de uma dessas branches. Exemplos de nomes de branches: para uma funcionalidade, feat/login-screen; para uma correção, fix/login-authentication.

    O padrão de nomenclatura das branches varia de projeto para projeto, normalmente determinado por uma convenção entre os desenvolvedores do time.

  • Commit: É uma descrição curta do que foi modificado. Ao desenvolver a primeira parte de uma funcionalidade, “commite”. Ao adicionar um novo pacote na aplicação, “commite”. Ao mudar configurações, “commite”!

    Uma boa prática é commitar sempre que uma modificação é feita e validada para que fique fácil rastrear e corrigir algum problema no futuro.

    Quando verificar que já existe uma grande quantidade de arquivos modificados, adivinha? “Commite”! Isso evitará dores de cabeça à medida que o projeto cresce.

  • Repositório: São os ambientes criados para armazenar seus códigos. Você pode possuir um ou mais repositórios públicos (qualquer um que acessar seu GitHub poderá ter acesso ao código) ou privados, locais (armazenados em sua máquina) ou remotos (armazenados em plataformas online).

    Podem armazenar não somente os próprios códigos a serem modificados, mas também imagens, áudios, arquivos e outros elementos relacionados ao seu projeto.

    Elementos que não devem subir para repositórios remotos são declarados no arquivo .gitignore.

  • Merge: Para unir as modificações feitas em uma branch ao código original, utilizamos o comando merge. Com esta funcionalidade, todas as alterações feitas em cópias manipuláveis são inseridas, após aprovadas, no código-fonte original sem complicações.

    Lembra que falei que toda nova funcionalidade possui sua própria branch? Um cenário comum de uso do merge é quando você quer atualizar a branch local da sua funcionalidade com modificações feitas por outros do time, isto é, eles jogam suas alterações na develop, e você faz o merge da develop na sua branch.

Git x GitHub

É bem comum, no começo, as pessoas que estão entrando na programação confundirem Git com GitHub ou acharem que são a mesma coisa.

Git Hub

GitHub é uma plataforma totalmente online onde você pode criar repositórios e hospedar seus projetos, colaborar com softwares open source, seguir outros(as) programadores(as) e interagir com códigos de terceiros. Ou seja, funciona também como uma rede social.

Basicamente, o Git, como já falamos, é um sistema de versionamento com branches e repositórios locais, diferente do GitHub, que é uma plataforma web com branches e repositórios remotos.

Outro ponto interessante é a possibilidade de implementar CI/CD. É um conjunto de práticas de desenvolvimento de software que visa automatizar e tornar mais eficiente o processo de entrega de código. Ele é dividido em duas partes:

  • CI (Continuous Integration): Integração Contínua. Os desenvolvedores enviam (ou integram) pequenas partes de código para um repositório central várias vezes ao dia. Cada vez que o código é enviado, testes automáticos são executados para garantir que ele funciona e não “quebra” o sistema. Assim, problemas são identificados rapidamente.

  • CD (Continuous Delivery ou Continuous Deployment): Entrega Contínua ou Implantação Contínua. A primeira, Continuous Delivery, é o processo de preparar o código para a produção automaticamente, garantindo que esteja sempre pronto para ser lançado. A segunda, Continuous Deployment, vai além e coloca o código em produção automaticamente após passar pelos testes.

Principais Comandos

O Git possui vários comandos para diversas situações no processo de desenvolvimento de software. Existem vários cheat sheet (Resumo / Folhas de dicas) com os vários comandos do Git e suas breves descrições, como este: GIT CHEAT SHEET.

A seguir, listei os principais que todo desenvolvedor iniciante precisa saber para começar seus primeiros passos com o uso do Git.

  • Init: Este comando dá origem a um repositório novo ou reinicializa um repositório já existente.

    git init newProject
    
  • Clone: Este comando clona o código de um repositório para sua manipulação em outro ambiente.

    git clone https://github.com/Brenovisk/SimpleLogin.git
    
  • Branch: Cria uma nova branch.

    git branch feature/nova-feature
    
  • Commit: Este comando move os arquivos da stage area para um repositório local, adicionando um comentário à modificação. Simplificando, esse comando grava as mudanças preparadas (stage) no histórico do repositório local, criando um ponto de registro com uma mensagem que descreve as alterações realizadas.

    É como tirar uma “foto” do estado atual dos arquivos para que você possa acompanhar ou reverter as mudanças no futuro.

    git commit -m "my commit"
    
  • Push: Este comando envia arquivos de um repositório local para um repositório remoto. No GitHub, por exemplo.

    git push
    
  • Pull: Ao contrário do push, este comando traz os arquivos do repositório remoto para o repositório local e mostra as modificações.

    git pull
    
  • Checkout: Este comando serve basicamente para mudar de branch.

    git checkout main
    
  • Stash: Este comando é útil quando você quer mudar de branch, mas não deseja “commitar” (pois não é possível trocar de branch se tiver arquivos na stage area). O comando guarda suas modificações.

    git stash
    

    Para pegá-las novamente, use o apply no comando:

    git stash apply
    

Git Flow

O Gitflow é apenas uma ideia abstrata do fluxo de trabalho Git, ou seja, ele dita que tipos de ramificações configurar e como e quando fazer o merge. Esse fluxo é bastante usado nas empresas de software, seja à risca ou com algumas adaptações, dependendo do ritmo e processo da empresa. A seguir, irei falar um pouco sobre as branches utilizadas e o fluxo propriamente dito.

Principais ramificações

  • Master ou Main: É a ramificação com os resultados finais das implementações. É o que será utilizado pelo cliente/usuário final. Por exemplo, o app que está na Google Store ou App Store veio da branch main; o site que você acessa também veio da branch main.

  • Develop: Serve como uma ramificação de integração para recursos. Simplificando, é a branch onde as novas funcionalidades são inseridas.

  • Feature: Cada nova funcionalidade deve ter sua própria branch e deve se originar da develop. Ao concluir, deve-se fazer merge de volta para a develop para que outros desenvolvedores possam ter acesso à nova funcionalidade. Outro ponto é que essa branch nunca deve interagir diretamente com a main.

Feature
  • Release: Uma vez que a branch develop adquiriu recursos suficientes para um lançamento (ou a data de lançamento está se aproximando), você cria uma branch release a partir da develop. As versões para testes geralmente saem dessa branch e é nela que as correções de bugs são realizadas antes do lançamento. Ao concluir, deve-se mandar para produção (merge com a main) e, após isso, fazer merge de volta para a branch de develop.
Release
  • Hot Fix: É a branch criada a partir da main para resolver um bug em produção (em versões já lançadas e que o usuário já está utilizando). O Hot Fix é a única branch que se origina diretamente da main. Depois de resolver o bug, deve-se fazer o merge dela tanto para a main quanto para a develop (ou na release atual).
Hot Fix

Ah, e é necessário mudar o número de versão da main. Isto é, o número mais à direita (conhecido como patch) é incrementado. Por exemplo, a versão antes do fix era 1.2.0, depois ficaria 1.2.1.

Exemplo de um fluxo completo

Suponhamos que você já tenha instalado e configurado o Git na sua máquina (nesta folha de dicas tem uma forma simples e objetiva) e queira adicionar uma nova funcionalidade em seu app, por exemplo, sign in com o Google. O que devemos fazer de acordo com o Git Flow? A seguir está o fluxo que uso normalmente no dia-a-dia, ele é o git flow com um pouco adaptado pelo fluxo do meu time de desenvolvimento. Confira a seguir:

  1. Crie as branches main e develop, caso ainda não tenha criado:

    git branch main
    
    git branch develop
    
  2. Mude para a branch develop:

    git checkout develop
    
  3. Crie a branch da funcionalidade derivando da develop. O comando a seguir cria e já muda para a nova branch em um único comando:

    git checkout -b feature/sign-in-google
    
  4. Neste momento, você já pode implementar a funcionalidade. Ao concluir, prepare e “commite”:

    git commit -am "Descrição das mudanças"
    
  5. Faça o push de suas mudanças para o repositório remoto e lá crie um Pull Request para a develop. Nada mais é que uma solicitação para revisar e integrar alterações de uma branch em outra, geralmente usada em colaboração em projetos Git (saiba mais). Nesse caso, as mudanças da sua feature irão para a develop após a aprovação.

    Observação: O Pull Request ao realizar a integração entre duas branches está realizando um merge entre elas. Isto é, é como se você mudasse para a branch, nesse caso, develop, e executasse o comando:

    git merge feature/sign-in-google
    
  6. Após o revisor aprovar, mude para develop e pegue as alterações:

    git checkout develop
    
    git pull
    
  7. Com a develop atualizada, crie uma branch release a partir da develop e mude para ela:

    git checkout -b release/1.0.0
    
  8. Envie para o repositório remoto:

    git push
    
  9. Após o time de testes aprovar a release atual, repita o procedimento de Pull Request agora para a master e para develop, para que sua feature seja enviada para a produção!

Conclusão

O Git é uma ferramenta indispensável no desenvolvimento de software, especialmente para quem trabalha em equipe ou quer manter um histórico organizado do seu código. Dominar os conceitos e comandos básicos, como branch, commit, merge, entre outros, é o primeiro passo para usar o Git de forma eficiente.

Além disso, entender fluxos como o Git Flow e a integração com plataformas como o GitHub pode facilitar muito a gestão de projetos.

Espero que este guia tenha esclarecido as principais dúvidas e servido como um bom ponto de partida para você. Agora, é hora de praticar e explorar esse poderoso sistema de versionamento! 🚀

Anexos