2 pontos por GN⁺ 15 일 전 | 1 comentários | Compartilhar no WhatsApp
  • jj é a interface de linha de comando do Jujutsu, uma ferramenta baseada em sistema de controle de versão distribuído (DVCS)
  • Oferece recursos mais simples e intuitivos que o git, mas ainda mais poderosos
  • Combina as vantagens do git e do Mercurial para reduzir o número de ferramentas centrais e fortalecer a integração orgânica
  • Usa um backend compatível com git, permitindo experimentação independente enquanto mantém o ambiente de colaboração existente
  • Para usuários avançados, é importante poder aproveitar recursos adicionais de controle de versão que são difíceis de usar com git

Introdução e características do jj

  • jj é a CLI (interface de linha de comando) do Jujutsu, e o Jujutsu é um sistema de controle de versão distribuído (DVCS)

    • Usuários podem já estar familiarizados com outros DVCS, como o git, e o tutorial parte da perspectiva de usuários de git
    • O jj foi projetado para ser uma ferramenta mais simples, mais fácil de usar e ainda assim poderosa em comparação com o git
    • Em geral, “poder” e “complexidade” entram em conflito, mas o jj propõe um novo equilíbrio entre esses aspectos
    • O jj combina as vantagens do git e do Mercurial (hg) para formar um novo tipo de DVCS
    • Reduz o número de ferramentas centrais e oferece um ambiente de trabalho eficiente por meio da integração orgânica entre elas
    • Usuários avançados podem aproveitar recursos adicionais de controle de versão que são difíceis de obter com git
    • O jj usa um backend compatível com git, permitindo experimentação independente sem alterar o ambiente de colaboração
    • Mantém compatibilidade com repositórios git existentes e, se necessário, permite voltar facilmente ao git
    • O tutorial sugere que, por meio dessas características, mostrará diretamente por que o jj é uma ferramenta digna de atenção

