Tutorial Git: trabalhar em equipa com branches e merge
verificado a 7 Setembro 2026 · 10 min
Cria uma branch com git switch -c nom, trabalha, e depois funde-a com git merge a partir da branch de destino. Em caso de conflito, o Git insere marcadores no ficheiro: escreve o conteúdo certo, apaga os marcadores e faz git add e git commit. O git merge --abort anula tudo a qualquer momento.
Uma branch é uma linha de desenvolvimento paralela. Permite-te trabalhar numa funcionalidade sem tocar na versão estável, e ao teu colega fazer o mesmo do lado dele. Este capítulo cobre o ciclo completo: criar uma branch, fundi-la, resolver um conflito à mão e escolher entre merge e rebase.
git switch em vez de git checkout
Historicamente, o git checkout servia para tudo: mudar de branch, criar uma, restaurar um ficheiro, colocar-te num commit preciso. Esta acumulação de papéis é a primeira fonte de confusão para quem começa, e uma fonte de acidentes para os outros.
O Git 2.23, lançado em agosto de 2019, dividiu o comando em dois: git switch para te deslocares entre branches, git restore para anular alterações. Saíram marcados como experimentais, já não o são na documentação oficial. Este capítulo usa-os e dá sempre o equivalente em checkout, que ainda vais encontrar durante muito tempo nos tutoriais e no Stack Overflow.
| Intenção | Comando moderno | Forma antiga |
|---|---|---|
| Mudar de branch | git switch nom | git checkout nom |
| Criar uma branch e passar para ela | git switch -c nom | git checkout -b nom |
| Voltar à branch anterior | git switch - | git checkout - |
| Anular a alteração de um ficheiro | git restore fichier | git checkout -- fichier |
| Tirar um ficheiro do índice | git restore --staged fichier | git reset HEAD fichier |
Criar uma branch e trabalhar nela
git switch -c feature/panierSwitched to a new branch 'feature/panier'A branch parte do commit onde estavas. Podes agora modificar, adicionar e fazer commit normalmente: nada disso vai aparecer na main enquanto não a fundires.
Quanto aos nomes das branches, o Git não impõe qualquer regra, mas os prefixos feature/, fix/ e hotfix/ são uma convenção bem difundida e as interfaces dos alojamentos agrupam-nas visualmente.
Para veres em que ponto estás:
git branch # as branches locais
git branch -vv # com o último commit e a branch remota seguida
git branch -a # locais e remotas
git switch - # voltar à branch anteriorPara publicares a branch e a tornares visível para a equipa:
git push -u origin feature/panierTrazer a branch de um colega
No sentido inverso, o git fetch atualiza o que sabes do servidor sem alterar nada nas tuas branches:
git fetch origin feature/collegue # uma branch específica
git fetch --all # todos os repositórios remotos
git branch -r # o que já conheces do servidor origin/HEAD -> origin/main
origin/feature/collegue
origin/mainSó falta passar para ela. O Git cria automaticamente a branch local e liga-a à do servidor:
git switch feature/colleguebranch 'feature/collegue' set up to track 'origin/feature/collegue'.
Switched to a new branch 'feature/collegue'Quando o Git recusa mudar de branch
É um dos primeiros erros que vais encontrar:
error: Your local changes to the following files would be overwritten by checkout:
index.html
Please commit your changes or stash them before you switch branches.
AbortingO Git protege o teu trabalho: o ficheiro que modificaste não tem o mesmo conteúdo na outra branch, e mudar de branch iria sobrescrevê-lo. Três soluções, por ordem de preferência.
Fazer commit, se o trabalho estiver coerente. É quase sempre a resposta certa, um commit imperfeito numa branch de trabalho não custa nada e corrige-se mais tarde com os comandos de anulação vistos no capítulo anterior.
Pôr de parte, se o trabalho estiver a meio:
git stash # põe as alterações de parte
git switch main # …fazes o que tinhas a fazer…
git switch -
git stash pop # traz de volta as alteraçõesSaved working directory and index state WIP on main: 6d495d9 Page d accueilDeitar fora, com git restore ., se as alterações não valiam nada. Sem volta atrás.
Fundir uma branch
Assim que a funcionalidade estiver terminada, passa para a branch de destino e funde:
git switch main
git merge feature/panierQuando as duas branches mexeram em ficheiros diferentes, o Git funde sozinho e não tem nada a perguntar-te. O caso interessante é o outro.
Resolver um conflito
Eis a situação reproduzida para este capítulo. Na feature/panier, a segunda linha do index.html foi substituída por uma mensagem de carrinho vazio. Na main, a primeira linha foi alterada para acrescentar o nome da marca. As duas branches mexeram no mesmo ficheiro.
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.Nada está partido. O Git fundiu o que conseguiu e deixa-te decidir o resto. Primeira coisa a fazer, perguntar em que ponto estás:
git statusOn branch main
Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: index.html
no changes added to commit (use "git add" and/or "git commit -a")Para obteres apenas a lista dos ficheiros a tratar:
git diff --name-only --diff-filter=UAbre o ficheiro. O Git inseriu-lhe marcadores:
<<<<<<< HEAD
<h1>Boutique Gekkode</h1>
<p>Bienvenue sur la boutique.</p>
=======
<h1>Boutique</h1>
<p>Votre panier est vide.</p>
>>>>>>> feature/panierA leitura é mecânica. Entre <<<<<<< HEAD e ======= está a versão da branch onde estás, aqui a main. Entre ======= e >>>>>>> está a versão da branch que estás a fundir.
Cabe-te a ti escrever o resultado correto. Não é forçosamente uma ou outra: aqui, as duas alterações estão certas e devem coexistir.
<h1>Boutique Gekkode</h1>
<p>Votre panier est vide.</p>Apaga os três marcadores, não podem ficar no ficheiro. Depois avisa o Git de que está resolvido e termina a fusão:
git add index.html
git commit -m "Fusionne feature/panier dans main"* 0899b0c Fusionne feature/panier dans main
|
| * aacf4c0 Panier : message quand le panier est vide
* | 11ff16b Ajoute le nom de la marque au titre
|/
* 6d495d9 Page d accueilO commit de fusão tem dois pais, o que o grafo torna visível.
Anular tudo e recomeçar do zero
Se o conflito te ultrapassar, não és obrigado a nada:
git merge --abortO repositório volta exatamente ao estado anterior ao comando merge. Nada se perde, podes recomeçar mais tarde ou falar com o autor da outra branch.
merge ou rebase
Ambos integram o trabalho de uma branch noutra, mas não da mesma maneira.
git merge cria um commit de fusão que liga os dois históricos. O histórico guarda o rasto exato do que aconteceu, incluindo o facto de terem existido duas branches em paralelo. O grafo é fiel, mas ramifica-se.
git rebase volta a aplicar os teus commits por cima da branch de destino, como se tivesses trabalhado a partir da última versão dela. O histórico continua uma linha reta, mais fácil de ler, mas foi reescrito: os teus commits mudam de identificador.
git switch feature/panier
git rebase mainUm rebase pode encontrar os mesmos conflitos que uma fusão, commit a commit. A resolução é idêntica, só muda o comando para continuar:
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
error: could not apply 4937109... Promo
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Could not apply 4937109... Promogit add index.html
git rebase --continue
# ou, para anular tudo
git rebase --abortA regra de ouro cabe numa frase: nunca faças rebase de uma branch que outras pessoas já trouxeram. Reescrever um histórico partilhado obriga os teus colegas a reparar o deles à mão. Já na tua própria branch de trabalho, antes de a propores, o rebase é perfeitamente legítimo e dá um histórico bem mais legível.
O caso do dia a dia: alguém fez push antes de ti
Queres fazer push e o Git recusa:
To /root/o.git
! [rejected] main -> main (fetch first)
error: failed to push some refs to '/root/o.git'
hint: Updates were rejected because the remote contains work that you do notO servidor tem commits que tu não tens. Tens de os integrar primeiro. E aí, num repositório novo, o Git faz-te uma pergunta em vez de agir:
hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint:
hint: git config pull.rebase false # merge
hint: git config pull.rebase true # rebase
hint: git config pull.ff only # fast-forward only
hint:O Git recusa-se a escolher por ti desde a versão 2.27. Responde de uma vez por todas, como proposto no capítulo de instalação:
git config --global pull.rebase trueO desenrolar passa então a ser este:
git pull --rebase
git pushFrom /root/o
622a60b..38b7dc5 main -> origin/main
Rebasing (1/1)Successfully rebased and updated refs/heads/main.
* 5b45117 Ajoute app.js
* 38b7dc5 Ajoute la doc
* 622a60b DepartO teu commit foi recolocado por cima do do colega e o histórico manteve-se linear, sem commit de fusão parasita. É a configuração a recomendar a uma equipa que está a começar.
Um aviso para terminar: nunca tentes desbloquear um push recusado com git push --force. Esse comando apaga o trabalho que está no servidor. Se tiveres mesmo de forçar, depois de um rebase da tua própria branch, usa o git push --force-with-lease, que se recusa a apagar commits que ainda não tinhas visto.
Fazer limpeza
Um ramo fundido já não tem razão de existir. Se foi publicado com -u, envie primeiro os seus últimos commits: o Git recusa-se a apagar um ramo local adiantado em relação ao ramo remoto, mesmo fundido em main.
git push origin feature/panier
git branch -d feature/panierDeleted branch feature/panier (was bc2203a).Sem esse push prévio, a mensagem é explícita:
warning: not deleting branch 'feature/panier' that is not yet merged to
'refs/remotes/origin/feature/panier', even though it is merged to HEAD
error: the branch 'feature/panier' is not fully merged
hint: If you are sure you want to delete it, run 'git branch -D feature/panier'
hint: Disable this message with "git config set advice.forceDeleteBranch false"Se a branch não tiver sido fundida, o Git trava-te, o que é uma rede de segurança útil:
error: the branch 'feature/promo' is not fully merged
hint: If you are sure you want to delete it, run 'git branch -D feature/promo'
hint: Disable this message with "git config set advice.forceDeleteBranch false"Para apagares também a branch no servidor e limpares as referências locais que ficaram obsoletas:
git push origin --delete feature/panier
git fetch --pruneO git fetch traz o estado do servidor sem fundir nada nas tuas branches, ao contrário do git pull. A opção --prune aproveita para apagar as branches remotas que já não existem, aquelas que os teus colegas fundiram e eliminaram.
Já sabes colaborar. O último capítulo trata da organização: que modelo de branches adotar consoante a tua equipa.
Erros frequentes
git stash, antes de mudares de branch.git pull recusa-se a escolher sozinho entre fusão e rebase. Resolve a questão com git config --global pull.rebase true.git pull --rebase. Nunca uses git push --force para passar por cima: apaga o trabalho dos outros.<<<<<<<, ======= e >>>>>>> têm de desaparecer do ficheiro antes do git add.