Skip to content
Fase 7Controlo de Versões

Git e GitHub

Progresso da fase0%

A carregar…

Até agora, se estragasses um ficheiro, a única solução era lembrares-te (ou não) do que tinha lá antes. O Git resolve isso: guarda o histórico completo de cada alteração ao teu código, permite experimentar sem medo em "ramos" separados, e o GitHub dá-te um sítio na nuvem para guardar e partilhar tudo isso. É, a seguir ao terminal, a ferramenta que mais vais usar todos os dias como programador.

Prompt recomendado para esta fase

Estou na Fase 7 a aprender Git e GitHub — commits, branches, merge, push e pull. Quando eu tiver um erro ou um conflito, ajuda-me primeiro a perceber o estado atual do repositório com git status e git log antes de me dares o comando de correção. Explica sempre o que cada comando de Git vai realmente fazer antes de eu o correr, porque alguns são difíceis de desfazer.

Conteúdos teóricos

4 temas

1. Porque precisamos de controlo de versões

O problema real que o Git resolve, antes de veres um único comando.

Se já tentaste guardar versões de um documento à mão — projeto_final.docx, projeto_final_v2.docx, projeto_final_v2_REAL_final.docx — já sentiste o problema que o Git resolve. Sem uma ferramenta de controlo de versões, três coisas correm mal com o tempo:

  1. Perdes o histórico. Não sabes o que mudou entre versões, nem porquê, nem quando.
  2. Não consegues experimentar em segurança. Se quiseres testar uma ideia arriscada, ou fazes uma cópia manual da pasta toda, ou arriscas estragar o que já funcionava.
  3. Colaborar é um pesadelo. Duas pessoas a editar o mesmo ficheiro ao mesmo tempo, por email ou numa pasta partilhada, acaba quase sempre em versões perdidas ou sobrepostas.

O que o Git faz, em uma frase

O Git guarda, a cada "commit" que fazes, uma fotografia completa do estado do teu projeto — com uma mensagem a explicar o que mudou. Podes voltar a qualquer fotografia anterior, comparar duas fotografias, ou criar "ramos" (branches) onde experimentas ideias sem tocar na versão principal.

Git é diferente do GitHub

Isto confunde muita gente no início: o Git é o programa que corre no teu computador e guarda o histórico localmente. O GitHub é um serviço na internet onde podes guardar uma cópia (remota) desse histórico, partilhá-lo com outros, e colaborar. Podes usar Git sem nunca usar GitHub — mas na prática, quase todos os projetos combinam os dois: Git para o histórico, GitHub para o backup e a colaboração.

2. Git local: init, add, commit

Os três comandos que vais usar em praticamente todos os dias de trabalho.

Iniciar um repositório

bash
git init

Corrido dentro de uma pasta, transforma-a num repositório Git — cria uma pasta escondida .git onde todo o histórico vai ser guardado. Fazes isto uma vez por projeto, no início.

O ciclo de trabalho: status, add, commit

bash
git status

Mostra que ficheiros mudaram desde o último commit, e quais ainda não estão a ser rastreados pelo Git. É o comando que deves correr constantemente — não custa nada e diz-te sempre exatamente onde estás, tal como pwd no terminal (Fase 0).

bash
git add nome-do-ficheiro.js
git add .

git add prepara ficheiros para o próximo commit — chama-se staging. git add . prepara todos os ficheiros alterados na pasta atual de uma vez.

bash
git commit -m "Adiciona validação ao formulário de login"

git commit guarda uma fotografia permanente de tudo o que preparaste com add, junto com uma mensagem que explica o que mudou.

Porque existem dois passos (add e commit)

Parece um passo a mais, mas dá-te controlo: podes ter alterado cinco ficheiros, mas só queres incluir dois neste commit (porque os outros três são de uma funcionalidade diferente e ainda não estão prontos). O add deixa-te escolher exatamente o que entra em cada fotografia.

Mensagens de commit boas

Escreve mensagens curtas, no presente, que descrevam o que mudou: "Adiciona validação ao login", não "fix" ou "alterações". Um histórico com mensagens boas é um dos recursos mais valiosos de um projeto — é o que te permite perceber, meses depois, porque é que uma linha de código específica existe.

Ver o histórico

bash
git log
git log --oneline

git log mostra todos os commits, do mais recente para o mais antigo, com autor, data e mensagem. --oneline comprime cada commit numa única linha — útil para uma visão geral rápida.

primeiro-repositorio.sh
git init
git status

# ... editas ficheiros ...

git add .
git commit -m "Primeiro commit: estrutura inicial do projeto"
git log --oneline
O ciclo completo, do zero ao primeiro commit

3. Branches: trabalhar em paralelo sem medo

Criar uma linha do tempo separada para experimentar, sem arriscares o que já funciona.

Um branch (ramo) é uma linha do tempo independente dentro do mesmo repositório. O branch principal chama-se normalmente main (ou, em projetos mais antigos, master). Sempre que quiseres trabalhar numa funcionalidade nova sem arriscar estragar o que já funciona no main, crias um branch novo.

bash
git branch nova-funcionalidade   # cria o branch
git checkout nova-funcionalidade # muda para ele

# atalho para os dois passos de uma vez:
git checkout -b nova-funcionalidade

Depois de mudares de branch, qualquer commit que fizeres fica só nesse branch — o main continua exatamente como estava. Podes alternar entre branches à vontade com git checkout nome-do-branch.

Juntar o trabalho de volta: merge

Quando a funcionalidade estiver pronta e testada, juntas o branch de volta ao main:

bash
git checkout main
git merge nova-funcionalidade

Isto pega em todos os commits feitos no branch nova-funcionalidade e aplica-os ao main. Se ninguém tiver alterado, entretanto, as mesmas linhas no main, o merge acontece automaticamente. Se houver sobreposição, o Git avisa-te de um conflito — vais aprender a resolver isso no exercício mais difícil desta fase.

Porque isto muda como trabalhas

Sem branches, "experimentar" um código significa arriscar a versão que funciona. Com branches, experimentar é grátis: se a ideia não resultar, simplesmente apagas o branch (git branch -d nome-do-branch) e o main nunca soube que aquilo existiu. É por isto que branches são considerados, a par dos commits, o coração de como o Git muda a forma de trabalhar de um programador.

4. GitHub: backup na nuvem e partilha

Levar o teu repositório local para a internet — histórico seguro e visível por outros.

O GitHub guarda uma cópia do teu repositório num servidor remoto. Isso dá-te três coisas que o Git local sozinho não dá: backup (se o teu computador falhar, o código não desaparece), partilha (outros podem ver, clonar ou contribuir para o teu projeto) e um portefólio público do teu trabalho.

Ligar um repositório local a um remoto

  1. Cria uma conta em github.com e um repositório novo (vazio, sem ficheiros).
  2. No teu projeto local, liga-o ao repositório remoto:
bash
git remote add origin https://github.com/o-teu-utilizador/nome-do-repo.git
git push -u origin main

git remote add origin ... regista o endereço do repositório remoto, com o nome origin (uma convenção, não és obrigado a usar esse nome, mas quase todos usam). git push envia os teus commits locais para o GitHub. O -u origin main na primeira vez liga o teu branch main local ao main remoto, para que os próximos git push sozinhos já saibam para onde enviar.

Trazer alterações de volta: pull e clone

bash
git pull    # traz e junta as alterações mais recentes do remoto
git clone https://github.com/utilizador/repo.git   # copia um repositório inteiro pela primeira vez

Usa git clone quando queres começar a trabalhar num repositório que já existe no GitHub (o teu, ou de outra pessoa) e ainda não tens localmente. Usa git pull num repositório que já clonaste, para atualizares com o que mudou entretanto no remoto (por exemplo, se estiveres a trabalhar em dois computadores diferentes, ou em equipa).

O .gitignore

Nem tudo o que está na tua pasta de projeto deve ir para o Git — pastas geradas automaticamente (node_modules), ficheiros com segredos (chaves de API, passwords) ou ficheiros do teu sistema operativo não devem ser partilhados nem guardados no histórico. Um ficheiro .gitignore, na raiz do projeto, lista padrões de ficheiros a ignorar:

