Skip to content

About

CLI único em Go para operar o git em vários projetos ao mesmo tempo: atualizar as branches principais, criar branches novas, alternar entre branches, abrir PRs com mensagem gerada pelo `claude`, revisar e corrigir os apontamentos do PR.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

12 Commits

Folders and files

Repository files navigation

git-manager

CLI único em Go para operar o git em vários projetos ao mesmo tempo: atualizar a branch principal, criar branches novas, alternar entre branches, abrir PRs com mensagem gerada pelo claude, revisar e corrigir os apontamentos do PR.

Instalação

make build           # gera ./bin/git-manager
make install         # instala em ~/.local/bin e cria o atalho gm

Requisitos: Go 1.26+, git, e — para as tarefas pr, review e fix — o claude no PATH. As tarefas pr, draft e ready também precisam, conforme o provider de cada projeto:

  • github: o gh (GitHub CLI) autenticado;
  • bitbucket: um API token da conta Atlassian (id.atlassian.com → Security → API tokens → "Create API token with scopes") com os escopos read:repository:bitbucket, read:pullrequest:bitbucket e write:pullrequest:bitbucket, informado em bitbucket.token ou na variável BITBUCKET_TOKEN, junto com o e-mail da conta em bitbucket.email ou na variável BITBUCKET_EMAIL. A autenticação é Basic (e-mail + token); tokens de acesso de repositório/workspace não são aceitos.

Configuração

Arquivo .yml com a lista de projetos:

bitbucket:
  email: ${BITBUCKET_EMAIL}
  token: ${BITBUCKET_TOKEN}

projects:
  - name: backend
    provider: bitbucket
    path: /Users/sergio/projects/backend
    main: true
    major-branch: develop
    commit-sufixo: teste-teste-teste

  - name: admin
    provider: bitbucket
    path: /Users/sergio/projects/frontend-admin
    main: true

  - name: client
    provider: github
    path: /Users/sergio/projects/frontend-client
    main: false
chave obrigatória descrição
name sim nome usado em --project=nome
provider sim github ou bitbucket; define como os PRs são criados e alterados
path sim diretório do repositório (aceita ~ e variáveis de ambiente)
main sim define se o projeto entra nas execuções sem --no-main
major-branch não branch principal do projeto: origem das tarefas update, new e checkout e destino da tarefa pr; sem ela, --source/--target passam a ser obrigatórios
commit-sufixo não string acrescentada ao fim da mensagem de commit da tarefa pr

As chaves bitbucket.email e bitbucket.token só são necessárias se algum projeto usar provider: bitbucket. Aceitam o valor literal ou uma variável de ambiente (${NOME}); se estiverem vazias, as variáveis BITBUCKET_EMAIL e BITBUCKET_TOKEN são usadas. O workspace e o repositório são extraídos da URL do remote origin (ssh ou https), que precisa apontar para bitbucket.org.

Ordem de busca do arquivo quando --config não é informado:

  1. variável de ambiente GIT_MANAGER_CONFIG;
  2. diretório atual: git-manager.yml, git-manager.yaml, projects.yml, projects.yaml, config.yml, config.yaml;
  3. ~/.config/git-manager/config.yml (e .yaml);
  4. ~/.git-manager.yml (e .yaml).

Uso

git-manager <tarefa> [parâmetros]
gm <tarefa> [parâmetros]             # atalho criado pelo make install

Os parâmetros com valor aceitam -p backend, -p=backend, --project backend ou --project=backend.

Parâmetros globais

parâmetro efeito
--no-main executa em todos os projetos, inclusive os com main: false
-p, --project=nome executa apenas no(s) projeto(s) informado(s) (ignora o filtro de main)
-b, --branch=nome nome da branch (obrigatório nas tarefas new e checkout; opcional nas draft e ready)
-s, --source=nome branch de origem nas tarefas update, new e checkout; substitui o major-branch do config e é obrigatório quando algum projeto selecionado não o define
-t, --target=nome branch de destino na tarefa pr; substitui o major-branch do config e é obrigatório quando algum projeto selecionado não o define
--config=arquivo.yml caminho do arquivo de configuração
--dry-run imprime os comandos sem aplicar nenhuma alteração

