SSD Nodes Learn 🎉 VPS desde $4.99/mês
Guias Matt ConnorPor Matt Connor

Git e GitHub: qual a diferença para donos de VPS

Git é o programa de controle de versão no seu servidor. GitHub é um serviço hospedado para repositórios, revisões e builds. Entenda o impacto no VPS.

O que é o GitHub?

O GitHub é um serviço alojado que armazena repositórios Git e cria um site à volta deles. O Git é o programa de controlo de versões executado no seu próprio computador ou servidor. O GitHub é o produto de uma empresa construído sobre o Git e pertence à Microsoft desde 2018. Pode utilizar o Git todos os dias sem nunca abrir o GitHub. Não pode utilizar o GitHub sem o Git.

Esta distinção é importante assim que gere um VPS (servidor privado virtual). O Git regista o histórico dos seus ficheiros de configuração e scripts de deploy. O GitHub é o local onde fica uma cópia desse histórico quando o servidor não a tem, além de permitir executar builds e fazer revisões. Este guia acompanha um exemplo desde uma pasta vazia até um deploy num servidor e define cada termo novo no primeiro ponto em que aparece.

O que o Git faz por si só

Git é um sistema de controlo de versões: regista o estado de um diretório ao longo do tempo, para que possa ver o que mudou, quando mudou e porquê. Foi escrito em 2005 para o desenvolvimento do kernel Linux. É distribuído, o que significa que cada cópia de um repositório contém todo o histórico. O design não inclui um servidor central. O portátil de um colega é uma cópia tão completa como qualquer servidor.

Instale-o e defina a sua identidade. O Git recusa-se a registar um commit sem um nome e um endereço de email, porque ambos são gravados no próprio commit.

sudo apt update && sudo apt install -y git
git --version
git config --global user.name "Your Name"
git config --global user.email "you@example.com"

No Ubuntu 24.04, git --version mostra git version 2.43.0. Qualquer release dos últimos anos comporta-se da mesma forma em tudo o que é apresentado abaixo.

O exemplo: um repositório para os ficheiros de deploy do seu VPS

Um repositório, normalmente abreviado para "repo", é um diretório monitorizado pelo Git. Ele passa a ser um repositório quando executa git init, que cria uma pasta oculta .git no seu interior. Essa pasta é o repositório. Se eliminar .git, fica com um diretório normal sem histórico.

mkdir vps-deploy && cd vps-deploy
git init -b main
printf '.env\n*.key\n' > .gitignore

-b main atribui o nome main ao primeiro branch. Se o omitir, o Git apresenta uma mensagem longa sobre o nome do branch predefinido. .gitignore lista os caminhos que o Git nunca deve monitorizar. Escreva o ficheiro de segredos nesse ficheiro logo no primeiro dia, porque um ficheiro que tenha sido submetido uma vez permanece no histórico mesmo depois de o eliminar. Para o remover corretamente, é necessário reescrever todos os commits posteriores.

Commits: a unidade do histórico

Agora adicione um script e registe-o.

printf '#!/bin/sh\nsudo systemctl restart caddy\n' > restart.sh
git add restart.sh .gitignore
git commit -m "Add restart script and gitignore"
git log --oneline

git add move uma alteração para a área de preparação, que é a lista do que entrará no próximo commit. git commit grava essa lista no histórico como uma entrada. Um commit contém um instantâneo de todos os ficheiros monitorizados, uma mensagem, um autor, um carimbo de data e hora e um ponteiro para o commit anterior. git log --oneline imprime uma linha por commit, começando por um hash curto como a1b2c3d. Esse hash é o nome do commit, e praticamente todos os comandos Git aceitam-no.

Ignore o passo git add e git commit responde no changes added to commit (use "git add" and/or "git commit -a"). Não há nada avariado. O Git está a indicar que a área de preparação está vazia, pelo que não há nada para incluir no instantâneo. git status é o comando a executar sempre que estiver perdido: identifica o branch atual, as alterações preparadas e os ficheiros que o Git consegue ver, mas que não está a monitorizar.

Branches: uma segunda linha do histórico

Uma branch é um ponteiro móvel para um commit. main é uma branch e não tem nada de especial no Git. Criar uma branch não custa nada, porque o Git grava um novo ponteiro em vez de copiar os seus ficheiros.

git switch -c add-backup
printf '#!/bin/sh\nrestic backup /srv\n' > backup.sh
git add backup.sh
git commit -m "Add nightly backup"
git switch main
ls

