Se você estuda ou trabalha com desenvolvimento, provavelmente já ouviu falar de git, que é uma ferramenta gratuita e open source de versionamento de código (não é só isso, mas vamos simplificar). Quando eu comecei a estudar programação, toda a minha organização e versionamento de códigos era baseada em criar várias pastas no meu computador e ficar replicando várias e várias vezes. Quando queria compartilhar com alguém nós criávamos um .zip da pasta toda e depois gastávamos algumas horas tentando bater alterações pra fazer a entrega no final (meu TCC do técnico está guardado até hoje como tcc_final.zip
no OneDrive).
Git veio justamente pra resolver esses problemas: é mais fácil de gerenciar a evolução do seu código ou da sua aplicação; e principalmente, é muito mais fácil colaborar no desenvolvimento.
Tudo que eu preciso saber sobre?
Meu objetivo aqui é simples: prover toda informação disponível para você (desenvolvedor) começar e conseguir usar a ferramenta da vez. Não pretendo responder tudo que você pode ou deveria saber, apenas o necessário.
O que é git
Numa tradução livre da documentação oficial, git
é um sistema de controle de versão distribuído gratuito e de código aberto, projetado para lidar com projetos de pequenos a muito grandes, com velocidade e eficiência.
Ele foi criado pelo Linus Torvalds (criador do Linux) em 2005, para ajudar a gerenciar o desenvolvimento do kernel Linux.
A ideia de ser um sistema distribuído é que isso possibilita que várias pessoas ou times possam colaborar num projeto de software enquanto cada um mantém suas próprias cópias locais do projeto todo, incluindo seu histórico. Isso é o oposto do que seria se fosse um sistema centralizado, o que significaria que todos usuários precisariam se conectar a um único e mesmo repositório central.
E um sistema de controle de versão é feito para gravar mudanças em arquivos (ou grupos de arquivos) ao longo do tempo, de forma que você possa recorrer a versões específicas mais tarde. A verdade é que vamos falar aqui de usar no contexto de software, mas isso pode ser usado para basicamente qualquer tipo de arquivo num computador. Então seria muito interessante usar isso mesmo para trabalhos como edição de video, por exemplo.
Ou seja, git existe para te ajudar a acompanhar as mudanças na sua base de código, a colaborar com múltiplas pessoas desenvolvedoras e a garantir que você tem uma forma de backup e recuperação de como era o seu código a qualquer momento; tudo isso além de ter um sistema de branch que permite que possamos trabalhar no código sem afetar o código “principal”.
Um ponto importante, é que git é o sistema, e não está diretamente relacionado com as empresas e softwares Github e Gitlab.
Quando eu deveria usar git
Sempre. Sério, o único motivo que pode justificar a não utilização de git em um projeto, é falta de conhecimento. E pra isso que estou escrevendo isso aqui, então no geral, use sempre.
Mas falando de forma geral, os principais casos de uso são justamente o de trabalhos colaborativos, além do poder de controlar o versionamento em si. Sabe quando você faz um projeto, que está funcionando, ai começa a mexer pra “melhorar” e ele para de funcionar? Com git você consegue voltar no histórico sem depender do seu ctrl+Z.
E apesar de poder usar localmente, é difícil encontrar motivos pra não usar algum host de git (mesmo para os seus projetos pessoais) como o Github, Gitlab ou Bitbucket, já que todos têm planos gratuitos.
Por onde começar
Já que eu espero que você tenha lido sobre como configurar o windows para desenvolvimento, vou dizer como se instala no Ubuntu. Caso precise instalar em outro sistema, a documentação oficial tem exemplos para várias opções.
No nosso caso, basta executar
sudo apt install git
git config
Depois de instalar, idealmente você precisa fazer algumas configurações padrões para garantir o melhor funcionamento. Parte das informações armazenadas pelo git envolvem seu nome e email, por exemplo, para que sejam anexadas ao histórico de alterações. Para configurar essas informações de forma global, você pode usar os seguintes comandos:
git config --global user.name "[seu nome ou nome de usuário]"
git config --global user.email "[seu email]"
Também podemos configurar essas informações em nível de repositório, mas para começar a configuração global é mais do que suficiente.
Como funciona
(não que você precise saber)
Ao invés de tentar armazenar quais alterações são feitas em quais arquivos, Git pensa nos seus dados como uma série de snapshots de um sistema de arquivos. Ou seja, toda vez que você faz um commit (que é a ação de salvar o estado do seu projeto), Git vai basicamente tirar uma foto de como todos os seus arquivos estão naquele momento, e armazenar uma referência a isso. E pra ser eficiente, se não houve nenhuma alteração em algum arquivo, ele não vai ser armazenado novamente. Ao invés disso, o Git vai simplesmente fazer uma referência ao arquivo que já foi armazenado.
Além disso, quase toda operação feita com Git depende somente dos seus recursos e arquivos locais, sem depender muito de informações vindas de outro computador ou de um servidor. Isso faz com que ele seja extremamente rápido e eficiente, além de garantir que mesmo que você esteja offline, vai conseguir trabalhar.
E a forma como Git “mede” as alterações em arquivos, é que eles fazem o processo chamado de checksum. A ideia é que você gera um valor com base no conteúdo do arquivo, e caso o conteúdo se altere, esse valor também é alterado. Isso é uma forma de garantir que Git tenha integridade, já que é impossível que o conteúdo de qualquer arquivo ou diretório seja mudado sem que Git note. (Esses checksums são gerados a partir de um hash SHA-1 , que é uma string de 40 caracteres hexadecimais, tipo assim: 24b9da6552252987aa493b52f8696cd6d3b00373
. Quando usar git, vai ver que esses códigos estão presentes em todo lugar, porque é assim que as informações são armazenadas).
Conceitos fundamentais
Commit
Como mencionado brevemente acima, o commit é a ação de salvar o estado atual do seu projeto.
Branch
Apesar do poder do versionamento, as vezes precisamos trabalhar em múltiplas coisas de uma vez. É nesse contexto que as branches (ou ramificações) aparecem. Git consegue armazenar múltiplos estados diferentes do seu projeto através dessas ramificações, que posteriormente podem ser juntadas de acordo com a necessidade.
Comandos básicos
init
Esse é o comando que você executa num diretório para iniciar um novo projeto de git. Ele vai fazer a inicialização básica do sistema.
git init
clone
Caso queira fazer uma cópia de um projeto já existente, você usa esse comando.
git clone [URL do projeto remoto]
pull
É o jeito mais comum de baixar o conteúdo mais recente do repositório remoto, mas é preciso ter cuidado com ele. Quando você executa um pull
, além de baixar tudo ele também atualiza o seu conteúdo local para o mais recente, o que pode gerar conflitos.
git pull
branch
É o comando usado para listar, criar ou apagar uma branch.
# Listar todas as ramificações
git branch
# Criar uma nova branch
git branch [nome da branch nova]
# Apagar uma branch
git branch -d [nome da branch]
checkout
Continuando na ideia de branches, esse comando é usado para definir qual é a branch ativa do seu repositório local.
git checkout [nome da branch]
# bonus: criar e trocar para uma branch
git checkout -b [nome da branch nova]
add
Conforme você vai fazendo alterações, você precisa adicionar elas para que sejam armazenadas posteriormente. Você vai usar esse comando quando cria novos arquivos, quando muda o nome deles ou quando altera o conteúdo. É importante entender que isso não vai armazenar o estado, vai apenas colocar os arquivos na “fila”.
## para adicionar um arquivo ou diretório específicos
git add [arquivo ou diretório]
## para adicionar N arquivos ou diretórios especificos
git add [arquivo1] [arquivo2] [diretorio]
## ou para adicionar todos os arquivos alterados
git add --all
## ou
git add *
commit
Para salvar o estado atual do projeto, após ter adicionado os arquivos, fazemos um commit. Ele vai criar uma nova revisão do seu repositório, gerar um novo código e guardar todas as alterações que foram feitas, junto com a informação de quando e por quem foram feitas.
## Para uso interativo, dessa forma você vai ser
## direcionado para um editor de texto antes de finalizar o commit
## Aqui você deve escrever sua mensagem de commit, com os detalhes que achar necessários.
git commit
## Caso a mensagem seja curta, ou simplesmente não queira passar pelo editor
git commit -m "[sua mensagem de commit]"
Aqui também fica a recomendação da utilização dos Commits Convencionais, que são uma sugestão de padrão do início da mensagem de commit.
push
É basicamente o contrário do pull
, serve para enviar suas alterações locais para o repositório remoto.
# Enviar alterações para uma branch que já existe no remoto
git push
# Enviar alterações para uma branch que foi criada local
git push --set-upstream [nome do remoto] [nome da branch]
# geralmente é usado como git push --set-upstream origin [branch]
status
É usado para comparar o estado atual do seu repositório local com o último estado armazenado, e com o repositório remoto (caso haja).
git status
fetch
De forma semelhante ao pull, serve para baixar mudanças feitas no projeto remoto. A diferença é que dessa forma elas não serão aplicadas automaticamente para o seu repositório local, você vai precisar definir o que fazer com as alterações na sequência.
git fetch
stash
As vezes precisamos mudar de branch depois de já ter trabalhado em uma, mas antes que as coisas estejam prontas o suficiente para virar um commit. Nesse contexto podemos usar o stash, que vai armazenar temporariamente as modificações na área de stash, que é essencialmente é uma pilha (uma lista onde os elementos são empilhados).
# Para "guardar" os arquivos no stash
git stash
# Para listar todos os existentes
git stash list
# Para apagar um stash da pilha
git stash drop
# Para recuperar um stash
git stash apply
# Para aplicar/recuperar e remover da pilha (eu costumo usar esse)
git stash pop
merge
Depois de trabalhar em múltiplas branches, provavelmente você vai precisar unificar as coisas em algum momento. É ai que entra o merge, que vai ser responsável por juntar 2 branches em uma única.
git merge [branch de destino] [branch de origem]
Isso vai criar um commit de merge na branch de destino, e vai atualizar comparar apenas as últimas versões de cada um. Esse é um método interessante porque ele não vai mexer no histórico de nada, vai apenas criar um novo commit para garantir que as coisas estejam atualizadas.
Comandos adicionais
rebase
O objetivo é parecido com o do merge, mas o rebase reescreve o histórico de commits do projeto, de forma que ele move a sua branch para o final do histórico, criando novos commits para cada commit da branch de origem, de forma que o histórico do seu projeto vai ficar muito mais “limpo”. Isso porque ele não tem os commits de merge (que são feitos quando você usa git merge
, e no final o histórico do seu projeto fica perfeitamente linear (enquanto com merge as coisas podem ficar difíceis de acompanhar, dependendo da complexidade do projeto). É importante deixar claro que com isso você perde um pouco da rastreabilidade (pois está sempre reescrevendo o histórico) e você perde o contexto de quando as alterações foram “aceitas” na sua branch principal.
git checkout [branch de destino]
git rebase [branch de origem]
Esse é um comando que pode impactar bastante o trabalho colaborativo, então antes de pensar em usar é importante saber se tem mais alguém trabalhando na branch em que você vai mexer. Isso porque vão acontecer vários conflitos entre a sua versão (a com rebase) e a versão que a pessoa pode estar trabalhando. Algumas pessoas chamam isso de “Golden Rule do rebase”.
log
Esse é o comando que você pode usar para ver o histórico de commits do repositório.
git log
revert
Esse é um comando para desfazer mudanças, mas que ao invés de modificar os commits já feitos no histórico, ele vai criar um novo commit desfazendo as mudanças. Podemos considerar que é uma alternativa segura ao git reset
, que tem uma chance de te fazer perder o histórico.
git revert [commit hash]
# Também podemos dizer quantos commits a partir do último serão revertidos
git revert HEAD~[numero de commits]
remote
Esse é o comando que você usa pra criar a conexão entre o seu repositório local e um repositório remoto.
git remote add [apelido do repo remoto] [url do repositório]
# Geralmente vai ser algo como
git remote add origin <https://github.com/>[nome de usuario]/[nome do repo]
cherry-pick
Imagina que você e uma outra pessoa estão trabalhando em duas branches diferentes, mas que a outra fez um commit com uma alteração que você também pode usar, e você não quer reescrever algo que já foi feito. O cherry-pick permite que você selecione qualquer commit de uma branch, e aplicá-lo a uma outra branch, sem ter que se preocupar com o histórico todo.
git cherry-pick [commit hash]
blame
É o comando utilizado para dizer qual usuário fez quais alterações num determinado arquivo.
git blame [nome do arquivo]
Na prática
Apesar de achar importante você conhecer, entender e saber usar a linha de comando, a verdade é que você provavelmente não precisa. A maioria das IDE’s ou editores de código tem extensões para lidar com git e te prover uma interface que facilita bastante a utilização. Também existe o Github Desktop mas eu pessoalmente não gosto muito dele.
Uso a maior parte das coisas direto na extensão de git padrão do VS Code, que te da um resumo das alterações atuais do repositório, uma lista de commits, de branches e de stashes e honestamente tudo que você pode precisar. Isso facilita muito, principalmente na hora de resolver conflitos.
Ele também acrescenta o git blame
no próprio editor, fazendo ficar bem fácil entender o histórico do projeto.
Eu só uso a extensão padrão, mas se você tiver recomendações de extensões, fique a vontade pra acrescentar nos comentários.
Onde encontrar mais informações
A melhor fonte é provavelmente a oficial, que é onde eu costumo buscar referências (e o que serviu de inspiração pra boa parte do que está aqui):
Git Book (em PT-BR): https://git-scm.com/book/pt-br/v2
Git Book: https://git-scm.com/book/en/v2
Também gostei bastante do conteúdo da Atlassian, que é a empresa criadora do BitBucket
E como não pode faltar, também tem conteúdo da LINUX Tips sobre git:
Descomplicando o Git: https://www.youtube.com/watch?v=_aj3hsEh9iw
Aulão de certificação do gitlab: https://www.youtube.com/watch?v=SMzaAP09BD4
Conclusão
A verdade é que eu fiquei anos usando git e só sabendo git add
, git commit
, git pull
e git push
. Isso é tudo que você precisa pra um projeto simples, e usando alguma extensão com interface gráfica você só precisa entender as ações e como executá-las na interface que estiver usando.
Mas conforme vamos trabalhando, passando por projetos de maior complexidade ou simplesmente precisando fazer coisas em grupo, os conflitos e erros começam a acontecer e aí precisamos entender melhor o poder dessa ferramenta.
Não espero que ninguém saia desse post sabendo usar tudo isso, mas aqui tem uma introdução de tudo que eu gostaria de saber quando comecei. Saber quando usar qual comando vem da utilização na prática, então minha recomendação é sempre que você comece. E novamente, não consigo pensar em um motivo pra não usar git em qualquer projeto de desenvolvimento, seja pessoal, de estudos, de faculdade ou de trabalho.
Me diz o que você achou desse tipo de post, e se você gostaria que isso virasse um vídeo no Youtube! Independente do resultado, semana que vem vou falar sobre RegEx.
Espero que isso tenha sido útil para alguém, até a próxima!