Git básico: só que .ignorando o básico
Introdução
Eu sei que prometi ignorar a parte que você já sabe sobre git, mas eu preciso que todos estejamos na mesma página durante essa leitura. Então, se você já tá careca de saber um pouquinho da história do Git, pode pular para o próximo parágrafo. Se você ainda tá aqui, vou presumir que precisa de algum contexto, então: o git é a resolução de um problema, mas não do versionamento de código porque isso já existia antes dele. O git veio como uma alternativa ao BitKeeper visando mais velocidade, suporte para trabalho em equipes (às vezes até milhares de pessoas) e resolver outras dores dos desenvolvedores. O Linus Torvalds, que inventou o sistema operacional Linux, decidiu que era hora de facilitar todo esse trabalho porque as alternativas eram: usar os sistemas já existentes ou trabalhar compartilhando arquivos que podiam ou não ser a versão mais recente.
Ok, agora já temos contexto suficiente para eu poder te falar que usar Git só pra dar commit
e push
é tipo comprar um liquidificador e só usar pra misturar açúcar no seu café (ou chá, leite ou qualquer bebida que você prefira). Funciona? Sim. É só isso? NÃO!
É muito comum aprendermos o básico nos nossos primeiros meses de estudo. Adicionar os arquivos, fazer commits, fazer forks, criar uma branch… Depois a gente começa a usar o git em equipe e vem o choque inicial de não sabemos lidar com um conflito de merge, mas a gente supera essa fase. Começamos a expandir mais os nossos conhecimentos, usamos um cherry-pick
ou talvez um --force
. É completamente possível resolver inúmeros problemas assim, mas será que a gente realmente sabe o que tá fazendo? Ou só estamos copiando o que aprendemos nosso youtuber fav ou com um salva-vidas no StackOverFlow?
Os porquês
Antes de tudo, quero te apresentar uma grande amiga: a documentação. Eu sei, eu sei; você já a viu, ela parece ser chata e até meio metida, mas te juro que ela é gente boa. Clicando aqui, você vai acessar aquele site com um design meio old-school que pode já ter aparecido nas suas pesquisas no Google. Tô te falando dele porque foi o que eu usei como referência para esse artigo.
Agora, voltando ao título dessa sessão: antes dos porquês, vamo dar uma passada nos “por ques” e “o ques”!
- Por que a gente precisa dar
add
antes fazer um commit? - Por que às vezes acontece de um colega ter dado push, mas quando você usa o
pull
recebe umAlready up to date.
? - Por que às vezes só fazemos
pull
e outras vezes fazemos umfork
? - O que acontece se você quiser trazer pro seu perfil um projeto que você foi adicionado como colaborador e não fez
fork
? Aliás, dá pra fazer isso? Como?
Não, não, não. Antes de você lançar um “porque é assim que se faz” ou “porque aprendi assim”, vou lhe parar aí mesmo com alguém que eu espero muito que você saiba quem é:
Talvez tenhamos ficado adultos demais para querer entender os por ques e comos do dia-a-dia, mas hoje vamos considerar a famosa fala do Telekid, personagem do Castelo RaTimBum: “’porque sim’ não é resposta”!
E é exatamente por isso que vamos partir agora para uma análise mais profunda do Git, entendendo não só o que fazemos, mas também por que fazemos. Vamos explorar os conceitos fundamentais que estão por trás dos comandos que usamos todos os dias. Afinal, conhecimento sem entendimento pode atrapalhar mais do que ajudar.
Para começar, vamos primeiro entender a arquitetura básica do Git e como ele realmente funciona nos bastidores. Isso vai nos ajudar a compreender melhor o fluxo de trabalho (ou workflow, que te conto mais sobre daqui a pouco) e por que certos comandos se comportam de maneiras específicas. Depois, vamos mergulhar em cada um daqueles "por ques" que listamos acima, destrinchando cada conceito com exemplos práticos.
Eu não vou te explicar já com um “untracked changes” porque acredito fortemente que isso funciona pra pouquíssimas pessoas. Pode ser que você já tenha visto um diagrama como esse abaixo e até entendeu, mas depois esqueceu tudo.
Imagem reproduzida da web, copiada em 10/04/2025 do link https://ismailgok.medium.com/lets-git-familiar-part-1-5de13a6ad7b5
Pra conseguir simplificar um pouco esse monte de setas, vamo começar imaginando que o nosso repositório git é uma festa, mais especificamente em uma balada. Você, como uma pessoa pontual, chegou cedo e entrou na fila antes dos seus amigos. Nesse momento, você já estava lá, mas a administração da festa não fazia ideia da sua existência; se você fosse embora dali mesmo, nem saberiam que você esteve lá. Como nossa balada não é bagunça, para entrar, é necessário fazer um registro e tirar uma foto rapidinho. Essa foto vai ser salva junto com o seu nome para que saibam quem você é e você vai receber uma pulseirinha com um identificador e seu nome.
Como você sabe que seus amigos já estão na fila, você decidiu esperar ali pelo lobby para entrarem todos juntos. Uma amiga entrou e vocês decidiram ir pra pista e esperar o resto do pessoal lá dentro. Agora você está onde deveria e pode pedir seus drinks sem se preocupar em pagar um por um porque a galera tá ligada em quem você é e consegue rastrear as suas atividades. Você e sua amiga tiram uma foto já com seus drinks e enviam no grupinho, claro que o objetivo principal é fazer uma invejinha pros atrasados, mas a imagem também vai servir para eles saberem se vocês já estão bebendo e onde estão.
Agora, vamo deixar as caipirinhas de lado. Se você já manja do workflow do git, certeza que já entendeu, mas senão, eu te explico. Primeiro, dá uma olhada nesse mesmo diagrama, mas com os nomes corretos das áreas do workflow.
A fila da balada é equivalente ao Working Directory, onde ficam os untracked files e as changes not staged for commit — em tradução livre, "arquivos não rastreados" e "mudanças não preparadas para o commit", respectivamente. Ou seja, é aquele repositório (normalmente local, na que está na sua máquina) onde você vai fazer suas alterações, como criar, editar ou deletar arquivos.
Assim como o pessoal não sabe que você tá lá até o seu check-in, o git também não sabe das suas modificações até você “contar” pra ele. Quando você usa o add
, você está basicamente falando que essa informação está preparada para ser registrada e que ele já pode salvá-la. Usar o commit antes disso seria equivalente a tentar fazer alguém entrar na festa com um lençol cobrindo seus corpo e rosto: o segurança tem que saber quem é aquela pessoa pra entender se ela já existe no sistema ou se precisa ser atualizada, por exemplo.
Seguindo com nossa analogia, agora que o git já sabe que você tá ali, pronto pra entrar, vai ser preciso te identificar. Lembra da pulseirinha que falei antes? Ela é o commit
. O identificador aqui é equivalente ao hash de um commit, que é uma espécie de ID; e o seu nome é equivalente à mensagem (que é obrigatória em cada commit). Se você ainda não sabe por que precisa escrever algo ou até é uma das pessoas que usa -m “”
para deixar a mensagem vazia (POR FAVOR, NÃO SEJA ESSA PESSOA), imagina chegar na balada e falar pro segurança te achar no sistema através do seu identificador “2dfea268sd9454gdfs”. Melhor ainda: se imagina perguntando pra um colega (desses que usam -m “”
) qual commit dele você precisa revisar e ele diz “ah, é um dos que fiz ontem”.
Indo para a próxima área: você já está devidamente fotografado e identificado e chegou ao Lobby, ou Local Repository. Você já tá dentro, pode seguir pra pista, esperar outras pessoas (commits) chegarem para irem justos ou simplesmente ficar ali, afinal ninguém vai te obrigar a entrar, a menos que usem do --force
. Estando no Lobby, você tem duas opções: entrar para a Pista (o git push
para enviar informações para o Remote Repository) ou dar só uma espiadinha para ver se algo mudou desde a última vez que você foi lá (o git fetch
para saber o que mudou, mas sem trazer essas mudanças). Ou seja, nessa “rota” Local Repository ↔ Remote Repository, você pode enviar suas alterações para o Remote ou pedir a ele um spoiler do que mudou, que vai “resumir” pro Local sobre novos commits, novas branches e tags, e até atualizações nas refs.
Por último, diferentemente do fetch
que é só uma espiadinha bem por cima, o pull
vai trazer, de fato, as informações para o Working Directory. É aquela foto que você manda pra galera que tá fora, assim eles conseguem saber o que tá rolando lá dentro.
Confesso que essa parte da analogia ficou meio furada, então para esclarecer a diferença mais efetivamente:
fetch
Baixa as atualizações do repositório remoto e atualiza os ponteiros remotos (origin/branch), mas não modifica sua branch atual nem seus arquivos.pull
Faz umfetch
+merge
(ou rebase) automaticamente: baixa e aplica as atualizações na sua branch atual.
Agora que entendemos melhor o fluxo básico do Git, vamos explorar alguns conceitos mais avançados que são fundamentais para o trabalho em equipe. Mas antes, precisamos falar sobre branches e como elas se encaixam nessa nossa analogia da balada. Afinal, como em qualquer festa boa, às vezes precisamos nos dividir em grupos menores para diferentes atividades.
Imagine que cada branch é como um espaço diferente na balada: enquanto um grupo está na pista de dança principal (nossa branch main), outros podem estar no lounge conversando ou na área do bar. Cada espaço tem seu próprio propósito e ambiente, mas todos fazem parte da mesma festa. E assim como você pode transitar entre esses espaços durante a noite, no Git você pode mudar entre branches conforme necessário.
Usando nossa analogia da balada, quando você faz um git checkout
para uma nova branch, é como se você estivesse se movendo para um outro ambiente da festa. Todas as suas "alterações" (seus drinks, suas fotos, sua pulseirinha) vão com você, mas agora você está em um contexto diferente. E assim como você pode voltar para a pista principal quando quiser, você pode sempre retornar à branch principal com suas alterações quando o trabalho estiver pronto.
Como estamos discutindo o básico, mas também fugindo do básico: por que esse checkout
se existe o git branch
? O que significa aquele -b
? E por que tem gente que usa um tal git switch
? Para explicar sem um parágrafo infinito, vamos usar algo mais visual:
git branch
Lista as branches locais e marca a atual com um *git branch nova-branch
Cria uma branch chamada “nova-branch”git switch nova-branch
Muda para a branch “nova-branch”git checkout nova-branch
Muda para a branch “nova-branch”git checkout -b
Cria uma branch chamada “nova-branch” e muda para ela logo em seguida
Para esse caso, eu vou te contar. Como o git já é um adulto (caminhando para os 20 anos esse ano 🥳), muita coisa mudou. O git checkout
existe desde o nascimento da ferramenta e é um canivete suíço, tem muitos diferentes usos. O git branch
é da mesma época, mas ele não muda entre uma branch e outra, só as gerencia. O switch
entrou nessa dança muito mais recentemente (em 2019) porque o checkout é como um mago poderosíssimo, mas que faz tanta coisa que é difícil explicar pra quem ainda não sabe nem usar o Wingardium Leviosa, não chega a ter a possibilidade furar o olho de alguém como um Leviosá (se você não entendeu, assista/leia Harry Potter o mais rápido possível).
Saindo do mundo da magia e voltando pro mundo onde os código são “automagicamente” (salve, Felipão) versionados, podemos relembrar de uma boa prática bem básica, que você já deve estar cansado de ouvir, é o ‘S’ do tão famoso SOLID: Single responsibility, “responsabilidade única”, em tradução livre. Uma função deve ter somente uma responsabilidade. Imagina precisar dar manutenção em uma function CriaEAlteraBranch()
que cria e altera - ou só altera, se você quiser - uma branch; e também restaura arquivos para como eles eram alguns commits atrás; e que, além disso, também é ótima pra te ajudar a desfazer as alterações que você acabou de fazer. Doideira, né?
Agora, eu espero ter cumprido minha promessa de falar do básico, mas sem falar só o básico. Além de te mostrar um pouco do que acontece “atrás das cortinas” no git, espero que esse artigo também te incentive a perguntar e responder outras dúvidas que você deixou de lado com a justificativa “porque o professor disse que é assim”.
O curso sobre git e Github é muito bom e vai te ajudar a entender várias dessas confusões que eles causam mesmo a quem tem muita prática. Infelizmente, uma aula com tooooodos os mínimos detalhes sobre cada coisinha seria insuportável. Então, se você foi contaminado com minha curiosidade e quiser mergulhar em git, você pode:
- acessar o livro ProGit disponível de forma gratuita e com traduções para vários idiomas (a versão pt-BR infelizmente ainda não tá completa);
- usar o Github Training Kit para conceitos mais básicos em um idioma familiar; ou minha opção preferida (recomendo para quem consegue entender um pouco)
- aproveitar que já está aprendendo um assunto técnico pra dar um super boost no teu inglês porque conhecimento nunca é demais e o inglês pode desbloquear um mundo cheio de oportunidades.
É isso, webamigos. Antes de me despedir, só mais uma provocação: por que no java nós declaramos uma lista como List<String> lista = new ArrayList<String>();
? Por que não List<String> lista = new List<String>();
? Se você já sabe, é proibido soprar pro colega do lado.
Convido vocês a assistirem o curso de git e github se ainda não o fizeram, há também outros cursos avulsos e mentorias que falam sobre. Tenho alguns outros artigos aqui na DIO que você pode ler no meu perfil público. E, caso tenha dúvidas ou encontrou algum erro, sinta-se à vontade para contribuir no chat.
Obrigada por lerem meu post. 💜