Dia 24: Git para Sysadmins — Repos, Branches, Tags e Workflows
O Git deixou de ser uma ferramenta exclusiva de programadores para se tornar peça fundamental na gestão de configuração de servidores. Rastreio de mudanças em /etc, versionamento de playbooks Ansible, versionamento de scripts de automatização e auditoria de quem alterou o que e quando — tudo isto é trabalho de sysadmin moderno que o Git resólve de forma nativa. Este artigo cobre a configuração inicial, operações do dia-a-dia, branches e tags, e workflows práticos para gerir configuração de infraestrutura com Git, com comandos validados contra a documentação oficial (git-scm.com/docs).
- Instalar e Configurar o Git
- Repositório Local — init, clone e add
- Commits — Mensagens, Amend e Log
- Branches — Criação, Mudança e Merge
- Tags — Versionamento de Configuração
- Repositórios Remotos — push, pull e fetch
- Stash — Guardar Trabalho Temporariamente
- Workflow de Configuração com /etc em Git
- Erros Comuns
- Checklist de Verificação
Instalar e Configurar o Git
O Git está disponível em praticamente todas as distribuições Linux. Antes de qualquer operação, convém instalar a versão mais recente disponível nos repositórios oficiais e configurar a identidade do útilizador — cada commit regista nome e e-mail, e essa informação fica permanente no histórico do repositório. Num contexto de sysadmin, onde multiplas pessóas podem administrar o mesmo servidor, configurar identidades correctas é essencial para auditoria.
Instalar no Ubuntu/Debian e derivados:
sudo apt update && sudo apt install git
Instalar no RHEL/Rocky/Alma/Fedora:
sudo dnf install git
Verificar a versão instalada:
git --version
Configurar identidade globalmente (aplica-se a todos os repositórios do útilizador actual). A opção --global grava as definições em ~/.gitconfig:
git config --global user.name "Maria Silva"
git config --global user.email "[email protected]"
git config --global init.defaultBranch main
git config --global core.editor nano
A directiva init.defaultBranch main define o nome do ramo inicial — anteriormente era master por omissão, mas a comunidade mudou para main em 2020 (documentação git-config). Configurar o editor (neste exemplo nano) garante que comandos como git commit abrem um editor familiar em vez do vi predefinido.
Repositório Local — init, clone e add
Um repositório Git pode ser criado de dois modos: git init cria um repositório novo num directório vazio ou existente; git clone copia um repositório remoto completo, incluindo todo o histórico. Para sysadmins que começam a versionar configuração de um servidor já existente, git init no directório de configuração e o ponto de partida.
Inicializar um repositório dentro de um directório de configuração:
cd /etc/nginx
sudo git init
sudo git add -A
sudo git commit -m "Estado inicial da configuração nginx"
Clonar um repositório remoto existente (por exemplo, um repositório de playbooks Ansible):
git clone https://github.com/empresa/ansible-playbooks.git
cd ansible-playbooks
Adicionar ficheiros ao staging área — o passó intermédio entre editar e confirmar. O Git exige que se adicionem explicitamente as mudanças que se querem incluir no próximo commit, o que evita confirmar ficheiros acidentais:
git add nginx.conf # um ficheiro especifico
git add configs/ # um directório inteiro
git add -A # todas as mudanças (adições, modificacoes, remocoes)
git add -p # interactivo: escolher pedaco a pedaco
Verificar o estádo do repositório a qualquer momento:
git status
O comando git status mostra três secções: ficheiros modificados ainda não adicionados ao staging, ficheiros no staging prontos para commit, e ficheiros não rastreados (untracked). A opção -p no git add permite revisar cada alteração individualmente antes de confirmar — útil quando se mexeu em varios ficheiros mas só se quer fazer commit de parte das mudanças (documentação git-add).
Commits — Mensagens, Amend e Log
O commit é a unidade atómica de mudança no Git. Cada commit representa um snapshot completo do estádo do repositório num momento específico, com uma mensagem descritiva, autor, data e hash único. Para sysadmins, o commit é o equivalente a um registo de auditoria — a mensagem deve descrever o que mudou e porquê, não apenas o quê.
Criar um commit com mensagem inline:
git commit -m "Aumentar worker_processes para 4 no nginx"
git commit -m "Titulo curto" -m "Descricao longa com contexto
e razao da mudança"
Corrigir o último commit (se ainda não foi enviado para remoto). O --amend substitui o commit anterior por um novo que inclui as mudanças actuais. Util para corrigir uma mensagem esquecida ou adicionar um ficheiro que ficou de fora:
git add ficheiro-esquecido.conf
git commit --amend -m "Nova mensagem corrigida"
git commit --amend em commits que já foram enviados para um repositório remoto com git push. O amend reescreve o histórico, criando um hash novo que entra em conflito com a copia remota.
Visualizar o histórico de commits. O git log é a ferramenta de auditoria do Git — mostra quem mudou o que, quando e porquê:
git log # histórico completo
git log --oneline # uma linha por commit
git log --oneline --graph # com ramificacao visual
git log --author="Maria" # filtrar por autor
git log --since="2026-01-01" # filtrar por data
git log -p ficheiro.conf # histórico com diff de um ficheiro
git log --stat # com estatisticas de mudanças
A opção --oneline --graph é particularmente útil em ambientes com multiplos ramos: mostra a árvore de merges e pontos de ramificação de forma compacta. O git log -p <ficheiro> permite rastrear todas as mudanças a um ficheiro específico ao longo do tempo — essencial para perceber quando uma configuração deixou de funcionar (documentação git-log).
Branches — Criação, Mudança e Merge
Branches (ramos) permitem trabalhar em mudanças paralelas sem afectar o ramo principal. Num contexto de sysadmin, um branch pode representar uma alteração de configuração em teste, um upgrade de versão ou uma correção urgente — tudo isólado do ramo main que reflecte o estádo em produção. Quando as mudanças são validadas, faz-se merge para main.
Criar e mudar para um novo branch. A analogia: o branch é como uma via paralela na linha ferrea — pode-se construir e testár nessa via sem interromper o trafego na via principal:
git branch upgrade-nginx # criar branch
git checkout upgrade-nginx # mudar para o branch
# ou em um unico passo:
git checkout -b upgrade-nginx # criar + mudar
Listar branches existentes:
git branch # branches locais
git branch -a # incluindo remotos
git branch -v # com ultimo commit de cada branch
Fazer merge de um branch de volta para main. Primeiro muda-se para o ramo de destino (main), depois incorpora-se o branch com as alterações:
git checkout main
git merge upgrade-nginx
Eliminar um branch depois de merged:
git branch -d upgrade-nginx # so permite se ja tiver merge
git branch -D upgrade-nginx # forca eliminacao (descarta mudanças)
O Git distingue entre merge fast-forward (quando o branch de destino não teve commits novos desde a criação do branch — o ponteiro avança simplesmente) e merge com merge commit (quando ambos os ramos evoluiram independentemente — cria um commit de junção). Em ambos os casós, o conteúdo final é o mesmo; a diferença está no histórico (documentação git-merge).
Tags — Versionamento de Configuração
Tags marcam pontos específicos no histórico do repositório, tipicamente versões ou releases. Para sysadmins, uma tag pode representar “configuração estável antes do upgrade”, “versão colocada em produção em produção na data X” ou “ponto de rollback conhecido”. Ao contrario dos branches, as tags não se movem — apontam sempre para o mesmo commit.
Criar uma tag leve (lightweight) e uma tag anotada (recomendada — inclui autor, data e mensagem):
git tag v1.0 # tag leve
git tag -a v1.0 -m "Configuracao estável pre-upgrade" # tag anotada
git tag -a v1.1 9f2a3b1 -m "Hotfix SSL timeout" # tag num commit passado
Listar e consultar tags:
git tag # listar todas
git tag -l "v1.*" # filtrar por padrao
git show v1.0 # ver detalhes da tag anotada
Fazer checkout para uma tag específica — útil para auditoria ou rollback. Isto coloca o repositório em estádo detached HEAD (sem branch ativo):
git checkout v1.0
# para voltar ao estado normal:
git checkout main
Enviar tags para o repositório remoto (tags não são enviadas automaticamente com git push normal):
git push origin v1.0 # uma tag especifica
git push origin --tags # todas as tags
As tags anotadas são preferíveis porque guardam metadados (autor, data, mensagem) que permitem perceber o contexto da marcação meses depois. Uma tag leve é apenas um apontador — sem informação adicional (documentação git-tag).
Repositórios Remotos — push, pull e fetch
Repositórios remotos permitem sincronizar mudanças entre maquinas, fazer backup da configuração e colaborar. Um sysadmin tipicamente tem um repositório central (GitHub, GitLab, Gitea auto-hospedado) para o qual envia as mudanças locais e do qual recebe actualizações feitas por colegas.
Adicionar um repositório remoto e enviar mudanças:
git remote add origin https://github.com/empresa/config-servidor.git
git remote -v # listar remotos
git push -u origin main # enviar branch main e definir upstream
git push # envios subsequentes são mais simples
git push origin upgrade-nginx # enviar branch especifico
Receber mudanças do remoto. O git fetch descarrega mas não integra; o git pull descarrega e integra automaticamente (equivale a fetch + merge):
git fetch origin # descarregar sem integrar
git pull # descarregar e integrar (se upstream definido)
git pull origin main # especificar remoto e branch explicitamente
Clonar um repositório com histórico reduzido (útil para CI/CD onde só interessa o estádo final):
git clone --depth 1 https://github.com/empresa/playbooks.git
A opção -u (equivalente a --set-upstream) no git push cria a assóciação entre o branch local e o remoto, permitindo que comandos futuros como git pull saibam automaticamente de onde descarregar (documentação git-push).
Stash — Guardar Trabalho Temporariamente
O git stash guarda mudanças não confirmadas numa pilha temporária, limpando a árvore de trabalho. É útil quando se precisa de mudar de branch ou fazer pull sem perder trabalho em cursó. Pense no stash como uma gaveta onde se guarda o que estáva a fazer para retomar mais tarde.
git stash # guardar mudanças atuais
git stash list # ver stashes guardados
git stash pop # restaurar e remover da pilha
git stash apply # restaurar mas manter na pilha
git stash drop # remover sem restaurar
git stash save "WIP: tunings SSL" # com etiqueta descritiva
A diferença entre pop e apply: pop aplica e remove o stash da pilha (operação destrutiva se houver conflitos); apply aplica mas mantem o stash, permitindo re-aplicar noutro branch se necessario (documentação git-stash).
Workflow de Configuração com /etc em Git
Um padrão comum em administração de sistemas e versionar o directório /etc (ou subdirectórios específicos como /etc/nginx, /etc/ansible) num repositório Git. Isto da rastreio total de mudanças, capacidade de rollback e auditoria de quem alterou cada ficheiro. Existem ferramentas dedicadas como etckeeper que automatizam este processó, mas o método manual é simples e funciona em qualquer distribuição.
Configurar um repositório Git em /etc com .gitignore selectivo. Nem tudo em /etc deve ser versionado — ficheiros com segredos (chaves privadas, palavras-passe) devem ser excluídos:
cd /etc
sudo git init
# Criar .gitignore para excluir ficheiros sensiveis
sudo tee .gitignore </dev/null <<'EOF'
# Segredos - NAO versionar
shadow
shadow-
gshadow
gshadow-
ssh/
ssl/private/
letsencrypt/
wireguard/
# Ficheiros temporarios
*.tmp
*.bak
*~
EOF
sudo git add .gitignore
sudo git commit -m "Inicial: repo /etc com .gitignore"
sudo git add -A
sudo git commit -m "Snapshot inicial de configuração /etc"
Rotina diaria do sysadmin com Git em /etc. Depois de fazer uma alteração de configuração, confirmar imediatamente com uma mensagem descritiva:
# Editar configuração
sudo nano /etc/nginx/nginx.conf
sudo nginx -t # testar sintaxe
sudo systemctl reload nginx # aplicar
# Confirmar mudança no Git
cd /etc
sudo git add nginx/nginx.conf
sudo git commit -m "Aumentar worker_connections para 1024 no nginx"
sudo git push # se remoto configurado
Auditar quem mudou o que. O git blame mostra quem alterou cada linha de um ficheiro e em que commit:
cd /etc
sudo git blame nginx/nginx.conf
sudo git log -p nginx/nginx.conf | head -100
/etc contem ficheiros com permissões sensíveis (chaves SSH, certificados privados, hashes de palavras-passe em /etc/shadow). O .gitignore deve ser revisto cuidadosamente antes de enviar o repositório para um remoto. Considerar usar git-crypt ou sóps para encriptar ficheiros sensíveis que precisam de ser versionados.
Erros Comuns
A tabela seguinte reune os problemas mais frequentes quando se começa a usar Git para gestão de configuração, com causa e sólução para cada um.
| Problema | Causa | Solução |
|---|---|---|
| fatal: not a git repository | Executar comandos git fora de um repositório ou sem .git no directório actual |
Verificar com pwd e ls -la .git; se necessario, git init |
| error: Your local changes would be overwritten | Tentar git pull ou git checkout com mudanças por confirmar |
Fazer git stash antes, ou git commit as mudanças locais primeiro |
| fatal: refusing to merge unrelated histories | Os repos local e remoto foram criados independentemente sem histórico comum | Usar git pull origin main --allow-unrelated-histories (cuidado: pode criar conflitos extensós) |
| CONFLICT (content): Merge conflict in ficheiro | Dois ramos modificaram as mesmas linhas de um ficheiro de forma diferente | Abrir o ficheiro, procurar marcadores <<<<<<< e >>>>>>>, escolher a versão correcta, git add e git commit |
| error: src refspec main does not match any | Tentar fazer push sem nenhum commit no repositório | Fazer pelo menos um commit antes de git push |
| fatal: Authentication failed | Credenciais incorrectas ou token expirado (GitHub usa PAT desde 2021) | Gerar Persónal Access Token no GitHub/GitLab; usar SSH keys como alternativa (docs git-clone) |
| warning: LF will be replaced by CRLF | Mistura de terminações de linha entre Linux (LF) e Windows (CRLF) | Configurar git config --global core.autocrlf input em Linux |
Checklist de Verificação
Antes de considerar o repositório pronto para usó em produção, verificar cada ponto:
- Git instalado — confirmar com
git --version(2.x ou superior). - Identidade configurada —
git config user.nameegit config user.e-maildevolvem valores correctos. - .gitignore criado — ficheiros sensíveis (shadow, chaves privadas, certificados) estão excluídos.
- Branch inicial e main —
git branchmostra* main. - Pelo menos um commit existe —
git log --onelinenão devolve erro. - Remoto configurado (se aplicavel) —
git remote -vmostra origin com URL correcta. - Push testádo —
git push -u origin maincompleta sem erros. - Autocrlf configurado —
git config core.autocrlf inputpara evitar avisós de terminação de linha.
Artigos Relacionados
- Dia 23: Ansible — Playbooks, Inventários e Idempotência — O Git é a base natural para versionar playbooks Ansible e controlar mudanças na infraestrutura.
- Dia 22: Docker Compose e Multi-Service Stacks — ficheiros docker-compose.yml beneficiam de versionamento Git para rastrear mudanças de configuração de containers.
- Dia 13: Cron e Agendamento — crontab, at, systemd timers — Scripts agendados devem ser versionados em Git para auditoria e rollback.
- Dia 7: Systemd — Services, Timers, Targets e journalctl — Ficheiros de unit systemd podem ser geridos num repositório Git para sincronização entre servidores.
- Dia 10: SSH — Configuração, Chaves, Tunnels e Hardening — A configuração SSH (
/etc/ssh/sshd_config) é candidata ideal para versionamento Git.