Depois de git switch main, backup.sh desaparece da listagem. Nada foi eliminado. O ficheiro existe na branch add-backup, mas main nunca o teve. Por isso, o Git removeu-o do seu diretório de trabalho quando mudou de branch. Isto surpreende toda a gente uma vez. git switch add-backup restaura-o.

Remotos: onde o GitHub finalmente aparece

Até agora, tudo foi executado numa única máquina, sem qualquer rede. Um remoto é um URL com nome para outra cópia do mesmo repositório. O GitHub aloja uma dessas cópias por si. O nome convencional do remoto principal é origin.

Crie um repositório vazio através do site do GitHub e, em seguida, ligue-se a ele. Prefira SSH a HTTPS neste caso: uma chave SSH é um ficheiro que controla e não expira como um personal access token.

ssh-keygen -t ed25519 -C "vps-deploy"
cat ~/.ssh/id_ed25519.pub
ssh -T git@github.com

Cole a chave pública apresentada na página de chaves SSH da sua conta do GitHub e execute novamente o teste. Uma chave funcional responde Hi yourname! You've successfully authenticated, but GitHub does not provide shell access.. O GitHub não lhe fornece uma shell, por isso essa recusa indica sucesso. git@github.com: Permission denied (publickey). significa que a sua chave nunca foi apresentada ou não foi aceite. Confirme se colou o ficheiro .pub e não a chave privada que está ao lado.

git remote add origin git@github.com:yourname/vps-deploy.git
git push -u origin main

git push envia os seus commits para o remoto. -u regista que o main local acompanha o main remoto, para que mais tarde seja suficiente executar um git push simples. git clone <url> faz o inverso numa máquina nova: copia todo o repositório com o respetivo histórico e configura origin automaticamente. Um remoto HTTPS também funciona e utiliza o mesmo protocolo que qualquer página Web, o que ajuda em redes que bloqueiam a porta de saída 22. Se essa frase precisar de mais explicações, o que compõe realmente um pedido HTTP descreve os detalhes.

Pull requests, issues e forks: as partes que são do GitHub, não do Git

Tudo o que foi descrito acima é Git e funciona com qualquer servidor. As três palavras abaixo referem-se a funcionalidades do GitHub. Outros serviços copiam-nas, mas o Git não tem conhecimento delas.

Um pull request (PR) é um pedido para integrar uma branch noutra, apresentado numa página própria para discussão. Faz push de add-backup, abre um PR contra main e o site mostra as diferenças commit a commit. As pessoas comentam linhas específicas. As verificações automatizadas indicam se a branch passou ou falhou. Ao clicar em integrar, o GitHub faz a integração na sua própria cópia e depois atualiza main. O nome vem do fluxo de trabalho original, em que se pedia a um responsável pela manutenção para fazer pull da sua branch para a branch dele.

Um issue é uma discussão numerada sobre um bug ou uma tarefa. Fica na base de dados do GitHub, não no seu repositório. Isto é importante ao escolher um serviço: ao clonar o repositório, obtém todos os commits, mas não obtém nenhum issue. Para exportar os issues, é necessário chamar a API.

Um fork é uma cópia do repositório de outra pessoa no servidor, pertencente a si. Tem acesso de escrita à cópia, faz push de uma branch para ela e abre um pull request da sua cópia para o repositório original. É assim que contribui para um projeto cujos responsáveis nunca ouviram falar de si. Um fork é um clone alojado no GitHub que mantém a referência à sua origem.

O software lê os três através da mesma API que uma pessoa utiliza. Um agente de revisão de pull requests executado no seu próprio servidor monitoriza novos PRs, lê o diff e publica comentários em linhas específicas. Convenções como um ficheiro AGENTS.md na raiz de um repositório existem porque um repositório é agora lido tanto por ferramentas como por pessoas.

O que o GitHub realmente faz para o proprietário de um VPS

Comece pelo armazenamento fora do servidor. Os seus scripts de deploy e playbooks devem ficar num local diferente do servidor que configuram. Recrie o VPS a partir de uma imagem limpa, faça o clone e execute. Mantenha esse repositório privado e dê ao servidor uma deploy key: uma chave SSH registada para um único repositório, em vez de toda a sua conta, configurada como somente leitura. Se uma deploy key somente leitura for exposta, apenas um repositório fica comprometido. Se uma chave da conta for exposta, tudo o que pode enviar fica comprometido.

sudo git clone git@github.com:yourname/vps-deploy.git /srv/vps-deploy
cd /srv/vps-deploy
git pull --ff-only

--ff-only recusa-se a criar um commit de merge. Num servidor que apenas consome alterações, um merge é sempre um acidente, portanto esta flag transforma um histórico confuso no erro simples fatal: Not possible to fast-forward, aborting. Algo mudou no servidor e não devia ter mudado. Encontre a causa antes de fazer pull novamente.

Faça o clone como root e depois execute o Git como outro utilizador para obter fatal: detected dubious ownership in repository at '/srv/vps-deploy'. O Git recusa-se a ler um repositório pertencente a outro utilizador, porque um .git/config hostil pode fazer o Git executar comandos. Corrija o proprietário com chown em vez de adicionar uma exceção safe.directory, pois a exceção silencia a verificação sem remover a causa.

GitHub Actions: pipelines de compilação e implementação

Actions é o sistema de CI/CD (integração contínua e entrega contínua) do GitHub. Faça commit de um ficheiro YAML em .github/workflows/ e o GitHub executa-o quando ocorre o evento que definiu.

name: check
on:
  push:
    branches: [main]
jobs:
  shellcheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - run: sudo apt-get update && sudo apt-get install -y shellcheck
      - run: shellcheck *.sh

O ficheiro é um workflow. Um job é executado numa máquina. Um step é um comando ou uma action publicada. uses: inclui uma action de outro repositório, e @v7 fixa a respetiva versão principal (v7 é a versão atual de actions/checkout em agosto de 2026). Fixe sempre uma versão, porque uma action sem versão fixa executa código que não leu com acesso aos seus secrets.

runs-on: ubuntu-latest solicita ao GitHub uma máquina virtual nova, que é eliminada quando o job termina. Os runners padrão são gratuitos em repositórios públicos, e o plano gratuito inclui 2,000 minutos por mês para repositórios privados em agosto de 2026. Consulte a página de preços atual antes de elaborar um orçamento com base nesse valor.

Os secrets são armazenados nas definições do repositório e lidos como ${{ secrets.DEPLOY_KEY }}. Um workflow acionado por um pull request de um fork recebe um token apenas de leitura e não tem acesso a esses secrets. Caso contrário, uma pessoa externa poderia abrir um PR cuja única função fosse imprimi-los.

Executar o runner do Actions no seu próprio VPS

runs-on: self-hosted envia o job para uma máquina que você controla. A página de configurações do runner do repositório fornece uma linha de download, o endereço web do repositório e um token de registo válido por uma hora. Coloque os dois últimos em REPO_URL e RUNNER_TOKEN; depois, a configuração resume-se a três comandos.

./config.sh --url "$REPO_URL" --token "$RUNNER_TOKEN"
sudo ./svc.sh install
sudo ./svc.sh start
./svc.sh status

svc.sh status deve indicar o serviço como ativo e mostrar as linhas recentes do log. O runner abre uma ligação HTTPS de saída para o GitHub e solicita trabalho, por isso não é necessário abrir nenhuma porta de entrada para ele. svc.sh install escreve a unidade systemd, e este é o passo que muitas pessoas ignoram: sem ele, o runner termina quando a sessão SSH termina, e todos os jobs seguintes ficam em fila sem explicação. a configuração completa do runner self-hosted num VPS explica o hardening e a limpeza necessários para um runner de longa duração.

A vantagem é que um deploy já não precisa de uma chave SSH de entrada acessível pela Internet, porque o job já está a ser executado na máquina. A cache da compilação também permanece disponível entre execuções, e não existe nenhum contador de minutos a contabilizar.

Há um aviso que não é opcional. A documentação do próprio GitHub recomenda runners self-hosted apenas para repositórios privados, porque forks de um repositório público podem executar código perigoso no seu runner ao abrir um pull request. O runner executa tudo o que o ficheiro de workflow nessa branch definir. Num repositório privado em que controla quem pode fazer push, o risco é reduzido. Num repositório público, trate qualquer runner self-hosted como uma máquina na qual pessoas desconhecidas podem executar código.

É mesmo necessário usar o GitHub?

Não. Git é o padrão; GitHub é uma conveniência. Forgejo e Gitea são forjas autoalojadas. Uma forja é um servidor Git com issues e pull requests associados. Ambos são distribuídos como um único binário Go, ambos funcionam num VPS pequeno, e o Forgejo é um fork do Gitea criado em 2022 que agora alimenta o Codeberg. A migração de um repositório requer um comando, porque o protocolo de comunicação é idêntico.

git remote -v
git remote set-url origin git@git.example.com:you/vps-deploy.git
git push origin main

