CommunityPesquisa e Análise de Dadosgithub.com

dragon-fish/versionamento-arquivos-configuracao

Versionamento automático de arquivos de configuração locais via git + observadores de sistema de arquivos. Uma skill plug-and-play para agentes de codificação de IA (Claude Code, Codex, Gemini CLI, etc.).

O que é versionamento-arquivos-configuracao?

Esta skill, 'Config File Versioning', implementa um sistema de versionamento automático para arquivos de configuração críticos e pequenos que você não quer que sejam sobrescritos silenciosamente. Ela utiliza observadores de sistema de arquivos do sistema operacional (como launchd no macOS e systemd path units no Linux) para monitorar arquivos específicos. Quando uma alteração real de conteúdo é detectada, a skill gera automaticamente um commit git em um repositório local separado (usando a técnica de 'separate-git-dir'), garantindo que o histórico do arquivo seja preservado mesmo se o diretório de trabalho original for deletado. Um recurso de throttling (padrão de 10 segundos) evita commits excessivos durante alterações rápidas ou múltiplas. A skill é útil para desenvolvedores que desejam uma proteção simples e eficaz contra a perda de configurações importantes, oferecendo a capacidade de reverter para qualquer versão histórica com comandos git. É suportada em macOS e Linux (via systemd), com alternativas para outros sistemas.

Funciona com✓Claude Code✓Codex CLI~Cursor✓Gemini CLI
npx skills add dragon-fish/config-file-versioning

Installed? Explore more Pesquisa e Análise de Dados skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Skill: Versionamento de Arquivos de Configuração

Faz backup automático de versões de arquivos de configuração local que são "pequenos + importantes + que você não quer que sejam sobrescritos silenciosamente".

Cada vez que o conteúdo de um arquivo monitorado muda de fato, um commit git é gerado automaticamente em até 10 segundos, mantido em um repositório local separado (separate-git-dir). Reverta para qualquer versão anterior com um comando.


Quando Usar

Use esta skill quando o usuário apresentar qualquer um dos seguintes sinais de gatilho:

  • "Adiciona versionamento/backup automático para "
  • "Não quero que algum programa sobrescreva meu de novo"
  • "Faz commit automático quando mudar"
  • "Usa <diretório de backup existente> para fazer backup de "
  • O usuário menciona que uma config importante foi perdida por sobrescrita acidental e pergunta como prevenir no futuro

Não é adequado para:

  • Repositórios de código grandes (use o fluxo de trabalho git normal)
  • Sincronização entre máquinas (esta skill só mantém histórico local; para sincronizar, adicione Syncthing ou git push manual para um remote privado)
  • Arquivos que mudam com alta frequência (.bash_history, history.jsonl, etc. — gerariam commits em massa)

Visão Geral da Arquitetura

   <Arquivo Protegido>           (local real, ex.: ~/.ssh/config)
        │ alteração
        ▼
   Observador de Sistema de Arquivos (Nível de SO)
   ┌──────────────────────────────┬──────────────────────┬─────────┐
   │ macOS: launchd WatchPaths    │ Linux: systemd .path │ Outros  │
   └──────────────────────────────┴──────────────────────┴─────────┘
        │ disparo (após throttle de 10s)
        ▼
   auto-commit.sh
        │ git add -A → só faz commit se houver diff no staged
        ▼
   <BACKUP_ROOT>/<dominio>-config.git/   ← repositório git real (separate-git-dir)
        ▲
        │ conectado pelo ".git" (uma linha "gitdir: <caminho>") na raiz da worktree

Pontos-chave de design:

DesignMotivo
Cada domínio de config tem seu próprio repositório (não unificado em um grande repositório)Histórico limpo; pode ser ativado/desativado/migrado independentemente
separate-git-dirQuando a worktree inteira é deletada por algum programa, o histórico continua vivo em <BACKUP_ROOT>
.gitignore de lista branca (* + !<arquivo_protegido>)Evita que dados de runtime, cache ou arquivos temporários no mesmo diretório sejam incluídos acidentalmente
Observação orientada a eventos + throttle (padrão 10s)Sem processos residentes em idle; evita múltiplos commits para uma única escrita
Verificação git diff --cached --quiet no script de commitSai silenciosamente se o conteúdo realmente não mudou (apenas mtime alterado)

Passos de Implementação

