Partilhar: Classroom Teams WhatsApp
aulify · Sebenta
UC · Unidade de Competência · UC00617

Utilizar serviços Git e GitHub

Do primeiro commit à colaboração em repositórios remotos, com tags, branches e resolução de conflitos
25h · 2.25 pontos crédito Curso: T. Desenv. Software, T. Inform. Gestão ↗ Referencial oficial SNQ
Índice

Há um pacote premium desta unidade: um PowerPoint editável de 100 ou mais diapositivos, um manual em PDF e dois testes com correção. Esta sebenta continua gratuita.

Introdução

Qualquer projeto de software, por pequeno que seja, muda ao longo do tempo: uma função é reescrita, uma página é redesenhada, um erro é corrigido, uma colega acrescenta uma funcionalidade. Quem não regista estas mudanças acaba com pastas cheias de cópias e sem saber qual é a boa. O Git resolve este problema: é um sistema de controlo de versões que guarda o historial de um projeto, permite voltar atrás e deixa várias pessoas trabalhar em paralelo sem se atropelarem. O GitHub é a plataforma na Internet onde esses projetos ficam alojados, partilhados e discutidos.

Esta sebenta cobre a UC00617 passo a passo, seguindo as três realizações do referencial: instalar o Git, criar e configurar uma conta na plataforma GitHub e criar e gerir repositórios. O percurso é este: primeiro percebemos o que é o controlo de versões e como se instala e configura o Git; depois aprendemos a trabalhar num repositório local (commits, histórico, desfazer, tags); a seguir estudamos branches, merge e conflitos; passamos ao cliente gráfico; criamos a conta e a página pessoal no GitHub; ligamos o repositório local ao remoto; e fechamos com a colaboração (forks, pull requests, revisão de código), o workflow profissional e as normas que se aplicam ao trabalho com código e dados.

Objetivos de aprendizagem (referencial): instalar o Git; criar e configurar uma conta no GitHub; criar e gerir repositórios locais e remotos; usar comandos de terminal e um cliente gráfico; analisar e editar o histórico de commits; aplicar e gerir tags; utilizar branches e resolver conflitos localmente e no GitHub; colaborar e contribuir em repositórios; cumprir as normas e regulamentos aplicáveis.

Como estudar com esta sebenta. Cada capítulo tem explicação, tabelas de consulta e exemplos resolvidos passo a passo. Faz sempre os comandos num repositório de treino, na tua máquina, antes de ler o resultado: o Git aprende-se a errar num sítio onde errar não custa nada. Os blocos de código mostram o que escreves no terminal; as linhas que começam por # são comentários, não precisas de as escrever.

1. Controlo de versões

1.1 O problema sem controlo de versões

Imagina uma equipa de três formandos a construir um site. Cada um trabalha numa cópia da pasta e envia ficheiros por correio eletrónico. Ao fim de duas semanas a pasta tem este aspeto:

site/
  index.html
  index_v2.html
  index_v3_FINAL.html
  index_v3_FINAL_corrigido.html
  index_FINAL_mesmo.html
  index_usar_este.html

As perguntas que ninguém consegue responder sem abrir os ficheiros um a um são sempre as mesmas:

1.2 O que é um sistema de controlo de versões

Um sistema de controlo de versões (VCS, de Version Control System) regista cada alteração feita aos ficheiros de um projeto, com a data, o autor e uma justificação. Em vez de guardar cópias com nomes diferentes, guarda uma sequência ordenada de estados, que se podem consultar, comparar e restaurar.

Modelo Exemplos Como funciona Limitação principal
Local RCS Cópias de versões na própria máquina Não serve para trabalho em equipa
Centralizado CVS, Subversion Um servidor central guarda o historial; cada pessoa descarrega uma versão Sem servidor não se grava historial; offline fica-se limitado
Distribuído Git, Mercurial Cada pessoa tem uma cópia completa do historial Exige perceber o conceito de repositório local e remoto

No modelo distribuído, o repositório de cada pessoa é completo: contém todos os commits desde o início. Por isso quase tudo no Git é instantâneo e funciona sem rede. A rede só é precisa quando se envia ou recebe trabalho de outro repositório.

1.3 Porquê o Git

O Git foi criado por Linus Torvalds em 2005 para gerir o desenvolvimento do núcleo do Linux. Hoje é a ferramenta dominante em desenvolvimento de software e a que se espera que um técnico domine. As razões:

1.4 Terminologia essencial

Termo Significado
Repositório (repo) Pasta de projeto acompanhada pelo Git, com o historial na subpasta oculta .git
Diretório de trabalho Os ficheiros que vês e editas
Área de preparação (staging area, index) Onde se escolhe o que vai entrar no próximo commit
Commit Instantâneo do projeto, com autor, data e mensagem
Branch Linha de desenvolvimento com nome, que aponta para um commit
HEAD Ponteiro para o ponto onde estás neste momento, normalmente o último commit da branch atual
Remote Repositório noutro sítio (por exemplo no GitHub) com que sincronizas
origin Nome habitual do remote principal
Clone Cópia completa de um repositório remoto para a tua máquina
Push Enviar commits locais para o remoto
Pull Receber commits do remoto e integrá-los (fetch mais merge)
Fetch Receber commits do remoto sem os integrar
Merge Juntar o trabalho de duas branches
Conflito Duas alterações incompatíveis na mesma zona de um ficheiro
Tag Etiqueta fixa num commit, usada para marcar versões

Exemplo resolvido · de seis ficheiros a um só

Voltando à pasta site/ do início, vejamos como o Git elimina o problema.

  1. Mantém-se um ficheiro index.html e cria-se o repositório com git init.
  2. Cada versão com sentido passa a ser um commit: git commit -m "Adiciona cabeçalho", depois git commit -m "Corrige ligação do menu", e assim por diante.
  3. Para ver o que mudou entre o segundo e o terceiro estado, usa-se git diff entre os dois commits, em vez de abrir ficheiros.
  4. Para voltar a um estado antigo, regressa-se ao commit correspondente, sem ficheiros espalhados.
  5. Duas pessoas editam em branches separadas e juntam-se no fim com git merge.

Conclusão: o nome do ficheiro deixa de transportar a informação da versão. Essa informação passa a estar no historial.

2. Instalar e configurar o Git

2.1 Instalação

A instalação é a primeira realização do referencial. Segue sempre as instruções oficiais em git-scm.com, porque os instaladores mudam de aspeto, mas o objetivo é o mesmo: ter o comando git disponível no terminal.

Sistema Como instalar Notas
Windows Transferir o instalador "Git for Windows" em git-scm.com Inclui o Git Bash, um terminal com os comandos habituais de Linux, e o gestor de credenciais
macOS brew install git (com o Homebrew) ou instalar as ferramentas de linha de comandos da Apple Ao escrever git num Mac novo, o sistema oferece a instalação
Debian e Ubuntu sudo apt install git O pacote pode não ser a versão mais recente
Fedora sudo dnf install git

Para confirmar que ficou instalado:

git --version
# git version 2.x.y

Se aparecer "comando não encontrado" (ou "não é reconhecido como um comando interno ou externo", no Windows), fecha e volta a abrir o terminal: o terminal já aberto não conhece o programa acabado de instalar.