Cada commit é migrado, porque cada clone já contém o histórico completo. O que não é migrado é a camada construída pelo GitHub: as issues e os threads dos pull requests. O CI também não é transferido. O Forgejo tem a sua própria implementação de Actions, que lê YAML semelhante a partir de .forgejo/workflows/. A documentação é clara sobre as limitações: GitHub Actions e Forgejo Actions não são iguais, e algumas funcionalidades podem não funcionar imediatamente. Também é necessário instalar o seu próprio runner. Planeie essa etapa como uma migração, não como uma cópia.

A razão real pela qual a maioria dos projetos permanece no GitHub são os contribuidores. O código público tem de ficar num serviço onde as pessoas já tenham uma conta. Os seus scripts privados de deploy não têm esse requisito. São duas decisões separadas, e pode tomar decisões diferentes para cada uma.

O que falha primeiro e o que o erro indica

Um push é rejeitado. É apresentado o seguinte:

 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'github.com:yourname/vps-deploy.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally.

Foi feito um push desde o seu último pull, muitas vezes uma edição feita no editor web. Execute git pull --rebase para reaplicar os seus commits sobre os commits existentes e, em seguida, faça push novamente. Evite git push --force numa branch partilhada, porque remove os outros commits dessa branch no servidor.

fatal: refusing to merge unrelated histories. Executou git init localmente e também permitiu que o GitHub criasse o repositório com um README. Os dois históricos não partilham nenhum commit, por isso o Git não consegue determinar automaticamente como os combinar. A solução mais simples é clonar a cópia do GitHub para uma pasta nova e mover os seus ficheiros para lá.

error: src refspec main does not match any. A branch indicada não existe aqui. Normalmente, o repositório ainda não tem commits ou a sua branch chama-se master. git branch --show-current resolve a situação.

Um segredo chegou a um commit. Altere a credencial imediatamente. Considere-a pública a partir do momento em que foi enviada, porque forks, mirrors e vistas em cache mantêm cópias que não tem forma de eliminar.

FAQ

O GitHub é a mesma coisa que o Git?

Não. O Git é um programa de controlo de versões que instala numa máquina e funciona sem rede e sem conta. O GitHub é um serviço comercial alojado que armazena repositórios Git e acrescenta uma interface web, issues, pull requests e CI. O Git foi lançado em 2005 e o GitHub foi lançado em 2008 sobre essa base. Pode usar o Git indefinidamente sem o GitHub. Todas as funcionalidades do GitHub dependem do Git.

Preciso de uma conta do GitHub para usar o Git no meu VPS?

Não. git init, git commit e git log funcionam num servidor sem qualquer remote configurado, o que já é suficiente para controlar alterações a ficheiros /etc ou a scripts de deploy. Uma conta torna-se útil quando pretende manter uma cópia do histórico fora do servidor ou quando precisa de uma segunda máquina que possa cloná-lo. Forjas self-hosted como Forgejo e Gitea resolvem a mesma necessidade em hardware que controla, e um remote SSH simples apontado para um repositório bare noutra máquina funciona sem qualquer software de forja.

O que é um pull request?

Um pull request é um pedido para fazer merge de uma branch noutra, com uma página de discussão associada. Faz push de uma branch, abre o PR para main e o serviço apresenta as alterações commit a commit, permitindo aos revisores comentar linhas individuais e aos testes automatizados indicar sucesso ou falha. É uma funcionalidade do GitHub, não do Git, pelo que o próprio Git não tem nenhum comando para isso. Outros serviços implementam a mesma ideia, por vezes chamando-lhe merge request.

Devo executar um runner do GitHub Actions no meu próprio VPS?

Para um repositório privado, muitas vezes sim. O job é executado em hardware que já paga, não há minutos contabilizados, a cache de build permanece disponível e um deploy deixa de precisar de uma chave SSH de entrada exposta à Internet, porque o runner liga-se ao GitHub através de uma ligação de saída e solicita trabalho. Para um repositório público, o GitHub não recomenda essa configuração: qualquer pessoa pode fazer fork do seu repositório e abrir um pull request cujo workflow execute código na sua máquina.

Posso retirar os meus repositórios do GitHub mais tarde?

O código, sim, facilmente. Cada clone contém o histórico completo, pelo que git remote set-url origin <new url> seguido de um push transfere tudo o que um commit contém. O que fica para trás é a camada gerida pelo GitHub: as issues, as discussões dos pull requests e o histórico do Actions ficam na base de dados do serviço, não na sua pasta .git. As ferramentas de migração podem copiar issues através da API, e os ficheiros de workflow normalmente precisam de ser editados para funcionarem com a CI do novo serviço. Ter isto em conta é um argumento para manter a documentação importante no repositório, em vez de a colocar em threads de issues.

#github#git#version-control#ci-cd#developer-tools