Passo 0: Alinhar 4 variáveis com o usuário

VariávelSignificadoValor Padrão Recomendado
<DOMINIO>Abreviação do domínio de config (apenas letras minúsculas, números e hífens; usado como nome de diretório/sufixo de label)Discutir com o usuário; ex.: ssh / zsh / vscode / claude
<WORKTREE>Caminho absoluto do diretório onde está o arquivo protegido (raiz da git worktree)Geralmente o diretório onde está o arquivo monitorado
<ARQUIVOS>Lista de caminhos absolutos a serem monitorados (≥ 1)Especificado pelo usuário
<BACKUP_ROOT>Diretório raiz para armazenar repositórios, scripts e templates de serviçoPerguntar obrigatoriamente: sugestão padrão ~/.local/share/config-versioning/<DOMINIO>/ (convenção XDG); se o usuário já tiver um diretório dedicado para backup/sincronização (ex.: ~/Documentos/backups/, ~/Sync/..., seu próprio diretório sandbox), deixar o usuário decidir

Passo 1: Criar diretório de dados + iniciar repositório git

mkdir -p "<BACKUP_ROOT>"

mkdir -p "<WORKTREE>"
cd "<WORKTREE>" && git init -q -b main

Passo 2: Escrever .gitignore de lista branca

Copie templates/gitignore-whitelist para <WORKTREE>/.gitignore e adicione, para cada item em <ARQUIVOS>, uma linha !<caminho-relativo> relativa a <WORKTREE>.

Exemplo: worktree=~/.ssh, proteger ~/.ssh/config e ~/.ssh/known_hosts, adicione:

!config
!known_hosts

Passo 3: Commit inicial

cd "<WORKTREE>"
git add -A
git commit -q -m "chore: snapshot inicial da config <DOMINIO>"

Não use -c user.name/-c user.email para forçar sobrescrita — deixe o git usar a configuração global do usuário. O repositório é puramente local, não é feito push, o autor do commit é irrelevante.

Passo 4: Mover o diretório .git para <BACKUP_ROOT> e criar ponteiro gitdir

GITDIR="<BACKUP_ROOT>/<DOMINIO>-config.git"
mv "<WORKTREE>/.git" "$GITDIR"
echo "gitdir: $GITDIR" > "<WORKTREE>/.git"
git -C "$GITDIR" config core.worktree "<WORKTREE>"

Passo 5: Copiar e adaptar o script auto-commit

Copie templates/auto-commit.sh para <BACKUP_ROOT>/auto-commit.sh e substitua os 2 placeholders:

PlaceholderSubstituir por
__WORKTREE__Caminho absoluto de <WORKTREE>
__LOG__Caminho do log; sugestão: ~/Library/Logs/config-file-versioning.log (macOS) ou ~/.local/state/config-file-versioning.log (Linux)

chmod +x no arquivo.

Passo 6: Instalar camada de observação (por sistema operacional)

6a. macOS (launchd LaunchAgent)

Copie templates/launchagent.plist, substitua os placeholders:

PlaceholderSubstituir por
__LABEL__local.<USUARIO>.<DOMINIO>-config-watch (prefixo local. evita conflitos; <USUARIO> usar $USER)
__SCRIPT_PATH__Caminho absoluto de <BACKUP_ROOT>/auto-commit.sh
__WATCH_PATHS__Cada arquivo em <ARQUIVOS> dentro de um par <string>...</string>, agrupados em <array>
__LOG__Mesmo do passo 5

Salve em dois lugares (garantindo portabilidade do diretório):

  1. <BACKUP_ROOT>/<LABEL>.plist (template de backup)
  2. ~/Library/LaunchAgents/<LABEL>.plist (ativo)

Carregar:

launchctl unload "$HOME/Library/LaunchAgents/<LABEL>.plist" 2>/dev/null
launchctl load   "$HOME/Library/LaunchAgents/<LABEL>.plist"
launchctl list | grep "<LABEL>"   # verificar se está registrado

6b. Linux (systemd path unit)

Copie templates/systemd.path e templates/systemd.service para ~/.config/systemd/user/, renomeando para <DOMINIO>-config-watch.path e <DOMINIO>-config-watch.service, substituindo os placeholders conforme os arquivos. Depois:

systemctl --user daemon-reload
systemctl --user enable --now <DOMINIO>-config-watch.path