1 comentários

 
GN⁺ 15 일 전
Comentários no Hacker News
  • Muita da discussão se concentra nas diferenças entre git e jj, mas acho melhor simplesmente esquecer o git e focar no fluxo básico do jj
    Em um repositório limpo, basta executar jj para verificar o estado e, depois de fazer alterações, usar jj commit -m "made changes" para fazer o commit
    Se cometer um erro, corrija e use jj squash para juntar ao último commit
    Só é preciso usar jj new -r lmnop quando quiser trabalhar a partir de uma revisão específica, como se fosse uma nova branch
    O histórico do git pode ser visto com git log, e o funcionamento interno do jj não aparece

    • Eu também queria algo parecido, então criei um alias do git como alias.save="!git add -A; git commit -m" e costumava usar $ git save "made changes"
  • Sinto que o JJ me pede para pensar de trás para frente
    No git, você faz mudanças e depois escreve a mensagem do commit, mas no jj parece que você primeiro cria um novo commit e depois adiciona a descrição
    Estou acostumado a pegar só as mudanças necessárias e fazer commit delas mesmo quando o estado está bagunçado com várias funcionalidades misturadas, e só pelo tutorial do jj não tenho certeza se isso é possível

    • jj new é como uma área de staging vazia do git
      No jj sempre existe um commit, e esse commit tem um changeid estável calculado a partir do conteúdo da pasta
      Se quiser dividir várias alterações em commits separados, use jj split
    • Eu costumo criar commits temporários com jj new e deixar a mensagem vazia
      Mais tarde, quando estiver pronto, junto vários commits com squash em um só e adiciono a mensagem
      Esse método funciona como uma espécie de histórico de undo, então fica muito mais fácil experimentar
    • Na verdade, jj new é só “criar um novo commit por cima”, então não há necessidade de escrever a descrição na hora
      Eu também tentei criar esse hábito no começo, mas na prática foi ineficiente
    • No JJ, essa forma de trabalhar é padrão
      O Git também vem recomendando um fluxo parecido, e o Squash Workflow mostra como criar um fluxo semelhante ao índice do Git
    • Quando faço várias alterações, às vezes funcionalidades diferentes acabam se misturando
      Por isso mantenho vários workspaces e uso bastante o recurso de shelve do IntelliJ
      Às vezes também salvo temporariamente diffs como patches do git
      Tento esconder esse processo caótico dos colegas para parecer um pouco mais profissional
  • O que não gostei no jj é que alterações em arquivos são commitadas automaticamente
    Se eu der checkout em um commit antigo para explorá-lo e editar arquivos, aquele commit é alterado e todo o histórico seguinte é rebaseado
    Por isso preciso criar um commit vazio novo por precaução
    No git é mais confortável porque o repositório não muda até eu fazer commit explicitamente

    • Eu também pensava assim antes, mas mudei de ideia depois de conhecer jj evolog
      O jj já tinha uma solução melhor do que staging
      Estar acostumado com a CLI do git acabou sendo mais um obstáculo para aprender jj
      Curiosamente, usar jj ajuda a entender melhor a estrutura do motor de armazenamento do git
    • Em vez de edit, usar jj new permite rastrear alterações de forma mais limpa
      Parece muito melhor do que ficar fazendo malabarismo com stash do git
    • jj edit é a maior armadilha do jj
      Em vez disso, use jj new, e se errar dá para recuperar com jj undo
      O jj trata commits como snapshots baratos, então faz mais sentido focar em “mudanças” do que em commits
      O rebase automático fica congelado como imutável depois do push, então é seguro
    • O fato de alterações em arquivos serem commitadas automaticamente é uma funcionalidade central do jj
      Basta combinar jj new com jj squash para gerenciar como se fosse o head de uma branch do git
      O jj facilita trabalhar em estado de detached head
    • Você provavelmente fez checkout de um commit antigo com jj edit
      Se trocar para jj new, o problema se resolve
  • O último parágrafo sobre jj é o ponto principal
    Como ele usa um backend totalmente compatível com git, dá para testá-lo sozinho sem exigir que a equipe toda mude
    Se não gostar, sempre pode voltar para git

    • Exceto em organizações que usam LFS, submodules ou hooks
    • Não é compatibilidade total. Há interoperabilidade, mas não é perfeitamente fluida
      Operações feitas no git não são registradas no log do jj, então é preciso importá-las manualmente
      Recomenda-se usar apenas uma interface por projeto
    • Antigamente eu usava o git assim também, junto com CVS e Subversion
    • Mas usar git e jj ao mesmo tempo no mesmo diretório pode causar problemas
  • Meu recurso favorito é o jj absorb
    Ele move automaticamente as alterações da revisão atual para commits anteriores relacionados
    É útil quando você esquece de ajustar arquivos de configuração ou o .gitignore
    Basta fazer jj new, alterar, e depois jj absorb
    E o melhor é não precisar lidar com merge conflict

    • Se o jj absorb aplicar algo errado, dá para desfazer com jj undo
      Esse recurso faz até rebases complexos parecerem menos assustadores
    • Só como referência, o git também tem git absorb
  • Não consegui atualizar o tutorial por muito tempo, mas ainda uso jj todos os dias
    Fiquei ocupado na startup ersc.io e não consegui trabalhar no upstream
    Perguntas são sempre bem-vindas

    • A diferença de imutabilidade do DAG entre git e jj é o ponto central
      O jj usa IDs de mudança estáveis, enquanto o git usa IDs de commit imutáveis
      Por isso, no jj, undo e rebase parecem muito mais flexíveis
    • O jj esconde automaticamente mudanças “não interessantes”
      Às vezes quero ver mais alterações, então fico curioso se existe alguma opção para mostrar tudo de uma vez
  • Vale a pena experimentar o jj justamente por ele ser diferente do git
    Só vivenciar uma abordagem diferente já amplia sua visão de engenharia
    Não é preciso testar tudo, mas entender os trade-offs de fluxos de trabalho diferentes é importante

    • Claro, em 99% dos casos, tentativas com ganho mínimo podem ser perda de tempo
  • A relação entre git e jj parece a relação entre C e Python
    O git é rastreamento forense, e o jj é mais como capítulos de uma história
    Às vezes é preciso reescrever os primeiros capítulos para que os últimos fiquem mais naturais

    • O que o jj faz também é possível no git, mas a forma habitual de pensar no git atrapalha
      O jj foi projetado com a filosofia de que “a working tree em si é um commit” e “até conflitos podem ser commitados”
  • Acho que a afirmação de que ele é “mais poderoso e mais fácil” precisa de exemplos concretos

    • Alguns pontos fortes do jj seriam:
      • não é preciso resolver conflitos de rebase/merge imediatamente
      • manipular commits é muito fácil, especialmente com jjui
      • o jj tem um operation log que rastreia mudanças de estado do git
      • branches sem nome permitem trabalhos experimentais com liberdade
      • ele é totalmente compatível com git, então pode ser usado em conjunto dentro da equipe
    • Quando migramos de SVN para git sentimos uma grande melhora, mas hoje não temos grandes incômodos com o fluxo de trabalho do git
    • Dá para trabalhar em vários PRs ao mesmo tempo dentro de um único repositório e fazer push de cada um conforme necessário
      Se você não tem esse tipo de necessidade, talvez não veja valor no jj
    • O encanto do jj não está nos comandos, e sim no fluxo de trabalho intuitivo
      Só usando para entender
    • Só o jj undo já vale a pena por si só
      No git é fácil cair em um estado sem recuperação, mas no jj isso se resolve com alguns undos
  • O jj me deu confiança para aproveitar um DAG não linear
    Lido livremente com mudanças que têm vários pais ou filhos
    Antes eu forçava uma ordem desnecessária, mas agora consigo expressar dependências com clareza
    O processo de revisão e envio também ficou muito mais eficiente

    • Fico curioso se, sobre essas mudanças ramificadas, usam um fluxo de trabalho de mega-merge + absorb