3 pontos por GN⁺ 2024-11-26 | 1 comentários | Compartilhar no WhatsApp
  • Em um ambiente em que tanto repositórios pessoais quanto de trabalho ficam em ~/workspace, é mais preciso separar a identidade do Git com base na URL do remote do que na localização da pasta
  • O includeIf do Git pode carregar configurações por caminho com gitdir, mas quando repositórios de várias contas se misturam dentro do mesmo diretório de trabalho, a ramificação por caminho esbarra em limites
  • Ao usar a condição hasconfig:remote.*.url:, é possível incluir arquivos de configuração separados conforme o padrão da URL do remote, como GitHub, GitLab, SourceHut ou uma organização específica do GitHub
  • As chaves SSH precisam ser gerenciadas separadamente em ~/.ssh/config com Host, Hostname, User e IdentityFile, e para usar chaves por organização mesmo no mesmo github.com, é necessário um alias de Host
  • Ao configurar url.<base>.insteadOf junto, você pode continuar usando git@github.com:orgname/project normalmente, enquanto internamente isso é substituído por gh-work:orgname, acionando a configuração SSH correta

Separando a configuração do Git com base na URL do remote

  • Exemplos tradicionais de includeIf incluem arquivos de configuração diferentes conforme o caminho do diretório local, como gitdir:~/code/** e gitdir:~/work/**
    • Em ~/code, é possível carregar ~/.config/git/personal, e em ~/work, ~/.config/git/work
    • Esses arquivos normalmente contêm a identidade do Git e a chave de assinatura, como user.name, user.email e user.signingkey
  • Se todo o código fica em ~/workspace, repositórios pessoais, work-1 e work-2 podem se misturar na mesma estrutura de caminhos, o que dificulta obter a separação desejada apenas com condições baseadas em caminho
  • Com hasconfig:remote.*.url: do Git, é possível incluir um arquivo de configuração apenas quando o repositório atual tiver uma URL de remote específica
    • Se corresponder a git@github.com:*/**, incluir ~/.config/git/config-gh
    • Se corresponder a git@github.com:orgname/**, incluir ~/.config/git/config-gh-org
    • Se corresponder a git@gitlab.com:*/**, incluir ~/.config/git/config-gl
    • Se corresponder a git@git.sr.ht:*/**, incluir ~/.config/git/config-srht
  • O Git inclui a última configuração correspondente, então a ordem das condições é importante
    • A condição github.com:orgname/** precisa vir abaixo da condição geral github.com:*/** para que a configuração exclusiva da organização não seja sobrescrita pela configuração geral do GitHub
  • No fim, repositórios com remote github.com:orgname/** usam config-gh-org, enquanto os demais repositórios do GitHub usam a configuração geral do GitHub

Ajustando informações de acesso por organização com chaves SSH e insteadOf

1 comentários

 
GN⁺ 2024-11-26
Opiniões no Hacker News
  • Em vez de insteadOf, clonar o repositório como gh-work:org/repo e, na configuração do Git, usar includeIf "hasconfig:remote.*.url:gh-work:**/**"
    Assim, repositórios clonados com a identidade SSH definida em gh-work passam a carregar automaticamente a configuração gh-work.inc, que contém a identidade do Git e a chave de assinatura, além de configurações de SSH
    No fim, o nome gh-work vira o critério para distinguir a identidade SSH da identidade Git, o que fica mais fácil de entender

    • A solução do texto parecia incômoda por ter mais graus de liberdade do que o necessário, mas esta parece uma forma elegante de reduzir os parâmetros em tempo de execução a um só
    • includeIf diferencia maiúsculas de minúsculas, e, na prioridade, a última configuração vence
      Para verificar se está funcionando corretamente, basta executar git remote get-url origin e git config --get user.email
    • Esse método poderia quebrar scripts que esperam que a URL do repositório remoto tenha um formato específico
  • Acho que uma forma melhor é colocar aliases por identidade no .gitconfig do HOME e, logo após inicializar ou clonar um repositório, executar git config-company ou git config-personal
    Ative user.useConfigOnly = true e, nos aliases, configure user.email, user.name e core.sshCommand do repositório local com as chaves SSH pessoais/de trabalho, respectivamente

    • A questão é como fazer o clone inicial sem a configuração SSH correta desde o começo
      A vantagem do método do texto parece ser que, ao clonar a partir da organização, simplesmente funciona
  • Tempos atrás, em uma startup, havia uma pessoa que mudava sua identidade todos os dias para algum nome qualquer de conto de fadas
    Commits de segunda eram de Mr. Bunnymann, os de terça de Doctor Funtime e assim por diante, o que era muito inconveniente ao fazer forense de controle de versão
    Sendo generoso, talvez ela estivesse tentando lembrar que qualquer pessoa pode colocar qualquer valor nas configurações de identidade, então não se deve confiar demais nesses valores

    • Em uma cultura sem culpabilização, em uma análise forense de controle de versão, quando aconteceu e em torno de quais mudanças seria mais importante do que quem fez
      Ainda assim, saber quem fez ajuda na hora de perguntar detalhes ou prever estilo e especialidade
      Se você exigir assinatura GPG nos commits e registrar as identidades GPG permitidas, é possível identificar o autor real pela assinatura em vez dos metadados de autor/committer
      Claro que “simplesmente” e assinatura GPG nem sempre combinam bem
    • Dá para confiar nisso tanto quanto se confia em documentos ou assinaturas escritos por um funcionário
      Se não dá para confiar que um funcionário identifique corretamente os próprios commits, acho que ele deveria ser demitido
    • Sendo generoso, eu ficaria curioso para saber se era usada a mesma chave de assinatura
    • É surpreendente que alguém tenha sido pago para esse tipo de brincadeira
    • O Git tem suporte embutido para separar autor e committer, e provavelmente a pessoa só alterou o atributo de autor
  • Sem precisar mexer em ~/.ssh/config, basta colocar em ~/.gitconfig ou, como no texto, em ~/.config/git/personal algo como core.sshCommand = /usr/bin/ssh -o IdentitiesOnly=yes -i ~/.ssh/IdentityFile2 -a
    Assim, submódulos ficam mais fáceis mesmo sem insteadOf

    • Ainda resta a questão do que fazer quando há mais de uma identidade SSH
  • Eu já usava includeIf baseado em diretório havia tempos (https://www.bobek.cz/til/git-identities/), mas hasconfig:remote é realmente muito limpo
    Também funciona ao clonar um repositório

  • includeIf é muito bom
    Hoje deixo a complexidade do SSH em ~/.ssh e mantenho um include para cada cliente/projeto/identidade
    Para casos sem um hostname exclusivo, como o GitHub, coloco um alias de host como customer-github e configuro HostName github.com, IdentityFile ~/.ssh/customer_rsa, User git etc.
    Depois, é só usar esse alias no git clone

  • Eu tinha o mesmo problema, e agora parece que há uma solução
    Usando NixOS e home-manager no Linux e no Mac, essa configuração fica simples
    Em programs.git.includes, basta colocar condition = "hasconfig:remote.*.url:git@github.com:/**" e a configuração de user.email
    Referência: https://nix-community.github.io/home-manager/options.xhtml#opt-programs.git.includes

    • Parece menos simples do que escrever diretamente no .gitconfig
      É a mesma condição e configuração do texto, só que com uma etapa de build/template e ainda a necessidade de aprender uma nova linguagem de programação com sintaxe peculiar
  • Eu já separava as configurações de trabalho e pessoais com includeIf: "gitdir", mas hasconfig:remote muda completamente o jogo

    • É difícil acreditar que essa joia ficou escondida como rascunho por 3 anos
  • Para consultores, sempre recomendo fortemente usar uma máquina separada para trabalho ou, no mínimo, um usuário de sistema operacional separado
    Usar uma máquina pessoal para trabalho pode trazer um grande risco de problemas

    • “Usar uma máquina pessoal para trabalho” cobre um escopo muito amplo
      Em uma empresa remote-first, alguém pode preparar o próprio notebook e receber reembolso para comprar um novo aparelho a cada 2 ou 3 anos, mas ainda assim ele ser um notebook pessoal; também pode ser um contrato temporário
      É preciso explicar de forma mais específica em quais situações isso vira problema e por quê
      O risco existe, mas, se você não consegue enumerá-lo, fica mais perto de espalhar FUD do que de educar
  • Esta é uma ferramenta que criei para trocar facilmente a identidade Git por projeto: https://github.com/cquintana92/git-switch-user
    Depois de configurar as identidades, ao executar $ git su Personal ou $ git su Work, o e-mail, o nome, a chave SSH e, opcionalmente, até a chave PGP são configurados no .git/config do repositório
    Economizou muito tempo para mim

    • Também existe uma ferramenta para gerenciar identidades do GitHub para acesso Git via SSH: https://github.com/dolmen/github-keygen
      É uma ferramenta de 12 anos, mas ainda é mantida ativamente