Sem --no-main e sem --project, a tarefa roda somente nos projetos com main: true.

Nas tarefas update, new e checkout, a branch de origem é o --source, quando informado; na tarefa pr, a branch de destino é o --target. Sem o parâmetro, ambas usam o major-branch de cada projeto no config. A execução falha antes de tocar em qualquer projeto se, sem o parâmetro, algum projeto selecionado não tiver major-branch ou se os projetos selecionados tiverem major-branch diferentes — a tarefa sempre usa uma única branch para todos os projetos da execução.

--project aceita múltiplos nomes separados por vírgula (ex.: --project=backend,admin), executando a tarefa em cada um deles, na ordem informada. Nomes repetidos são ignorados e um nome inexistente falha a execução inteira.

Tarefas

status

Não altera nada no repositório: faz git fetch --prune origin (para o ahead/behind refletir o remoto) e mostra, para a branch atual:

  • se está limpa ou o número de arquivos alterados (staged, não staged, não rastreados e em conflito);
  • a situação com o upstream (origin/<branch>): em dia, sem upstream configurado, ou quantos commits à frente/atrás;
  • quando a branch atual não é a principal: quantos commits à frente/atrás ela está de origin/<principal>.
git-manager status --no-main

update

Atualiza a branch de origem (--source ou major-branch), que precisa existir em origin; caso contrário a tarefa falha sem alterar o repositório.

  1. git fetch --prune origin;
  2. se a branch atual tiver alterações não commitadas (e não for a de origem): git add --all, git commit --no-verify -m "processo automático" e git push --force origin <branch>;
  3. git checkout <origem> (com --force caso o checkout normal seja bloqueado);
  4. git pull origin <origem>; se a branch de origem tiver alterações locais ou o pull for bloqueado, aplica git reset --hard origin/<origem>.
git-manager update                                  # origem: major-branch do config
git-manager update --source=develop --no-main       # origem explícita para todos

new --branch=nome

Executa o update e em seguida git checkout -b nome, criando a branch a partir da branch de origem. Se a branch já existir localmente, apenas faz o checkout nela e avisa.

git-manager new --branch=feature/login --no-main

checkout --branch=nome

Executa o update — inclusive o commit automático com a mensagem processo automático e o force push da branch atual — e em seguida entra na branch informada:

  1. se ela existir localmente: git checkout <nome>;
  2. senão, se existir em origin: git checkout -b <nome> --track origin/<nome>;
  3. se não existir em nenhum dos dois, a tarefa falha e indica o uso do new.

Depois do checkout, a branch de origem é mesclada nela com git merge --no-edit <origem>, para que a branch informada também fique atualizada (não só a de origem). A mensagem do merge é gerada automaticamente pelo git, sem abrir editor. Se o merge gerar conflito, a tarefa falha e o merge fica em andamento para resolução manual (resolva os conflitos e finalize com git commit, como em qualquer merge normal).

Informar a própria branch de origem é aceito: o update já deixa o repositório nela, atualizada.

git-manager checkout --branch=feature/login --no-main

pr

Abre o PR contra a branch de destino (--target ou major-branch).

  1. git add --all;
  2. gera título e descrição com claude -p "@pr-message gere a mensagem das alterações no formato markdown" --allowedTools "Read,Edit,Bash,Git";
  3. git commit --no-verify -m "<title> <commit-sufixo>";
  4. git push --set-upstream origin <branch> (com fallback para --force);
  5. abre o PR em draft contra a branch de destino, usando o title como título e o message como descrição:
    • github: gh pr create --draft --assignee @me, atribuído ao usuário autenticado no gh;
    • bitbucket: POST /2.0/repositories/<workspace>/<repo>/pullrequests com draft: true (o autor é o dono do token; Bitbucket não tem assignee).

Chamadas ao GitHub/Bitbucket que falham por indisponibilidade (HTTP 5xx, timeout) são repetidas até três vezes. No GitHub, se ainda assim a criação com assignee falhar, o PR é criado sem assignee e a atribuição é tentada em seguida com gh pr edit --add-assignee @me; persistindo o erro, um aviso pede a atribuição manual.