No Windows, o instalador faz perguntas. As que mais importam a quem começa: aceitar o editor sugerido (ou escolher o Visual Studio Code, se o tiveres), deixar o Git no PATH (para o comando funcionar também fora do Git Bash) e usar o nome de branch inicial main.

2.2 Configuração inicial

Há três níveis de configuração, do mais geral para o mais específico:

Nível Opção Onde fica Âmbito
Sistema --system Ficheiro do sistema Todos os utilizadores da máquina
Utilizador --global Ficheiro na tua pasta pessoal Todos os teus repositórios
Repositório (nenhuma) .git/config Só esse repositório

O nível mais específico prevalece sobre o mais geral. A configuração mínima, feita uma vez por máquina, é a identidade:

git config --global user.name "Joana Ferreira"
git config --global user.email "joana.ferreira@exemplo.pt"

Estes dois valores ficam gravados em todos os commits que fizeres e fazem parte do historial. Se usares o mesmo email da tua conta GitHub, a plataforma associa os commits ao teu perfil.

Outras definições úteis:

# Nome da branch inicial em repositórios novos
git config --global init.defaultBranch main

# O git pull faz merge quando os dois lados têm commits novos
git config --global pull.rebase false

# Editor usado nas mensagens de commit mais longas
git config --global core.editor "code --wait"

# Cores no terminal
git config --global color.ui auto

# Ver tudo o que está definido e de onde vem
git config --list --show-origin

Para um repositório específico (por exemplo, um projeto da escola com o email da escola), corre git config user.email "..." sem --global, dentro da pasta do repositório.

2.3 Ajuda integrada

O Git traz a documentação consigo, e interpretar manuais e guiões técnicos é uma aptidão do referencial:

git help commit      # abre o manual completo do comando
git commit -h        # resumo curto das opções

No manual, a secção SYNOPSIS mostra a sintaxe (o que é obrigatório e o que é opcional, entre parênteses retos) e a secção OPTIONS explica cada opção. A documentação oficial também está em git-scm.com/docs.

Exemplo resolvido · primeira configuração e verificação

Situação. Instalaste o Git num computador da escola. Queres que os teus commits fiquem com o teu nome e o email da escola, mas só neste projeto.

  1. Verifica a instalação: git --version.
  2. Cria a pasta e o repositório: mkdir treino, cd treino, git init.
  3. Define a identidade só para este repositório: git config user.name "Joana Ferreira" e git config user.email "joana@escola.exemplo.pt".
  4. Confirma: git config user.email devolve joana@escola.exemplo.pt.
  5. Confirma a origem: git config --list --show-origin mostra a linha de user.email com o ficheiro .git/config, prova de que a definição vale só neste repositório.

Resultado: noutros repositórios da máquina, continua a valer a identidade --global.

3. Repositórios locais e commits

3.1 Criar ou clonar um repositório

Há duas maneiras de ter um repositório local.

Começar do zero, dentro de uma pasta:

mkdir meu-projeto
cd meu-projeto
git init

O comando cria a pasta oculta .git, onde o Git guarda tudo. Se a apagares, perdes o historial (os ficheiros ficam, mas deixam de estar versionados).

Clonar um repositório existente:

git clone https://github.com/utilizador/repositorio.git
cd repositorio

O clone traz o historial completo e já deixa configurado o remote origin, que aponta para o endereço de onde clonaste.

3.2 As três áreas do Git

Perceber isto é perceber o Git. Um ficheiro passa por três sítios:

 Diretório de trabalho  --git add-->  Área de preparação  --git commit-->  Repositório (.git)
Área O que contém Como lá se chega
Diretório de trabalho Os ficheiros como estão agora Editas
Área de preparação (staging) O que vai entrar no próximo commit git add
Repositório Os commits gravados git commit

A área de preparação existe para que possas escolher o que entra em cada commit. Se alteraste cinco ficheiros mas só dois pertencem à mesma tarefa, preparas esses dois, gravas, e tratas dos outros num segundo commit.

3.3 Ver o estado

git status

Cada ficheiro aparece num de quatro estados:

Estado Significado
Untracked Ficheiro novo que o Git ainda não acompanha
Modified Ficheiro acompanhado, alterado desde o último commit
Staged Ficheiro preparado para o próximo commit
Committed Já gravado no historial

O git status diz também em que branch estás e sugere o comando seguinte. Corre-o sempre antes e depois de cada operação: é o comando que mais evita enganos.

3.4 Preparar e gravar

git add index.html              # um ficheiro
git add index.html style.css    # vários
git add src/                    # uma pasta
git add .                       # tudo o que mudou na pasta atual e abaixo
git add -p                      # escolher blocos (hunks) de alterações
git commit -m "Adiciona página inicial"   # gravar com mensagem
git commit                                # abre o editor para mensagem longa
git commit -am "Corrige título"           # prepara e grava ficheiros já acompanhados

O -a só apanha ficheiros que o Git já acompanha; ficheiros novos têm de passar primeiro por git add.

Uma boa mensagem diz o que o commit faz, e começa por um verbo. Em português usam-se duas formas: a que completa a frase "este commit..." ("Adiciona", "Corrige", "Remove") e o infinitivo ("Adicionar", "Corrigir", "Remover"). As duas são aceites; escolhe uma e usa-a em todo o projeto. A secção 12.1 detalha uma convenção.

3.5 Consultar o historial

git log                          # historial completo
git log --oneline                # uma linha por commit
git log --oneline --graph --all  # com o desenho das branches
git log -p                       # com as alterações de cada commit
git log --stat                   # com a lista de ficheiros alterados
git log --author="Joana"         # filtrar por autor
git log --since="2026-01-01"     # filtrar por data
git log --grep="menu"            # filtrar pela mensagem
git show abc1234                 # um commit em pormenor
git blame index.html             # quem alterou cada linha, e quando

Cada commit tem um identificador de 40 caracteres hexadecimais (o hash); normalmente bastam os primeiros 7, como abc1234.

3.6 Ver diferenças

git diff                   # diretório de trabalho contra a área de preparação
git diff --staged          # área de preparação contra o último commit
git diff abc1234 def5678   # entre dois commits
git diff main feature/menu # entre duas branches

Num diff, as linhas com - foram removidas e as linhas com + foram acrescentadas.

3.7 O ficheiro .gitignore

Há ficheiros que não devem ser versionados: dependências instaladas, ficheiros gerados, configurações do editor e, sobretudo, segredos. Lista-os no .gitignore, na raiz do projeto:

# Dependências
node_modules/
venv/

# Gerados
dist/
build/
*.pyc

# Editor e sistema
.vscode/
.idea/
.DS_Store
Thumbs.db

# Registos
*.log

# Configurações sensíveis
.env
*.key
*.pem

Regras de padrão: * substitui qualquer sequência de caracteres, uma barra no fim indica pasta, # inicia comentário e ! anula uma regra anterior. O .gitignore só impede ficheiros ainda não acompanhados: se um ficheiro já foi gravado num commit, ignorá-lo depois exige git rm --cached ficheiro para o deixar de acompanhar. O GitHub mantém modelos prontos para cada linguagem em github.com/github/gitignore.

Exemplo resolvido · primeiro repositório, passo a passo

Objetivo. Criar o repositório meu-site, gravar dois commits e consultar o historial.

mkdir meu-site
cd meu-site
git init

Saída: Initialized empty Git repository in .../meu-site/.git/.

  1. Cria index.html com um título e style.css vazio. Corre git status: os dois aparecem em Untracked files.
  2. git add index.html style.css. O git status mostra agora "Changes to be committed" com os dois ficheiros.
  3. git commit -m "Cria estrutura inicial do site". O Git responde com o resumo, por exemplo "2 files changed".
  4. Edita style.css e acrescenta uma regra. O git status mostra style.css como modified. O git diff mostra as linhas novas com +.
  5. git commit -am "Define cor de fundo". Como o ficheiro já era acompanhado, o -a basta.
  6. git log --oneline mostra duas linhas, a mais recente em cima:
e41c9d2 Define cor de fundo
7ab03f1 Cria estrutura inicial do site

Verificação: git status termina com "nothing to commit, working tree clean", sinal de que não há trabalho por gravar.

4. Desfazer e editar o histórico

Errar é normal; o Git tem uma ferramenta para cada tipo de erro. A pergunta a fazer é: onde está o erro? (no diretório de trabalho, na área de preparação ou num commit) e o commit já foi publicado?

4.1 Erros antes do commit

# Descartar alterações de um ficheiro (perde-as!)
git restore index.html

# Tirar um ficheiro da área de preparação, mantendo as alterações
git restore --staged index.html

Em versões mais antigas do Git, os equivalentes são git checkout -- ficheiro e git reset HEAD ficheiro. O git restore existe desde a versão 2.23.

O git restore ficheiro é irreversível: as alterações nunca foram gravadas, por isso o Git não as consegue devolver.

4.2 Corrigir o último commit

git commit --amend -m "Mensagem corrigida"

Para acrescentar um ficheiro esquecido ao último commit: git add ficheiro e depois git commit --amend --no-edit. O --amend substitui o último commit por um novo, com outro hash. Só o uses em commits que ainda não enviaste.

4.3 Reset e revert

Comando O que faz Seguro em commits publicados?
git reset --soft HEAD~1 Desfaz o último commit; as alterações ficam preparadas Não
git reset HEAD~1 (mixed) Desfaz o último commit; as alterações ficam no diretório de trabalho Não
git reset --hard HEAD~1 Desfaz o último commit e apaga as alterações Não
git revert abc1234 Cria um commit novo que anula o abc1234 Sim

HEAD~1 significa "o commit anterior ao atual". A regra de decisão: se o commit só existe na tua máquina, reset é aceitável; se já foi enviado e outras pessoas o podem ter recebido, usa revert, que acrescenta historial em vez de o reescrever.

4.4 Editar o historial com rebase interativo

Antes de partilhar uma branch, podes arrumar os commits:

git rebase -i HEAD~3

O Git abre uma lista dos últimos três commits, cada um com uma palavra de comando:

Comando Efeito
pick Manter o commit como está
reword Manter o commit, mudar a mensagem
squash Fundir com o commit anterior, juntando as mensagens
fixup Fundir com o anterior, descartando a mensagem
drop Eliminar o commit

Também se pode alterar a ordem das linhas para reordenar commits. O rebase interativo reescreve o historial, por isso aplica-se apenas a commits não publicados.

4.5 Guardar trabalho a meio: stash

Se estás a meio de uma tarefa e tens de mudar de branch sem gravar um commit incompleto:

git stash          # guarda as alterações e deixa o diretório limpo
git stash list     # ver o que está guardado
git stash pop      # voltar a aplicar a última e removê-la da lista

4.6 Aplicar um só commit noutra branch: cherry-pick

git switch main
git cherry-pick abc1234

Copia o efeito do commit abc1234 para a branch atual, como um commit novo. É útil para levar uma correção urgente para outra linha de trabalho.

4.7 O reflog, a rede de segurança

O Git regista todos os movimentos do HEAD:

git reflog
# e41c9d2 HEAD@{0}: commit: Define cor de fundo
# 7ab03f1 HEAD@{1}: commit (initial): Cria estrutura inicial do site

Se fizeste um reset --hard por engano a um commit já gravado, o git reflog mostra o hash de onde vinhas, e git reset --hard HEAD@{1} (ou o hash) devolve-te lá. O reflog é local e os registos expiram ao fim de algum tempo, por isso age depressa. Só salva o que chegou a ser gravado num commit.

Exemplo resolvido · limpar três commits antes de partilhar

Situação. Numa branch local fizeste três commits: "Adiciona formulário", "wip" e "corrige gralha no formulário". Vais partilhar a branch e queres um historial limpo.

  1. git log --oneline mostra os três commits.
  2. git rebase -i HEAD~3 abre a lista.
  3. Mantém pick na primeira linha; muda wip e a "gralha" para fixup, para se fundirem ao primeiro.
  4. Guarda e fecha o editor.
  5. git log --oneline mostra agora um commit: "Adiciona formulário".

Verificação: git status limpo e o conteúdo do ficheiro igual ao anterior; só o historial ficou mais arrumado.

Exemplo resolvido · recuperar de um reset --hard

Situação. Gravaste um commit "Adiciona rodapé" e, sem querer, correste git reset --hard HEAD~1. O rodapé desapareceu.

  1. git reflog lista os movimentos; a linha HEAD@{1} corresponde ao commit "Adiciona rodapé" (hash c8d21aa, por exemplo).
  2. git reset --hard c8d21aa repõe a branch nesse commit.
  3. git log --oneline mostra o commit de volta.

Lição: o Git perdoa o que foi gravado; não perdoa o que nunca saiu do diretório de trabalho.

5. Tags

5.1 O que são

Uma tag é uma etiqueta que fixa um nome num commit específico. Ao contrário de uma branch, não anda: aponta sempre para o mesmo commit. Usa-se para marcar versões publicadas: v1.0.0, v1.1.0.

5.2 Tags leves e anotadas

Tipo Comando O que guarda Quando usar
Leve git tag v1.0.0 Apenas o nome, a apontar para o commit Marcas temporárias e pessoais
Anotada git tag -a v1.0.0 -m "Primeira versão estável" Nome, autor, data e mensagem Versões que se publicam

Para versões partilhadas, a documentação do Git recomenda tags anotadas.

5.3 Comandos

git tag                          # listar
git tag -a v1.0.0 -m "Versão 1.0.0"   # criar anotada no commit atual
git tag -a v0.9.0 abc1234 -m "Versão beta"   # criar num commit antigo
git show v1.0.0                  # ver a tag e o commit
git push origin v1.0.0           # enviar uma tag
git push origin --tags           # enviar todas as tags
git tag -d v0.9.0                # apagar localmente
git push origin --delete v0.9.0  # apagar no remoto
git switch --detach v1.0.0       # ver o projeto como estava nessa versão

O git push normal não envia tags: é preciso enviá-las explicitamente.

5.4 Numeração de versões

A convenção mais usada é a versão semântica, no formato MAIOR.MENOR.CORREÇÃO:

Parte Quando sobe Exemplo
MAIOR Mudança incompatível com o que existia 1.4.2 passa a 2.0.0
MENOR Funcionalidade nova compatível 1.4.2 passa a 1.5.0
CORREÇÃO Correção de erro compatível 1.4.2 passa a 1.4.3

No GitHub, uma tag pode ser transformada numa release, com notas de versão e ficheiros anexos, a partir do separador Releases do repositório.

Exemplo resolvido · marcar e publicar a versão 1.0.0

Situação. O meu-site está pronto e já tem remote origin. Queres marcar a versão 1.0.0.

  1. Confirma que estás no commit certo: git switch main, git pull, git log --oneline -3.
  2. git tag -a v1.0.0 -m "Primeira versão publicada".
  3. git show v1.0.0 confirma o autor, a data e o commit.
  4. git push origin v1.0.0 envia a tag.
  5. No GitHub, o separador Releases permite criar a release a partir da tag, com as notas.

Mais tarde, depois de uma correção, a próxima tag será v1.0.1.

6. Branches e merge

6.1 Conceito

Uma branch é uma linha paralela de desenvolvimento. Tecnicamente é só um ponteiro com nome, que aponta para um commit; por isso criar uma branch é instantâneo e não copia ficheiros. Permite experimentar uma funcionalidade sem mexer na linha principal.

main:     A---B---C---------M
                   \       /
feature/menu:       D---E---

O main é a branch principal por convenção (em repositórios mais antigos chama-se master). O HEAD indica em que branch estás.

6.2 Operações básicas

git branch                    # listar branches locais (a atual leva *)
git branch -a                 # incluir as remotas
git branch feature/menu       # criar (sem mudar)
git switch feature/menu       # mudar para ela
git switch -c feature/menu    # criar e mudar de uma vez
git branch -m novo-nome       # renomear a atual
git branch -d feature/menu    # apagar (só se já foi integrada)
git branch -D feature/menu    # apagar mesmo sem integração (perde commits)

O git checkout faz o mesmo que o git switch (e mais coisas); em materiais mais antigos encontras git checkout -b nome com o sentido de git switch -c nome. O git switch existe desde a versão 2.23.

Antes de mudar de branch, o Git exige que o diretório de trabalho não tenha alterações que colidam com a branch de destino. Se tiveres trabalho a meio, grava um commit ou usa o git stash.

6.3 Merge

Para trazer o trabalho de uma branch para outra, vai-se para a branch de destino e funde-se a de origem:

git switch main
git merge feature/menu
git branch -d feature/menu

Há dois tipos de merge.

Fast-forward: a branch de destino não avançou desde que a outra nasceu. O Git só tem de avançar o ponteiro e o historial fica linear.

Antes:   main:  A---B---C
                         \
         feature:         D---E

Depois:  main:  A---B---C---D---E

Merge de três vias: as duas branches têm commits novos. O Git cria um commit de merge, com dois pais.

Antes:   main:  A---B---C---D
                     \
         feature:     E---F

Depois:  main:  A---B---C---D---M
                     \         /
         feature:     E---F---

Para obrigar a existir sempre commit de merge, mesmo quando um fast-forward seria possível, usa-se git merge --no-ff.

6.4 Merge ou rebase

O rebase refaz os commits da tua branch como se tivessem nascido a partir do ponto mais recente da outra:

git switch feature/menu
git rebase main
Antes:   main:  A---B---C---D
                     \
         feature:     E---F

Depois:  main:  A---B---C---D
                             \
         feature:             E'---F'
Merge Rebase
Historial Fiel ao que aconteceu, com commits de merge Linear e limpo
Reescreve commits Não Sim (E e F passam a E' e F', com outros hashes)
Seguro em branches partilhadas Sim Não

Regra de ouro: nunca faças rebase de commits que já enviaste para o remoto e que outras pessoas possam ter recebido. Rebase para organizar o teu trabalho local; merge para integrar o trabalho partilhado.

6.5 Estratégias de branching