bash
node_modules/
.env
*.log

Cria sempre um .gitignore antes do primeiro commit de um projeto novo — remover algo do Git depois de já o teres enviado ao GitHub é bem mais trabalhoso do que preveni-lo à partida.

Exercícios práticos

4 exercícios
Fácil

Exercício Fácil — O Teu Primeiro Repositório Git

Cria um repositório local, faz três commits distintos, e revê o histórico com git log.

FerramentasGitTerminalVS Code

Objetivo: praticar o ciclo git init, git add, git commit, e ler o histórico.

Passos a realizar

  1. Cria uma pasta diario-de-bordo, e dentro dela corre git init.
  2. Cria um ficheiro README.md com uma frase sobre o objetivo desta pasta. Faz o primeiro commit com uma mensagem clara.
  3. Cria um ficheiro dia-1.md com uma frase sobre o que aprendeste hoje. Faz o segundo commit.
  4. Altera o README.md, acrescentando mais uma frase. Faz o terceiro commit.
  5. Corre git log --oneline e confirma que vês os três commits, na ordem certa, com as tuas mensagens.
  6. Corre git status depois do último commit e confirma que diz que não há alterações por guardar.

Dicas úteis

  • Corre git status antes de cada git add — é o hábito mais útil que podes criar com Git, e não custa nada correr vezes a mais.
  • Uma mensagem de commit no presente e descritiva ("Adiciona README inicial") lê-se muito melhor num histórico do que "update" ou "mudanças".

Erros comuns

  • Esquecer git add antes de git commit, o que faz o Git dizer que não há nada para gravar.
  • Fazer um único commit gigante com tudo em vez de três commits separados, perdendo a prática de dividir o trabalho em passos com sentido.

As minhas dúvidas

Médio

Exercício Médio — Criar um Branch, Trabalhar Nele e Fazer Merge

Pratica o fluxo completo: criar um branch, fazer alterações isoladas, e juntá-las de volta ao main.

FerramentasGitTerminalVS Code

Objetivo: sentir na prática porque é que branches dão confiança para experimentar.

Passos a realizar

  1. No mesmo repositório diario-de-bordo (ou um novo), confirma que estás no branch main com git branch (o branch atual aparece marcado com um asterisco).
  2. Cria e muda para um novo branch chamado nova-secao com git checkout -b nova-secao.
  3. Cria um ficheiro ideias.md com uma lista de três ideias de projetos que gostarias de construir. Faz commit desta alteração, ainda dentro do branch nova-secao.
  4. Muda de volta para main com git checkout main, e confirma com ls (ou dir) que o ficheiro ideias.md não existe aqui — está isolado no outro branch.
  5. Faz o merge: git merge nova-secao, ainda estando no main.
  6. Confirma que o ficheiro ideias.md agora existe também no main, e que git log --oneline mostra o histórico combinado dos dois branches.

Fluxo de funcionamento

  1. 1main
  2. 2checkout -b nova-secao
  3. 3commits isolados no branch
  4. 4merge de volta ao main

Dicas úteis

  • git branch (sem argumentos) mostra sempre em que branch estás — usa-o sempre que não tiveres a certeza.
  • O ficheiro só "não existir" no main é o próprio Git a mostrar-te que os dois branches são histórias independentes até fazeres o merge.

Erros comuns

  • Fazer commits diretamente no main por esquecimento, em vez de mudar primeiro para o branch novo.
  • Tentar fazer merge estando ainda dentro do branch nova-secao, em vez de voltar primeiro para main — o merge junta o branch indicado ao branch onde estás, não ao contrário.

As minhas dúvidas

Médio

Exercício Médio — Publicar o Teu Repositório no GitHub

Cria uma conta no GitHub, publica o repositório local, e clona-o numa pasta diferente para simular outro computador.

FerramentasGitGitHubTerminal

Objetivo: fechar o ciclo local → remoto → local, exatamente como acontece em equipas reais.

