Utilizar serviços Git e GitHub
- Introdução
- 1. Controlo de versões
- 2. Instalar e configurar o Git
- 3. Repositórios locais e commits
- 4. Desfazer e editar o histórico
- 4.1 Erros antes do commit
- 4.2 Corrigir o último commit
- 4.3 Reset e revert
- 4.4 Editar o historial com rebase interativo
- 4.5 Guardar trabalho a meio: stash
- 4.6 Aplicar um só commit noutra branch: cherry-pick
- 4.7 O reflog, a rede de segurança
- Exemplo resolvido · limpar três commits antes de partilhar
- Exemplo resolvido · recuperar de um reset --hard
- 5. Tags
- 6. Branches e merge
- 7. Resolução de conflitos
- 8. Cliente gráfico
- 9. GitHub: conta, página pessoal e repositórios
- 10. Repositórios remotos
- 11. Colaborar e contribuir
- 12. Workflow profissional, boas práticas e normas
- Erros comuns
- Exercícios resolvidos
- Síntese
- Glossário
- Apêndice · Resumo de comandos
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:
- Qual é a versão atual?
- O que mudou entre a segunda e a terceira?
- Como se juntam as alterações de duas pessoas que editaram o mesmo ficheiro?
- Se apagarmos a errada, é possível recuperá-la?
- Como voltamos a um estado que funcionava?
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:
- Distribuído: trabalha-se offline e sincroniza-se quando convém.
- Rápido: as operações do dia a dia são locais.
- Branches baratos: criar uma linha paralela de trabalho custa um instante.
- Integridade: cada commit é identificado por uma impressão digital (hash) calculada a partir do conteúdo, por isso uma alteração silenciosa no historial seria detetada.
- Gratuito e de código aberto, com documentação oficial em git-scm.com.
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.
- Mantém-se um ficheiro
index.htmle cria-se o repositório comgit init. - Cada versão com sentido passa a ser um commit:
git commit -m "Adiciona cabeçalho", depoisgit commit -m "Corrige ligação do menu", e assim por diante. - Para ver o que mudou entre o segundo e o terceiro estado, usa-se
git diffentre os dois commits, em vez de abrir ficheiros. - Para voltar a um estado antigo, regressa-se ao commit correspondente, sem ficheiros espalhados.
- 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.
- Verifica a instalação:
git --version. - Cria a pasta e o repositório:
mkdir treino,cd treino,git init. - Define a identidade só para este repositório:
git config user.name "Joana Ferreira"egit config user.email "joana@escola.exemplo.pt". - Confirma:
git config user.emaildevolvejoana@escola.exemplo.pt. - Confirma a origem:
git config --list --show-originmostra a linha deuser.emailcom 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/.
- Cria
index.htmlcom um título estyle.cssvazio. Corregit status: os dois aparecem em Untracked files. git add index.html style.css. Ogit statusmostra agora "Changes to be committed" com os dois ficheiros.git commit -m "Cria estrutura inicial do site". O Git responde com o resumo, por exemplo "2 files changed".- Edita
style.csse acrescenta uma regra. Ogit statusmostrastyle.csscomo modified. Ogit diffmostra as linhas novas com+. git commit -am "Define cor de fundo". Como o ficheiro já era acompanhado, o-abasta.git log --onelinemostra 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.
git log --onelinemostra os três commits.git rebase -i HEAD~3abre a lista.- Mantém
pickna primeira linha; mudawipe a "gralha" parafixup, para se fundirem ao primeiro. - Guarda e fecha o editor.
git log --onelinemostra 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.
git refloglista os movimentos; a linhaHEAD@{1}corresponde ao commit "Adiciona rodapé" (hashc8d21aa, por exemplo).git reset --hard c8d21aarepõe a branch nesse commit.git log --onelinemostra 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.
- Confirma que estás no commit certo:
git switch main,git pull,git log --oneline -3. git tag -a v1.0.0 -m "Primeira versão publicada".git show v1.0.0confirma o autor, a data e o commit.git push origin v1.0.0envia a tag.- 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.
git switch mainegit statuslimpo.git switch -c feature/contactos. Ogit branchmostra* feature/contactos.- Cria
contactos.html,git add contactos.html,git commit -m "Adiciona página de contactos". - Altera o menu em
index.htmle gravagit commit -am "Liga o menu à página de contactos". git log --oneline --graph --allmostra os dois commits novos numa linha que se afasta domain.git switch mainegit merge feature/contactos. Como omainnão avançou, é um fast-forward.git branch -d feature/contactosapaga 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
git statuspara ver quais os ficheiros em conflito.- Abre cada ficheiro e decide: ficar com uma versão, com a outra, ou escrever uma combinação.
- Apaga os três marcadores. Um ficheiro com marcadores esquecidos fica estragado.
git add ficheiromarca o conflito como resolvido.git commitconclui o merge (o editor traz uma mensagem de merge pronta).- 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:
- Clica em Resolve conflicts.
- O editor mostra os mesmos marcadores
<<<<<<<,=======e>>>>>>>; edita o texto final e apaga os marcadores. - Clica em Mark as resolved para cada ficheiro.
- 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
- Branches de curta duração (dias, não meses).
- Atualizar a tua branch a partir de
maincom regularidade. - Combinar com a equipa quem mexe em que ficheiros.
- Dividir o código em ficheiros pequenos e com um só propósito.
- Usar o mesmo formatador de código em toda a equipa, para não haver conflitos só por espaços e fins de linha.
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.
git switch mainegit merge feature/titulo. O Git respondeCONFLICT (content): Merge conflict in index.html.git statuslistaindex.htmlem "Unmerged paths".- Abres o ficheiro e vês os dois blocos entre os marcadores.
- 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. git add index.html.git commit(aceitas a mensagem de merge proposta).git log --oneline --graphmostra 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".
- No separador Changes, desmarca
index.html; fica marcado apenasstyle.css. - No campo de resumo escreve "Muda a cor de fundo" e clica em Commit to main (ou na branch atual).
- Clica em Push origin para enviar.
- Em History, confirma que o commit aparece, com
style.csscomo ú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
- Abre github.com e escolhe Sign up.
- 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. - Resolve a verificação pedida e confirma o email com o código enviado.
- 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
- Ativa a autenticação de dois fatores (2FA), em Settings, Password and authentication. Com ela, uma palavra-passe roubada não chega para entrar na conta.
- Guarda os códigos de recuperação num sítio seguro, fora do computador.
- Usa uma palavra-passe única, de preferência num gestor de palavras-passe.
- Nas operações Git por HTTPS, a palavra-passe da conta já não é aceite: usa-se um token de acesso pessoal ou o gestor de credenciais que vem com o Git for Windows e com o GitHub Desktop. A alternativa é a chave SSH (secção 10.3).
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 |
 |
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.
- Cria a conta (secção 9.2) com um utilizador sóbrio, por exemplo
joana-ferreira-dev. - Ativa o 2FA e guarda os códigos de recuperação.
- Cria o repositório público
joana-ferreira-dev, marca "Add a README file" e escreve duas linhas sobre ti noREADME.md. O texto aparece no topo do perfil. - Cria o repositório de treino
treino-git, privado, com README e.gitignoredo modelo adequado. - 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.
- Cria no GitHub um repositório vazio, sem README, para não haver historiais diferentes.
- 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.
- No GitHub, New repository, nome
meu-site, sem README. Copia o endereço. - No terminal, dentro da pasta:
git remote add origin https://github.com/nome/meu-site.git. git remote -vmostraoriginpara fetch e push.git push -u origin main. O Git lista os objetos enviados e termina comBranch 'main' set up to track remote branch 'main' from 'origin'.- 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.
- No repositório original, Fork.
- Clona o teu fork:
git clone https://github.com/tu/projeto.git. - Acrescenta o
upstream(secção 10.5). - Antes de começar cada contribuição, atualiza o teu
maina partir doupstream.
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
- Lê o PR todo antes de comentar.
- Comenta linhas concretas, com um tom construtivo; pergunta em vez de acusar.
- Sugere alternativas com código quando possível.
- Reconhece o que está bem feito.
- Distingue o que bloqueia o merge do que é sugestão (os comentários menores chamam-se nits).
- Verifica: funciona? casos-limite? segurança? legibilidade? testes? documentação?
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
- PRs pequenos: como regra prática da equipa, cerca de 400 linhas alteradas no máximo.
- Descrição completa e o PR com um só propósito.
- Relê o teu próprio diff antes de pedir revisão.
- Responde a todos os comentários, mesmo que seja só "feito".
- Aceita a crítica ao código como crítica ao código, não a ti.
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.
- Fork do repositório para a tua conta.
git clonedo fork, egit remote add upstreamcom o endereço original.git switch -c docs/corrige-ortografia.- Corrige o texto,
git add README.md,git commit -m "docs: corrige ortografia na introdução". git push -u origin docs/corrige-ortografia.- 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). - Preenche o modelo de descrição e submete.
- Quem mantém o projeto revê. Se pedir alterações, fazes novos commits na mesma branch e
git push; o PR atualiza-se. - 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
git switch mainegit pull(começar atualizado).git switch -c feature/nome.- Trabalhar em commits pequenos.
git push -u origin feature/nome(egit pushnas vezes seguintes).- Abrir o PR, pedir revisão, responder aos comentários.
- 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.
- 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.
- Põe a nova chave num
.env, acrescenta.envao.gitignoree faz o código ler a variável de ambiente. - Remove o ficheiro do acompanhamento:
git rm --cached config.js, e gravagit commit -m "fix: remove chave do repositório". - 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.
- Verifica que
git statusnão mostra o.enve 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.
app.jsestá staged: foi preparado comgit add.style.cssestá modified: foi alterado, mas não foi preparado.notas.txtestá untracked: o Git não o conhece.- O commit grava apenas o
app.js. Ostyle.csse onotas.txtficam como estavam. - Para gravar também o
style.css, é precisogit add style.csse 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.
- A versão de cima (
HEAD) vem demain: taxa de 0,20. A de baixo vem defeature/preco: taxa de 0,10. - 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.
- Edita o ficheiro para ficar só
const taxa = 0.20;, sem marcadores. git add preco.jsegit commitconcluem o merge.- Como alternativa, para ficar com a versão da branch atual:
git checkout --ours preco.js, seguido degit addegit 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
- O Git é um sistema de controlo de versões distribuído: cada pessoa tem o historial completo, e trabalha-se offline.
- Um ficheiro passa por três áreas: diretório de trabalho, área de preparação (
git add) e repositório (git commit). - A instalação e a configuração (
user.name,user.email) fazem-se uma vez por máquina; a verificação égit --versionegit config --list. - O historial consulta-se com
git log,git showegit diff, e edita-se com--amend,rebase -i,reseterevert. Em commits publicados usa-serevert. - O reflog e o
stashsão redes de segurança para trabalho já gravado e para trabalho a meio. - Tags marcam versões; as anotadas guardam autor e mensagem, e é preciso enviá-las explicitamente.
- Branches são ponteiros baratos; o merge pode ser fast-forward ou de três vias; o rebase deixa o historial linear mas só se usa em commits locais.
- Um conflito resolve-se escolhendo o texto final, apagando os marcadores, fazendo
git addegit commit, no terminal, no editor ou no GitHub. - O cliente gráfico faz o mesmo que a linha de comandos, por interface.
- No GitHub criam-se a conta (com 2FA), o perfil, o README do perfil e os repositórios; o
README.mdapresenta o projeto. - Liga-se um repositório local a um remoto com
git remote add originegit push -u origin main; a autenticação é por token ou SSH. - Colabora-se com forks, issues e pull requests, com revisão de código e uma estratégia de merge escolhida pela equipa.
- Cumprem-se as normas aplicáveis: nada de dados pessoais reais nem segredos em repositórios, e licença explícita nos projetos públicos.
Glossário
- Branch: linha de desenvolvimento com nome, que aponta para um commit.
- Cherry-pick: copiar o efeito de um commit para a branch atual.
- Clone: cópia completa de um repositório remoto para a máquina local.
- Commit: instantâneo do projeto gravado no historial, com autor, data e mensagem.
- Conflito: duas alterações incompatíveis na mesma zona de um ficheiro, que exigem decisão humana.
- Conventional Commits: convenção de mensagens com tipo, âmbito e resumo.
- Fast-forward: merge em que o ponteiro da branch apenas avança, sem commit de merge.
- Fetch: descarregar novidades do remoto sem as integrar.
- Fork: cópia de um repositório de outra pessoa para a tua conta.
- GitHub Actions: sistema de automatização de tarefas a partir de ficheiros YAML no repositório.
- GitHub Pages: serviço que publica sites estáticos a partir de um repositório.
- Hash: identificador único de um commit, calculado a partir do conteúdo.
- HEAD: ponteiro para o commit ou a branch em que estás.
- Hook: script que o Git corre automaticamente num evento, como antes de um commit.
- Issue: registo de um erro, tarefa ou proposta num repositório.
- Merge: juntar o trabalho de duas branches.
- Origin: nome habitual do remote de onde se clonou.
- Pull: receber e integrar commits do remoto.
- Pull request: proposta de integrar uma branch noutra, com espaço para revisão.
- Push: enviar commits locais para o remoto.
- README: ficheiro de apresentação do projeto, em Markdown.
- Rebase: reaplicar commits sobre outro ponto de partida, reescrevendo-os.
- Reflog: registo local dos movimentos do HEAD.
- Release: versão publicada no GitHub, com notas, associada a uma tag.
- Remote: repositório noutro sítio com que se sincroniza.
- Repositório: pasta de projeto acompanhada pelo Git.
- Revert: criar um commit que anula outro.
- Staging area: zona onde se preparam as alterações do próximo commit.
- Stash: guardar temporariamente alterações por gravar.
- Squash: fundir vários commits num só.
- Tag: etiqueta fixa que marca um commit, normalmente uma versão.
- Upstream: repositório original de um fork.
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.