Estratégia Branches Quando faz sentido
Git Flow main, develop, feature/*, release/*, hotfix/* Produtos com versões lançadas em datas fixas
GitHub Flow main sempre pronta a publicar, mais branches curtas por tarefa Equipas pequenas, entrega contínua; é a usada neste curso
Trunk-based Quase só main, com branches de horas Equipas maduras com testes automáticos fortes

A documentação do GitHub descreve o GitHub Flow em seis passos: criar uma branch, fazer alterações (commits e envio para o GitHub), criar um pull request, tratar os comentários da revisão, fazer merge do pull request e apagar a branch.

6.6 Nomes de branches

Nomes claros dizem o que lá está. Usa um prefixo de tipo e palavras em minúsculas separadas por hífen:

Prefixo Uso Exemplo
feature/ Funcionalidade nova feature/formulario-contacto
fix/ Correção de erro fix/menu-mobile
docs/ Documentação docs/readme-instalacao
chore/ Manutenção chore/atualiza-dependencias

Evita nomes vagos como teste, nova ou branch1.

Exemplo resolvido · criar, trabalhar e integrar uma branch

Situação. No meu-site, queres acrescentar uma página de contactos sem arriscar a versão estável.

  1. git switch main e git status limpo.
  2. git switch -c feature/contactos. O git branch mostra * feature/contactos.
  3. Cria contactos.html, git add contactos.html, git commit -m "Adiciona página de contactos".
  4. Altera o menu em index.html e grava git commit -am "Liga o menu à página de contactos".
  5. git log --oneline --graph --all mostra os dois commits novos numa linha que se afasta do main.
  6. git switch main e git merge feature/contactos. Como o main não avançou, é um fast-forward.
  7. git branch -d feature/contactos apaga a branch, que já cumpriu o papel.

Verificação: git log --oneline em main mostra agora os dois commits, e contactos.html existe na pasta.

7. Resolução de conflitos

7.1 Quando acontecem

Um conflito acontece quando duas branches alteram a mesma zona do mesmo ficheiro de maneira diferente (ou quando uma apaga um ficheiro que a outra alterou). O Git não decide por ti. Se as alterações forem em zonas diferentes, junta-as sozinho.

git merge feature/titulo
# Auto-merging index.html
# CONFLICT (content): Merge conflict in index.html
# Automatic merge failed; fix conflicts and then commit the result.

O git status passa a mostrar both modified: index.html em "Unmerged paths".

7.2 Anatomia de um conflito

O Git escreve marcadores dentro do ficheiro:

<<<<<<< HEAD
<h1>Bem-vindo ao meu site</h1>
=======
<h1>O meu portefólio</h1>
>>>>>>> feature/titulo
Marcador Significado
<<<<<<< HEAD Início da versão da branch em que estás (o destino do merge)
======= Separador entre as duas versões
>>>>>>> feature/titulo Fim da versão que vem da branch que estás a fundir

7.3 Resolver localmente, passo a passo

  1. git status para ver quais os ficheiros em conflito.
  2. Abre cada ficheiro e decide: ficar com uma versão, com a outra, ou escrever uma combinação.
  3. Apaga os três marcadores. Um ficheiro com marcadores esquecidos fica estragado.
  4. git add ficheiro marca o conflito como resolvido.
  5. git commit conclui o merge (o editor traz uma mensagem de merge pronta).
  6. Confirma que o projeto funciona e corre os testes, se existirem.

Atalhos para quando queres ficar com um dos lados inteiro:

git checkout --ours index.html     # ficar com a versão da branch atual
git checkout --theirs index.html   # ficar com a versão da outra branch
git merge --abort                  # desistir e voltar ao estado anterior ao merge

7.4 Resolver na plataforma GitHub

Quando um pull request tem conflitos com a branch de destino, o GitHub mostra o aviso "This branch has conflicts that must be resolved" e o botão Resolve conflicts, que abre um editor no navegador:

  1. Clica em Resolve conflicts.
  2. O editor mostra os mesmos marcadores <<<<<<<, ======= e >>>>>>>; edita o texto final e apaga os marcadores.
  3. Clica em Mark as resolved para cada ficheiro.
  4. Clica em Commit merge. O pull request fica atualizado.

O editor web serve para conflitos simples. Se o conflito for complexo, ou se precisares de correr o projeto para o testar, resolve localmente: faz merge da branch de destino na tua branch, resolve, e envia.

7.5 Ferramentas visuais

O Visual Studio Code mostra sobre cada conflito as ações Accept Current Change, Accept Incoming Change, Accept Both Changes e Compare Changes. Existem ainda ferramentas dedicadas, como o Meld. Servem para decidir mais depressa, mas a decisão continua a ser tua: aceitar "ambos" sem ler pode deixar código duplicado ou incoerente.

7.6 Prevenir conflitos

Exemplo resolvido · dois títulos para a mesma página

Situação. No main, um colega mudou o título de index.html para "Bem-vindo ao meu site". Noutra branch, feature/titulo, outro colega mudou a mesma linha para "O meu portefólio". Vais fundir feature/titulo em main.

  1. git switch main e git merge feature/titulo. O Git responde CONFLICT (content): Merge conflict in index.html.
  2. git status lista index.html em "Unmerged paths".
  3. Abres o ficheiro e vês os dois blocos entre os marcadores.
  4. A equipa decide combinar: <h1>O meu portefólio</h1> fica como título, e "Bem-vindo ao meu site" passa a subtítulo num <p>. Escreves as duas linhas finais e apagas os três marcadores.
  5. git add index.html.
  6. git commit (aceitas a mensagem de merge proposta).
  7. git log --oneline --graph mostra o commit de merge com dois pais.

Verificação: o git status está limpo, a página abre no navegador com o título e o subtítulo, e grep -n "<<<<" index.html não devolve nada.

8. Cliente gráfico

8.1 Para que serve

Um cliente gráfico mostra repositórios, ficheiros alterados, branches e historial com botões, em vez de comandos. O referencial pede que se saiba usá-lo como alternativa à linha de comandos, tanto em repositórios locais como remotos.

Cliente Característica
GitHub Desktop Oficial do GitHub, gratuito, simples, ideal para começar
Visual Studio Code (painel Source Control) Integrado no editor; mostra diffs e conflitos
GitKraken, Sourcetree, Tower Clientes completos, com grafo de branches detalhado
Extensão GitLens (VS Code) Mostra quem alterou cada linha e o historial por ficheiro

8.2 Configuração

Segue as instruções do cliente escolhido. No GitHub Desktop: instalar, iniciar sessão com a conta GitHub e confirmar nome e email em Preferências. O cliente usa o mesmo Git que está no terminal e os mesmos repositórios: podes alternar entre os dois no mesmo projeto.

8.3 Equivalência com a linha de comandos

Tarefa Linha de comandos GitHub Desktop
Clonar git clone url File, Clone repository
Ver alterações git status, git diff Separador Changes
Gravar git add e git commit Escrever o resumo e clicar Commit
Criar branch git switch -c nome Current Branch, New Branch
Enviar git push Push origin
Receber git pull Fetch origin, Pull origin
Ver historial git log Separador History
Abrir pull request (no GitHub) Create Pull Request

8.4 Quando usar cada um

O cliente gráfico é mais rápido para ver diferenças e escolher linhas a gravar; a linha de comandos é mais completa (rebase interativo, reflog, scripts) e é o que existe em qualquer servidor. Um técnico deve saber trabalhar com os dois e perceber o que o cliente faz por baixo.

Exemplo resolvido · gravar e enviar com o GitHub Desktop

Situação. Alteraste style.css e index.html, mas só a alteração do CSS pertence à tarefa "Muda a cor de fundo".

  1. No separador Changes, desmarca index.html; fica marcado apenas style.css.
  2. No campo de resumo escreve "Muda a cor de fundo" e clica em Commit to main (ou na branch atual).
  3. Clica em Push origin para enviar.
  4. Em History, confirma que o commit aparece, com style.css como único ficheiro alterado.

Isto equivale a git add style.css, git commit -m "Muda a cor de fundo" e git push.

9. GitHub: conta, página pessoal e repositórios

9.1 O que é o GitHub

O GitHub é uma plataforma que aloja repositórios Git e acrescenta ferramentas de colaboração. O Git é o programa; o GitHub é um serviço que o usa. Não é o único serviço deste tipo.

Funcionalidade Para que serve
Repositórios Alojar código e historial
Pull requests Propor alterações e revê-las
Issues Registar erros, tarefas e ideias
Projects Quadros de tarefas
Actions Automatizar testes e publicações
Pages Publicar sites estáticos a partir de um repositório
Releases Publicar versões com notas e ficheiros

Alternativas: GitLab, Bitbucket e Codeberg. Os conceitos de Git são os mesmos; mudam as interfaces e os nomes (no GitLab, o pull request chama-se merge request).

9.2 Criar a conta

  1. Abre github.com e escolhe Sign up.
  2. Indica o email, uma palavra-passe forte e um nome de utilizador. O nome de utilizador é público e aparece nos endereços dos teus repositórios (github.com/nome): escolhe um sóbrio e profissional.
  3. Resolve a verificação pedida e confirma o email com o código enviado.
  4. Em Settings, Emails, verifica que o email dos commits está associado à conta, para os commits ficarem ligados ao teu perfil.

9.3 Segurança da conta

9.4 Perfil e página pessoal

O perfil (github.com/nome) mostra o teu nome, fotografia, biografia e repositórios fixados. Preenche-o em Settings, Public profile.

README do perfil. Se criares um repositório público com o mesmo nome do teu utilizador e lhe acrescentares um README.md, o conteúdo desse ficheiro aparece no topo do teu perfil. É a tua montra: quem és, o que estás a aprender, ligações para projetos.

Página pessoal com GitHub Pages. Um repositório chamado nome.github.io, com um index.html, é publicado em https://nome.github.io. Em qualquer outro repositório podes ativar o Pages em Settings, Pages, escolhendo a branch e a pasta a publicar. O Pages serve apenas conteúdo estático (HTML, CSS, JavaScript). Tudo o que publicares fica acessível a qualquer pessoa: não ponhas lá dados pessoais de terceiros.

9.5 Criar um repositório

No GitHub, botão New repository:

Campo O que escolher
Owner A tua conta ou uma organização
Repository name Curto, minúsculas com hífen: loja-demo
Description Uma frase sobre o projeto
Public ou Private Público é visível a todos; privado só às pessoas que convidares
Ficheiro README Sim, para o repositório nascer com apresentação (a opção chama-se "Add a README file")
Ficheiro .gitignore O modelo da linguagem que usas, se o GitHub o oferecer na criação
Licença MIT é uma licença permissiva muito usada (ver secção 12.5)

9.6 O ficheiro README.md

O README.md é a primeira coisa que alguém vê num repositório. Está escrito em Markdown, uma sintaxe simples de texto para formatação:

Markdown Resultado
# Título Título de nível 1
## Secção Título de nível 2
**negrito** e *itálico* Negrito e itálico
- item Lista com marcadores
1. item Lista numerada
`código` Código em linha
[texto](endereço) Ligação
![descrição](imagem.png) Imagem

Um bom README responde a quatro perguntas: o que é o projeto, como se instala, como se usa e como contribuir. Exemplo mínimo:

# Loja Demo

Pequena loja online de exemplo, feita em HTML e JavaScript.

## Instalação

```bash
git clone https://github.com/nome/loja-demo.git
cd loja-demo
```

## Utilização

Abre o ficheiro `index.html` no navegador.

## Licença

MIT. Ver o ficheiro LICENSE.

Outros ficheiros habituais na raiz de um repositório: LICENSE, CONTRIBUTING.md (como contribuir), CHANGELOG.md (histórico de versões) e a pasta .github/ (modelos de issues, de pull requests e workflows).

Exemplo resolvido · conta, perfil e primeiro repositório

Objetivo. Ficar com uma conta segura, um README de perfil e um repositório de treino.

  1. Cria a conta (secção 9.2) com um utilizador sóbrio, por exemplo joana-ferreira-dev.
  2. Ativa o 2FA e guarda os códigos de recuperação.
  3. Cria o repositório público joana-ferreira-dev, marca "Add a README file" e escreve duas linhas sobre ti no README.md. O texto aparece no topo do perfil.
  4. Cria o repositório de treino treino-git, privado, com README e .gitignore do modelo adequado.
  5. Verifica no perfil que o primeiro aparece apresentado e que o segundo só é visível quando tens sessão iniciada.

Verificação: abre uma janela privada do navegador em github.com/joana-ferreira-dev; deves ver o repositório público e o README de perfil, mas não o treino-git.

10. Repositórios remotos

10.1 Local e remoto

Um repositório remoto é um repositório Git alojado noutro sítio, normalmente o GitHub. O repositório local e o remoto são independentes: nada se envia nem se recebe sem um comando explícito.

 Repositório local  --git push-->  Repositório remoto (GitHub)
 Repositório local  <--git pull--  Repositório remoto (GitHub)

10.2 Ligar um repositório local ao GitHub

Tens um repositório local e queres publicá-lo.

  1. Cria no GitHub um repositório vazio, sem README, para não haver historiais diferentes.
  2. No repositório local:
git remote add origin https://github.com/nome/meu-site.git
git remote -v                     # confirmar
git branch -M main                # garantir que a branch se chama main
git push -u origin main           # primeiro envio

O -u associa a branch local main à remota origin/main. A partir daí, git push e git pull dispensam argumentos.

Para o caminho inverso, em que o repositório já existe no GitHub: git clone.

10.3 HTTPS ou SSH

HTTPS SSH
Endereço https://github.com/nome/repo.git git@github.com:nome/repo.git
Autenticação Token de acesso pessoal ou gestor de credenciais Par de chaves (privada na tua máquina, pública no GitHub)
Configuração Mais simples Exige gerar e registar uma chave
Dia a dia Pode voltar a pedir credenciais Sem pedidos depois de configurado

Configurar SSH:

# 1. Gerar o par de chaves
ssh-keygen -t ed25519 -C "joana.ferreira@exemplo.pt"

# 2. Arrancar o agente e adicionar a chave privada
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

# 3. Mostrar a chave PÚBLICA para a copiar
cat ~/.ssh/id_ed25519.pub

# 4. No GitHub: Settings, SSH and GPG keys, New SSH key; colar e dar um nome

# 5. Testar
ssh -T git@github.com

Copia sempre o ficheiro .pub. A chave privada (sem .pub) nunca sai da tua máquina, nunca se envia nem se cola em lado nenhum.

10.4 Push, fetch e pull

Comando O que faz
git push Envia os teus commits para o remoto
git fetch Descarrega as novidades do remoto, sem alterar o teu trabalho
git pull fetch seguido de merge das novidades na branch atual
git pull --rebase fetch seguido de rebase dos teus commits locais por cima das novidades

Sem a definição pull.rebase (secção 2.2), as versões atuais do Git só fazem o pull quando basta avançar o ponteiro. Se os dois lados tiverem commits novos, o Git para com "fatal: Need to specify how to reconcile divergent branches". Com pull.rebase false, o git pull faz merge, como diz a tabela; numa só vez, pode usar-se git pull --no-rebase ou git pull --rebase.

Se o remoto tiver commits que não tens, o git push é recusado com "rejected ... fetch first". Não forces: faz git pull, resolve o que houver e volta a enviar. O git push --force reescreve o historial remoto e só é aceitável numa branch tua, que mais ninguém use.

Para ver o que mudou antes de integrar: git fetch e depois git log --oneline main..origin/main.

10.5 Mais de um remote: o upstream

Quando trabalhas num fork (secção 11.1), tens dois remotes: origin (o teu fork) e upstream (o projeto original):

git remote add upstream https://github.com/organizacao/projeto.git
git fetch upstream
git merge upstream/main

Exemplo resolvido · publicar o meu-site no GitHub

Situação. O meu-site tem três commits locais. Queres publicá-lo.

  1. No GitHub, New repository, nome meu-site, sem README. Copia o endereço.
  2. No terminal, dentro da pasta: git remote add origin https://github.com/nome/meu-site.git.
  3. git remote -v mostra origin para fetch e push.
  4. git push -u origin main. O Git lista os objetos enviados e termina com Branch 'main' set up to track remote branch 'main' from 'origin'.
  5. Recarrega a página do repositório no GitHub: aparecem os ficheiros e os três commits.

Verificação: git status diz "Your branch is up to date with 'origin/main'".

11. Colaborar e contribuir

11.1 Fork e clone

Num projeto teu ou da tua equipa, tens permissão de escrita e trabalhas diretamente no repositório (com branches). Num projeto de outra pessoa, sem permissão, fazes um fork: uma cópia do repositório na tua conta, onde podes escrever.

  1. No repositório original, Fork.
  2. Clona o teu fork: git clone https://github.com/tu/projeto.git.
  3. Acrescenta o upstream (secção 10.5).
  4. Antes de começar cada contribuição, atualiza o teu main a partir do upstream.

11.2 Issues

Uma issue regista um erro, uma tarefa ou uma proposta. Uma boa issue tem um título específico, os passos para reproduzir (se for um erro), o resultado esperado e o obtido. Podem levar etiquetas (labels), responsáveis e um marco. Escrever "Closes #12" na descrição de um pull request fecha a issue 12 automaticamente quando o pull request for integrado.

11.3 Pull requests

Um pull request (PR) propõe integrar uma branch noutra e abre espaço para revisão.

1. Branch nova                 git switch -c feature/contactos
2. Trabalhar e gravar          git add ...  e  git commit -m "..."
3. Enviar a branch             git push -u origin feature/contactos
4. Abrir o PR no GitHub        botão "Compare & pull request"
5. Revisão e discussão         comentários, pedidos de alteração
6. Novos commits na branch     git push (o PR atualiza-se sozinho)
7. Aprovação e merge           botão "Merge pull request"
8. Limpeza                     git switch main, git pull, git branch -d ...

Anatomia de um PR: título e descrição; branches de origem e de destino; separador Conversation; separador Commits; separador Files changed, com o diff e comentários linha a linha; verificações automáticas (checks); revisores, etiquetas e issues ligadas.

Um modelo de descrição, guardado em .github/pull_request_template.md:

## Descrição
O que faz este PR e porquê.

## Como testar
1. Passo um
2. Passo dois

## Lista de verificação
- [ ] O código corre sem erros
- [ ] Testei no navegador
- [ ] Atualizei a documentação

Closes #12

11.4 Rever código como revisor

Ao rever, escolhes entre Comment (só comentar), Approve (aprovar) e Request changes (pedir alterações antes do merge).

11.5 Rever código como autor

11.6 Estratégias de merge no GitHub

Estratégia Resultado em main Quando escolher
Create a merge commit Mantém todos os commits e acrescenta um commit de merge Quando o historial detalhado interessa
Squash and merge Todos os commits do PR viram um só Branches com muitos commits de arrumação
Rebase and merge Os commits do PR são reaplicados em linha, sem commit de merge Equipas que querem historial linear e commits limpos

A equipa deve escolher uma e manter a escolha, para o historial ter um padrão previsível.

11.7 Proteger a branch principal

Em Settings, Branches, podes criar uma regra para o main que exija pull request com pelo menos uma aprovação e impeça pushes diretos. As opções exatas variam com o tipo de conta e de repositório; consulta a documentação do GitHub antes de contar com uma delas.

Exemplo resolvido · contribuir para um projeto de outra pessoa

Situação. Encontras um erro de ortografia no README de um projeto aberto e queres corrigi-lo.

  1. Fork do repositório para a tua conta.
  2. git clone do fork, e git remote add upstream com o endereço original.
  3. git switch -c docs/corrige-ortografia.
  4. Corrige o texto, git add README.md, git commit -m "docs: corrige ortografia na introdução".
  5. git push -u origin docs/corrige-ortografia.
  6. No teu fork, clica em Compare & pull request. Confirma a base (repositório original, main) e a comparação (o teu fork, a tua branch).
  7. Preenche o modelo de descrição e submete.
  8. Quem mantém o projeto revê. Se pedir alterações, fazes novos commits na mesma branch e git push; o PR atualiza-se.
  9. Depois do merge feito por quem mantém, atualizas o teu main: git switch main, git fetch upstream, git merge upstream/main, git push.

Verificação: o teu commit aparece no historial do projeto original.

12. Workflow profissional, boas práticas e normas

12.1 Mensagens de commit: Conventional Commits

Uma convenção de mensagens torna o historial legível e permite automatizar notas de versão. O formato:

<tipo>(<âmbito>): <resumo>

<corpo, opcional>

<rodapé, opcional>
Tipo Uso
feat Funcionalidade nova
fix Correção de erro
docs Só documentação
style Formatação, sem mudar lógica
refactor Reestruturação sem mudar comportamento
test Testes
chore Manutenção
ci Configuração de integração contínua

Regras de resumo usadas neste curso: até 50 caracteres, a começar por um verbo na forma escolhida pela equipa (secção 3.4), sem ponto final; as linhas do corpo com até 72 caracteres. A convenção é originalmente escrita em inglês, e muitas equipas mantêm o inglês; escolhe uma língua e mantém-na no projeto inteiro.

Exemplos:

feat(menu): adicionar botão de contactos
fix(login): corrigir erro com palavra-passe vazia
docs(readme): acrescentar passos de instalação

Um commit com corpo e rodapé:

fix(carrinho): corrigir total com desconto

O desconto era aplicado duas vezes quando o cupão era
reutilizado. Passa a ser aplicado uma só vez.

Closes #34

12.2 Commits pequenos e atómicos

Um commit deve ter um só propósito e deixar o projeto a funcionar. Facilita a revisão, o git revert e a procura de erros. Evita commits gigantes, mensagens como "wip" ou "asdf", e misturar uma refatoração com uma funcionalidade nova.

12.3 O dia a dia numa equipa

  1. git switch main e git pull (começar atualizado).
  2. git switch -c feature/nome.
  3. Trabalhar em commits pequenos.
  4. git push -u origin feature/nome (e git push nas vezes seguintes).
  5. Abrir o PR, pedir revisão, responder aos comentários.
  6. Merge, apagar a branch, voltar ao passo 1.

12.4 Hooks e automatização

Os hooks do Git são scripts que correm em eventos, na pasta .git/hooks. Os mais usados: pre-commit (verificar formatação ou procurar segredos antes de gravar), commit-msg (validar o formato da mensagem) e pre-push (correr testes antes de enviar). Ferramentas como o Husky e o pre-commit ajudam a partilhar hooks pela equipa.

Os GitHub Actions correm tarefas automáticas a partir de ficheiros YAML em .github/workflows/. Um exemplo mínimo que corre os testes em cada push e pull request:

name: CI
on: [push, pull_request]
jobs:
  testes:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: 24
      - run: npm ci
      - run: npm test

Os resultados aparecem no PR como checks, verdes ou vermelhos.

12.5 Normas e regulamentos aplicáveis

O referencial pede que se cumpram as normas e regulamentos aplicáveis. Em trabalho com Git e GitHub, as questões práticas são estas.

Dados pessoais. Um repositório não é lugar para dados pessoais reais (listas de clientes, notas de formandos, moradas). Aplica-se o Regulamento Geral sobre a Proteção de Dados (RGPD), e em Portugal a Comissão Nacional de Proteção de Dados é a autoridade de controlo. Num repositório público qualquer pessoa pode ler e copiar o conteúdo, e o historial mantém o que já foi apagado. Para treinar, usa dados inventados.

Segredos. Palavras-passe, chaves de API, tokens e chaves privadas nunca entram num commit. Usa um ficheiro .env listado no .gitignore e um .env.example sem valores reais para documentar o que é preciso. Se um segredo for publicado por engano: revoga-o e troca-o de imediato, antes de limpar o historial. Apagar o ficheiro num commit novo não chega, porque o segredo continua nos commits antigos.

Licenças e direitos de autor. Um repositório público sem licença não dá a ninguém permissão para reutilizar o código. Escolhe uma licença e põe o texto no ficheiro LICENSE. Exemplos de licenças conhecidas: MIT e Apache 2.0 (permissivas) e GPL (exige que obras derivadas mantenham a mesma licença). A ferramenta choosealicense.com ajuda a comparar. Ao copiar código de outros, respeita a licença deles e indica a origem.

Termos de utilização. Ao criar a conta aceitas os termos do GitHub; consulta-os nas páginas legais da plataforma.

Regras da organização. Na escola ou na empresa, cumpre as regras internas: onde se guarda o código, quem pode criar repositórios e como se nomeiam.

12.6 Boas práticas, em resumo

Área Faz Evita
Commits Pequenos, atómicos, com mensagem clara Gigantes, "wip", código que não corre
Branches Nome claro, vida curta, apagar após merge Branches de meses, nomes vagos
Pull requests Cerca de 400 linhas, um propósito, revisão PRs enormes, auto-aprovação
Segurança .gitignore, 2FA, segredos fora do repo Palavras-passe no código
Colaboração Comunicar, rever com respeito push --force em branches partilhadas

Exemplo resolvido · segredo gravado por engano

Situação. Gravaste e enviaste um ficheiro config.js com uma chave de API de um serviço externo.

  1. Revoga a chave no painel do serviço e gera uma nova. Este passo vem primeiro: a partir do momento em que a chave esteve publicada, deve-se assumir que foi lida.
  2. Põe a nova chave num .env, acrescenta .env ao .gitignore e faz o código ler a variável de ambiente.
  3. Remove o ficheiro do acompanhamento: git rm --cached config.js, e grava git commit -m "fix: remove chave do repositório".
  4. Para limpar também o historial, usa uma ferramenta própria (a documentação do GitHub sobre remoção de dados sensíveis indica o procedimento) e coordena com a equipa, porque reescreve o historial.
  5. Verifica que git status não mostra o .env e que a aplicação continua a funcionar com a chave nova.

Lição: a ordem importa. Revogar vem antes de limpar.

Erros comuns

Erro Porque acontece Como evitar ou corrigir
Commits com a identidade errada Esqueceu-se a configuração inicial git config user.name e user.email antes do primeiro commit
git add . a apanhar ficheiros que não devia Falta de .gitignore Criar o .gitignore no primeiro commit e rever o git status antes de gravar
Gravar segredos Ficheiros de configuração versionados .env no .gitignore; revogar a chave se acontecer
Trabalhar diretamente em main Pressa Criar sempre uma branch para cada tarefa
git reset --hard sem pensar Confundir com restore Ler o git status; recuperar com git reflog se já havia commit
Rebase de commits já publicados Preferir historial linear Rebase só em commits locais; merge nas branches partilhadas
push --force numa branch partilhada O push foi recusado e forçou-se Fazer git pull, resolver e enviar normalmente
Deixar marcadores <<<<<<< no ficheiro Resolução apressada Procurar <<<< antes de git add
Mensagens como "wip" ou "mudanças" Sem convenção Conventional Commits e resumo a começar por um verbo
PRs enormes Branches de longa duração Dividir o trabalho; branches de dias
Esquecer o push das tags O git push normal não as envia git push origin v1.0.0
Copiar a chave privada em vez da pública Confusão entre os dois ficheiros Copiar só o ficheiro .pub
Criar o repositório remoto com README e depois ligar um local com historial próprio Historiais sem ancestral comum Criar o remoto vazio, ou clonar primeiro

Exercícios resolvidos

Exercício resolvido 1 · Identificar o estado de cada ficheiro

Enunciado. Num repositório, o git status mostra: app.js em "Changes to be committed", style.css em "Changes not staged for commit" e notas.txt em "Untracked files". Diz o estado de cada um e o que acontece se correres git commit -m "Atualiza app".

Resolução.

  1. app.js está staged: foi preparado com git add.
  2. style.css está modified: foi alterado, mas não foi preparado.
  3. notas.txt está untracked: o Git não o conhece.
  4. O commit grava apenas o app.js. O style.css e o notas.txt ficam como estavam.
  5. Para gravar também o style.css, é preciso git add style.css e outro commit (ou o -a, que só apanha ficheiros acompanhados).

Exercício resolvido 2 · Escolher o comando para desfazer

Enunciado. Para cada situação, indica o comando mais adequado: (a) alteraste index.html e queres voltar à versão do último commit; (b) preparaste um ficheiro por engano; (c) o último commit tem uma gralha na mensagem e ainda não foi enviado; (d) um commit com erro já está no main remoto.

Resolução.

Situação Comando Razão
(a) git restore index.html Descarta as alterações do diretório de trabalho; atenção, são perdidas
(b) git restore --staged ficheiro Tira da área de preparação e mantém as alterações
(c) git commit --amend -m "mensagem certa" O commit ainda é só local, pode ser substituído
(d) git revert abc1234 O commit já foi publicado, por isso anula-se com um commit novo, sem reescrever o historial

Exercício resolvido 3 · Ler a saída de um merge com conflito

Enunciado. Fundiste feature/preco em main e o Git respondeu CONFLICT (content): Merge conflict in preco.js. O ficheiro tem:

<<<<<<< HEAD
const taxa = 0.20;
=======
const taxa = 0.10;
>>>>>>> feature/preco

Explica o que significam as duas versões e como concluir o merge sabendo que o ficheiro preco.js serve produtos com a taxa normal.

Resolução.

  1. A versão de cima (HEAD) vem de main: taxa de 0,20. A de baixo vem de feature/preco: taxa de 0,10.
  2. A decisão é de negócio, não do Git: como o enunciado diz que o ficheiro serve produtos com taxa normal, fica a primeira. Os valores são ilustrativos.
  3. Edita o ficheiro para ficar só const taxa = 0.20;, sem marcadores.
  4. git add preco.js e git commit concluem o merge.
  5. Como alternativa, para ficar com a versão da branch atual: git checkout --ours preco.js, seguido de git add e git commit.

Exercício resolvido 4 · Fluxo completo de uma pequena alteração

Enunciado. Tens o repositório loja-demo clonado. Descreve os comandos para corrigir um preço no ficheiro precos.json, propor a alteração e limpar no fim.

Resolução.

git switch main
git pull
git switch -c fix/preco-caneta
# editar precos.json
git diff
git add precos.json
git commit -m "fix(precos): corrigir preço da caneta"
git push -u origin fix/preco-caneta
# abrir o PR no GitHub, rever, fazer merge
git switch main
git pull
git branch -d fix/preco-caneta

Pontos a verificar: o nome da branch segue a convenção; o resumo do commit tem menos de 50 caracteres; a descrição do PR explica o que muda e porquê; no fim, git branch já não mostra a branch apagada.

Síntese

Glossário

Apêndice · Resumo de comandos

# Configuração
git config --global user.name "Nome"
git config --global user.email "email@exemplo.pt"
git config --list

# Iniciar
git init
git clone <endereço>

# Dia a dia
git status
git add <ficheiro>
git commit -m "mensagem"
git diff
git diff --staged
git log --oneline --graph --all

# Desfazer
git restore <ficheiro>
git restore --staged <ficheiro>
git commit --amend
git reset --soft HEAD~1
git revert <commit>
git reflog

# Branches
git branch
git switch -c <nome>
git switch <nome>
git merge <nome>
git branch -d <nome>

# Remotos
git remote -v
git remote add origin <endereço>
git push -u origin main
git fetch
git pull

# Tags
git tag -a v1.0.0 -m "mensagem"
git push origin v1.0.0

# Outros
git stash
git stash pop
git cherry-pick <commit>
git blame <ficheiro>

Documentação oficial: git-scm.com/doc (inclui o livro Pro Git, gratuito) e docs.github.com.