6c. Outros / Alternativa

Qualquer ferramenta que "observe + execute comando" serve:

  • gitwatch (shell cross-platform): brew install gitwatch ou apt install gitwatch
  • fswatch + daemon próprio: fswatch <ARQUIVOS> | xargs -n1 <BACKUP_ROOT>/auto-commit.sh
  • inotifywait (Linux) + loop shell

Hospede o processo do observador no gerenciador de serviços da plataforma (OpenRC, runit, launchd, systemd).

Passo 7: Teste ponta a ponta (obrigatório, não pule)

Altere um arquivo monitorado, espere 2 segundos a mais que o intervalo de throttle, e verifique se o log e o git log foram atualizados. Primeiro injete um campo temporário, depois limpe-o, esperando 2 commits:

# Ex.: adicionar chave temporária _autoCommitTest em arquivo JSON
# sleep 12 (assumindo throttle=10s)
tail -2 "<LOG>"
git -C "<WORKTREE>" log --oneline | head -3

Passo 8: Escrever README

Cada <BACKUP_ROOT> deve conter um README.md para facilitar migrações futuras. Deve incluir no mínimo:

  • Propósito (por que isso existe)
  • Tabela de arquivos
  • Comandos do dia a dia (ver histórico, reverter, status do observador, ver log)
  • Manutenção (adicionar novo arquivo monitorado, alterar intervalo de throttle)
  • Passos para recriar em uma máquina nova
  • Passos completos de desinstalação

Anti-padrões (evitar explicitamente)

❌ Errado✅ Correto
Colocar múltiplos domínios de config no mesmo repositório gitUm repositório por domínio
Manter .git dentro da worktreeMover para <BACKUP_ROOT> usando ponteiro gitdir
Usar .gitignore de lista negraUsar .gitignore de lista branca
Pular o teste ponta a ponta antes de entregarObrigatório, confirmar que o commit realmente é gerado
Colocar arquivos plist/service apenas no diretório do sistema, sem template em <BACKUP_ROOT>Colocar em ambos, garantindo que o diretório seja autocontido e portátil
Fazer push para remote público no commitProibido — config pode conter tokens/informações sensíveis, repositório puramente local
Hardcodar git user.name/email no auto-commit.shDeixar para a configuração global do git; o script não deve conter informações pessoais
Usar KeepAlive=true para rodar fswatch residentePriorizar observação orientada a eventos (WatchPaths / .path unit), sem processo residente

Tratamento de Casos Limite

  • Diretório worktree não existe: Execute mkdir -p primeiro. Se for a primeira vez, o arquivo monitorado pode nem existir — pergunte se deve criar um arquivo vazio.
  • Arquivo monitorado é um link simbólico: No observador, monitore tanto o caminho do link quanto o caminho real de destino, para evitar que alguns métodos de escrita não disparem um dos tipos.
  • Arquivo monitorado é binário: Funciona normalmente (git armazena blob), mas o diff não mostra o conteúdo.
  • Mesmo label/serviço já existe: Primeiro faça unload/disable do antigo, depois carregue o novo.
  • Múltiplas escritas dentro do intervalo de throttle: Múltiplas alterações dentro da janela de throttle são consolidadas em um único commit (é o comportamento desejado).
  • Escrita atômica (write-temp + rename): launchd WatchPaths geralmente dispara corretamente; se a forma de escrever de algum programa específico causar perda de commit, oriente o usuário a usar KeepAlive + loop principal de gitwatch/fswatch.

Arquivos de Template


Filosofia de Design

  1. Visível + Legível + Editável manualmente: O histórico de versões é um repositório git; qualquer pessoa que entenda git pode localizar/reverter, sem depender de GUI.
  2. Orientado a eventos ≫ Polling: Reduz consumo de CPU/disco em idle.
  3. À prova de falhas: O script de commit não tem efeitos colaterais — falhas de cd, diff vazio etc. saem silenciosamente, sem danificar a worktree.
  4. Diretório autocontido: <BACKUP_ROOT> contém dados + scripts + templates plist/unit + README; copie o diretório inteiro e recrie em uma máquina nova.
  5. Não faz push: Evita enviar configurações privadas para qualquer remote; para backup remoto, use soluções em nível de arquivo (Time Machine / Backblaze / Syncthing com criptografia).

Habilidades Relacionadas