← todos os artigos
/// Coding & Infraestrutura ///

Como Automatizar a Sincronização Entre um Repositório Git Local e um Servidor (S)FTP

Aprenda a montar um sistema Python que compara, envia e baixa arquivos entre um repositório Git local e um servidor FTP ou SFTP — com relatório HTML automático e commits inteligentes, sem depender de CI/CD externo.

12 de December de 2025 · ~7 min de leitura · #git #ftp #sftp ·

Em muitos ambientes corporativos — especialmente em estruturas legadas ou altamente restritas — o uso de Git hospedado (GitHub, GitLab, Bitbucket) ou pipelines de CI/CD é simplesmente proibido. Mesmo assim, o desenvolvimento continua acontecendo, e manter arquivos atualizados no servidor pode se transformar em um trabalho cansativo, repetitivo e propenso a erros.

Fazer upload manual via FTP, baixar alterações feitas diretamente no servidor e tentar conciliar tudo com o repositório Git local rapidamente se torna um pesadelo. A boa notícia: é possível automatizar todo esse fluxo usando apenas o seu computador e acesso ao servidor (S)FTP.

Neste artigo você vai aprender como montar um sistema que:

  • 🔄 Compara arquivos entre Git local e FTP
  • ⬇️ Baixa arquivos quando o servidor está mais atualizado
  • ⬆️ Envia arquivos quando o Git local está mais novo
  • 📝 Gera relatórios HTML ou TXT
  • 🏷️ Registra automaticamente mudanças no Git

Tudo isso sem depender de nenhum serviço externo.

· · ·
01

🎯 Por que automatizar?

Imagine este cenário:

  • Um time precisa atualizar arquivos em um servidor legado via FTP
  • Vários desenvolvedores têm acesso ao mesmo ambiente
  • Mudanças às vezes são feitas diretamente no servidor por outro departamento
  • Não existe integração contínua
  • Não existe ambiente de testes

Sem automação, esse fluxo depende de disciplina — e sorte. Com automação, você ganha:

Controle
Todas as alterações passam por um processo rastreável, eliminando a dúvida de "quem mexeu nisso?"
Segurança
Nenhuma alteração é perdida. O Git registra o histórico de tudo que entra e sai do servidor.
Histórico de auditoria
Cada sincronização gera um relatório e um commit, criando trilha completa para auditoria interna.
Repetibilidade
O mesmo script executa sempre da mesma forma, independentemente de quem o rodar ou quando.

Automatizar a sincronização transforma um processo arriscado em um fluxo de trabalho consistente.

· · ·
02

🧩 Como funciona a lógica da sincronização?

A ideia é simples e poderosa: comparar a versão do arquivo no Git com a versão no servidor (S)FTP.

Sempre que um arquivo é encontrado, três cenários são possíveis:

  1. A versão remota é mais nova → Baixar e registrar no Git
  2. A versão local é mais nova → Enviar para o FTP e registrar no relatório
  3. As versões são iguais → Ignorar para poupar tempo

Esse fluxo garante que sempre exista um único ponto de verdade, mesmo em ambientes descentralizados.

📊 Diagrama do fluxo

[Git Local] → Verifica arquivo → [FTP]

              ↙      ↓      ↘
         FTP é novo  Igual  Git é novo

         Baixar       Nada      Enviar
         Commit        |         |
                   Relatório ←-----
Substitua o diagrama ao publicar
O diagrama acima é uma representação em texto. Para a publicação final, substitua pelo arquivo sync-flow-diagram.svg com o fluxo visual.
· · ·
03

⚙️ Comparando arquivos: hash, timestamps e integridade

Para decidir qual versão está mais atual, é possível usar diferentes estratégias:

✔️ Hash (MD5 / SHA1)
Garantia total de integridade — detecta qualquer mudança. Ponto negativo: requer baixar o arquivo remoto para calcular o hash.
✔️ Timestamp (MDTM)
Extremamente rápido e não requer baixar o arquivo. Depende do relógio correto no servidor — pode gerar falsos positivos em servidores com horário desatualizado.
✔️ Arquivo de versão separado
Ideal para sistemas com muitos arquivos e facilita auditorias. Requer manutenção manual do arquivo de versão.

No exemplo a seguir utilizamos hash + timestamp para máxima confiabilidade.

· · ·
04

🐍 Exemplo de automação com Python

O script abaixo percorre arquivos rastreados pelo Git, compara com a versão existente no FTP, baixa ou envia conforme a necessidade, gera um relatório HTML e adiciona commits automáticos quando há atualizações vindas do servidor.

📌 Código completo (pronto para uso)

import os
import hashlib
from ftplib import FTP
from datetime import datetime
from git import Repo

# CONFIG
LOCAL_PATH  = './my-local-repo'
FTP_HOST    = 'ftp.example.com'
FTP_USER    = 'youruser'
FTP_PASS    = 'yourpass'
REMOTE_PATH = '/remote/dir'

# Git Repo
repo   = Repo(LOCAL_PATH)
report = []

# Connect to FTP
ftp = FTP(FTP_HOST)
ftp.login(FTP_USER, FTP_PASS)
ftp.cwd(REMOTE_PATH)

def md5_local(file_path):
    with open(file_path, 'rb') as f:
        return hashlib.md5(f.read()).hexdigest()

def md5_remote(filename):
    from io import BytesIO
    buf = BytesIO()
    try:
        ftp.retrbinary(f'RETR {filename}', buf.write)
        return hashlib.md5(buf.getvalue()).hexdigest()
    except:
        return None

for file in repo.git.ls_files().split('\n'):
    local_file  = os.path.join(LOCAL_PATH, file)
    local_hash  = md5_local(local_file)
    remote_hash = md5_remote(file)

    if remote_hash is None:
        # Upload new file
        with open(local_file, 'rb') as f:
            ftp.storbinary(f'STOR {file}', f)
        report.append(f"[UPLOAD] {file} was not on remote.")

    elif remote_hash != local_hash:
        # Compare timestamps
        remote_time = ftp.sendcmd(f"MDTM {file}")[4:].strip()
        remote_dt   = datetime.strptime(remote_time, '%Y%m%d%H%M%S')
        local_dt    = datetime.fromtimestamp(os.path.getmtime(local_file))

        if remote_dt > local_dt:
            # Download newer remote version
            with open(local_file, 'wb') as f:
                ftp.retrbinary(f'RETR {file}', f.write)
            repo.index.add([file])
            repo.index.commit(f"[SYNC] Pulled newer {file} from FTP")
            report.append(f"[DOWNLOAD] {file} - FTP was newer")
        else:
            # Upload newer local version
            with open(local_file, 'rb') as f:
                ftp.storbinary(f'STOR {file}', f)
            report.append(f"[UPLOAD] {file} - Local was newer")

    else:
        report.append(f"[SKIP] {file} is up-to-date")

# Write report
with open(os.path.join(LOCAL_PATH, 'sync-report.html'), 'w') as report_file:
    report_file.write("<h2>Sync Report</h2><ul>")
    for line in report:
        report_file.write(f"<li>{line}</li>")
    report_file.write("</ul>")

ftp.quit()
print("✅ Sync complete.")
Dependências necessárias
Instale as dependências antes de rodar: pip install gitpython. A biblioteca ftplib já faz parte da biblioteca padrão do Python.
· · ·
05

📄 Relatório automático

O script gera automaticamente um arquivo sync-report.html contendo:

  • Arquivos enviados ao servidor
  • Arquivos baixados do servidor
  • Arquivos ignorados (sem alteração)
  • Data e hora da execução
  • Resumo da atividade

Esse relatório pode ser arquivado, enviado por e-mail ou compartilhado com outros times de TI para fins de auditoria.

· · ·
06

🚀 Possíveis evoluções

Se quiser tornar o sistema mais completo, você pode implementar as seguintes melhorias:

🔧 Versão SFTP com Paramiko
Ideal para ambientes que exigem SSH. A biblioteca paramiko oferece suporte completo ao protocolo SFTP com autenticação por chave pública.
⏲️ Execução automática
Agende o script via Windows Task Scheduler ou cron no Linux/macOS para sincronização periódica sem intervenção manual.
📤 Notificações integradas
Envie o relatório por e-mail, Slack ou Microsoft Teams ao término de cada execução — mantenha toda a equipe informada automaticamente.
🧭 Dashboard local
Construa uma interface web simples para visualizar o histórico de sincronizações e os relatórios gerados anteriormente.
🧪 Versionamento por arquivo
Mantenha um arquivo de versão individual por asset. Útil em ambientes com milhares de arquivos onde o hash completo seria muito lento.

Sincronização confiável em ambientes legados

Automatizar a sincronização entre o repositório Git local e um servidor (S)FTP elimina o risco de conflitos, perda de alterações e inconsistências. O processo se torna mais seguro, organizado e confiável — mesmo sem CI/CD ou serviços hospedados.

Se você trabalha em ambientes legados ou restritos, essa solução representa um enorme avanço em produtividade e segurança operacional. O investimento em configurar o script uma única vez se paga rapidamente em tempo economizado e erros evitados.

 Categorias

 Tópicos deste artigo

URL copiada!