Passos a realizar

  1. Cria uma conta gratuita em github.com, se ainda não tiveres uma.
  2. Cria um novo repositório vazio no GitHub (sem README, sem .gitignore — vazio de propósito, para não entrar em conflito com o teu histórico local).
  3. No teu repositório diario-de-bordo local, adiciona um ficheiro .gitignore com pelo menos node_modules/ e *.log, e faz commit dele.
  4. Liga o repositório local ao remoto com git remote add origin, usando o endereço que o GitHub te deu, e envia tudo com git push -u origin main.
  5. Atualiza a página do repositório no GitHub e confirma que vês todos os teus ficheiros e o histórico de commits.
  6. Numa pasta completamente diferente do teu computador, corre git clone com o mesmo endereço, para simulares "outro computador" a obter o projeto pela primeira vez, e confirma que todos os ficheiros e o histórico vieram junto.

Fluxo de funcionamento

  1. 1git remote add origin
  2. 2git push -u origin main
  3. 3Repositório visível no GitHub
  4. 4git clone noutra pasta

Dicas úteis

  • Um repositório remoto criado vazio (sem README nem .gitignore automáticos) evita o problema mais comum de principiante: histórico local e remoto que "não batem certo" logo no primeiro push.
  • git clone traz sempre o histórico completo, não só os ficheiros atuais — é uma cópia integral do repositório, incluindo todos os commits anteriores.

Erros comuns

  • Criar o repositório no GitHub já com um README, o que faz o primeiro git push falhar por os históricos serem diferentes.
  • Esquecer o .gitignore antes do primeiro push, enviando pastas como node_modules para o GitHub desnecessariamente.

As minhas dúvidas

Difícil

Exercício Difícil — Provocar e Resolver um Conflito de Merge

Cria de propósito um conflito entre dois branches, e resolve-o manualmente, linha a linha.

FerramentasGitVS CodeTerminal

Um conflito de merge acontece quando dois branches alteram a mesma linha do mesmo ficheiro de forma diferente, e o Git não consegue decidir sozinho qual versão manter. Este exercício provoca esse cenário de propósito, num ambiente seguro, para não teres medo dele da primeira vez que acontecer a sério.

Passos a realizar

  1. No repositório diario-de-bordo, garante que estás no main, e que o ficheiro README.md tem pelo menos uma linha de texto simples (ex: "Estado: em progresso").
  2. Cria um branch chamado ajuste-a, muda para ele, altera essa linha do README.md para "Estado: quase terminado", e faz commit.
  3. Volta ao main (git checkout main) e cria um segundo branch, ajuste-b, a partir daqui — ou seja, ajuste-b não tem a alteração do ajuste-a. Altera a mesma linha do README.md para "Estado: em revisão", e faz commit.
  4. Volta ao main e faz merge de ajuste-a primeiro — deve funcionar sem problemas.
  5. Agora tenta fazer merge de ajuste-b. O Git vai avisar-te de um conflito nesse ficheiro.
  6. Abre o README.md no VS Code — vais ver marcadores especiais (<<<<<<<, =======, >>>>>>>) a mostrar as duas versões em conflito. Edita o ficheiro manualmente para decidir o texto final (podes escolher uma das duas versões, ou escrever uma terceira), remove os marcadores, guarda, e completa o merge com git add README.md seguido de git commit.

Fluxo de funcionamento

  1. 1ajuste-a e ajuste-b alteram a mesma linha
  2. 2merge de ajuste-a: sem problema
  3. 3merge de ajuste-b: CONFLITO
  4. 4Editar, remover marcadores, add + commit

Dicas úteis

  • Um conflito não é um erro que quebrou algo — é o Git a pedir-te, com razão, uma decisão que só um humano consegue tomar. Lê-o com calma, sem entrar em pânico.
  • Depois de resolveres um conflito, confirma sempre com git log --oneline --graph que o histórico ficou como esperavas — vais ver os dois branches a juntarem-se visualmente.

Erros comuns

  • Esquecer de remover os marcadores <<<<<<< / ======= / >>>>>>> antes de guardar, deixando-os literalmente no ficheiro final.
  • Entrar em pânico e cancelar o merge com git merge --abort sem sequer tentar perceber o conflito — é uma opção válida em código real complexo, mas neste exercício o objetivo é praticar a resolução.

As minhas dúvidas