Se já existir um PR aberto para a branch, o push atualiza o PR existente, a URL é exibida no resumo e, no GitHub, se ele não tiver assignee, é atribuído a você. A tarefa falha se a branch atual for a própria branch de destino, se a branch de destino não existir em origin ou se não houver diferença em relação a ela.

A leitura da resposta do claude aceita três formatos, nesta ordem: as seções title:/message: (com ou sem blocos ); dois blocos sem rótulo, sendo o primeiro o título e o segundo a descrição — formato comum no modo -p, que costuma perder os rótulos e acrescentar um preâmbulo; ou um único bloco ```, em que a primeira linha vira o título e o restante a descrição. Texto sem nenhum bloco é recusado com erro, e a saída bruta é impressa para conferência.

draft

Converte para draft o PR da branch atual, usando gh pr ready <n> --undo (GitHub) ou PUT .../pullrequests/<n> com draft: true (Bitbucket). Com --branch=nome o PR daquela branch é usado sem trocar de branch no repositório.

  • se não houver PR aberto para a branch, a tarefa falha;
  • se o PR já estiver em draft, nada é alterado e o resumo informa isso.
git-manager draft --no-main
git-manager draft --branch=SYSVET-924 --project=backend

ready

Marca como pronto para revisão o PR da branch atual, usando gh pr ready <n> (GitHub) ou PUT .../pullrequests/<n> com draft: false (Bitbucket). Com --branch=nome o PR daquela branch é usado sem trocar de branch no repositório.

  • se não houver PR aberto para a branch, a tarefa falha;
  • se o PR já estiver pronto para revisão, nada é alterado e o resumo informa isso.
git-manager ready --no-main
git-manager ready --branch=SYSVET-924 --project=backend

review

claude -p "@pr-reviewer revise o pr da branch atual" --allowedTools "Read,Edit,Bash,Git", com a saída transmitida em tempo real.

Os agentes pr-reviewer e pr-comment-fixer usam o gh internamente, portanto review e fix só funcionam em projetos hospedados no GitHub.

fix

claude -p "@pr-comment-fixer corrija os apontamentos feitos no pr a branch corrente mesmo que forem problemas pré-existentes, pode corrigir" --allowedTools "Read,Edit,Bash,Git".

prune

  1. git fetch --prune origin;
  2. lista as branches locais cujo upstream foi removido ([gone] no git for-each-ref --format='%(upstream:track)');
  3. remove cada uma com git branch -D, pulando a branch atualmente selecionada (com aviso) caso ela esteja nessa lista.
git-manager prune --no-main

Exemplos

git-manager update                                  # projetos main: true, origem: major-branch
git-manager update --no-main                        # todos os projetos
git-manager update --source=develop --no-main       # origem explícita para todos
git-manager new --branch=feature/login --no-main
git-manager checkout --branch=feature/login --no-main
git-manager pr --project=backend                    # destino: major-branch do config
git-manager pr --target=release/2.0 --no-main       # destino explícito para todos
git-manager draft --no-main                          # PR da branch atual volta a draft
git-manager ready --no-main                          # PR da branch atual sai do draft
git-manager review --no-main
git-manager fix --project=backend
git-manager prune --project=backend,admin           # múltiplos projetos
git-manager update --no-main --dry-run              # simula, sem alterar nada

Detalhes de implementação

  • todos os commits usam --no-verify;
  • a branch principal usada pela tarefa status é detectada por origin/HEAD e, na ausência dela, por main e depois master; as demais tarefas usam a major-branch (ou --source/--target);
  • o commit-sufixo é aplicado no commit da tarefa pr; o commit automático do update mantém a mensagem fixa processo automático;
  • quando a branch atual é a de origem e existem alterações locais, elas são descartadas pelo reset --hard origin/<origem> (regra 5.1.b), em vez de gerarem um force push na branch de origem;
  • os projetos são processados em sequência e o resumo final lista o resultado de cada um; o processo sai com código 1 se algum projeto falhar.

Desenvolvimento

make fmt
make vet
make test

About

CLI único em Go para operar o git em vários projetos ao mesmo tempo: atualizar as branches principais, criar branches novas, alternar entre branches, abrir PRs com mensagem gerada pelo `claude`, revisar e corrigir os apontamentos do PR.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages