2 pontos por GN⁺ 2025-07-23 | 1 comentários | Compartilhar no WhatsApp
  • Jujutsu (jj) é um sistema de controle de versão que oferece conceitos e comandos mais simples do que o Git, mas com recursos poderosos
  • Como usa o Git como backend, tem a vantagem de poder ser usado em conjunto ou de voltar facilmente ao Git
  • Recursos como diffs em pilha, rebase fácil e revisões temporárias são oferecidos de forma natural
  • Em vez de branches, ele usa o conceito de bookmarks, o que é mais intuitivo para o fluxo de trabalho do dia a dia
  • A forma de lidar com conflitos é flexível e torna muito mais simples as tarefas cotidianas de controle de versão

Elevator Pitch

Jujutsu (jj) é um sistema de controle de versão que oferece um modelo mental e uma interface de linha de comando muito mais simples do que o Git.
Sem sacrificar funcionalidades, e na prática dá até para dizer que ele é mais poderoso
Recursos como diffs em pilha, rebase fácil e revisões temporárias funcionam de forma natural
Como usa o Git no backend, dá para começar a usá-lo lado a lado com um repositório Git com uma única linha e voltar ao Git a qualquer momento
Também não afeta a forma como outras pessoas lidam com o repositório

Getting Started

  • Depois de instalar a ferramenta de linha de comando jj, é recomendável configurar as informações do usuário e o autocompletar do shell
  • Ao aplicar em um repositório existente, é melhor fazer um novo clone ou começar a usá-lo quando não houver mudanças pendentes
  • Em um repositório existente, é possível criar repositórios Git e Jujutsu em paralelo com o comando jj git init --colocate .
  • Os dados do repositório jj ficam armazenados em uma pasta .jj/, separada da .git do Git
  • A sincronização de dados entre Git e Jujutsu normalmente funciona sem problemas
  • Mas é preciso cuidado, porque o comando git clean -fdx apaga a pasta .jj/
  • O rastreamento de remote branches também pode ser configurado de uma vez com esse comando

How To Use It

A interface de linha de comando do Jujutsu é mais enxuta e concisa que a do Git
Os conceitos básicos são simples, mas o fluxo de trabalho exige um pequeno período de adaptação
A seguir estão os principais modos de uso com procedimentos simples e exemplos

Starting A New Revision

  • No Git, um novo trabalho normalmente começa com a criação de uma branch, mas no Jujutsu a abordagem é criar uma nova revisão
  • Refletir o estado mais recente do repositório remoto: jj git fetch
  • Ver o histórico do repositório: jj log
  • As revisões no histórico são identificadas por um ID de revisão próprio do Jujutsu e por um hash de commit do Git
  • Para começar um novo trabalho, use jj new main para criar uma nova revisão em cima da main atual
  • A revisão que está sendo editada no momento é indicada pelo símbolo @
  • Se um mesmo prefixo deixar de existir, o prefixo curto do ID da revisão também muda junto

Making Changes

  • Ao editar arquivos, eles são incluídos imediatamente naquela revisão (não há staging area separada)
  • Quando terminar as alterações, adicione uma mensagem à revisão com jj describe -m "mensagem"
  • Para criar uma nova revisão, use jj new (ou especifique uma revisão anterior)
  • jj commit é uma operação combinada de jj describe + jj new

Navigating

  • Uma revisão vazia criada com jj new é descartada automaticamente ao se mover para outro lugar
  • Excluir explicitamente uma revisão: jj abandon <rev ID>
  • Desfazer a exclusão: jj op undo
  • Voltar para uma revisão existente: jj edit <rev ID>
  • Ao referenciar revisões, também é possível usar revset expressions:
    • @: revisão atual
    • x-: revisão pai
    • y+: revisão filha
    • z::: todos os descendentes de z

Branches (Bookmarks)

  • No Jujutsu, não existe o estado de “estar em uma branch” como no Git
  • Em vez disso, os bookmarks são apenas ponteiros para uma revisão específica
  • Criar um novo bookmark: jj bookmark create <nome> -r <revisão>
  • Mesmo após um commit, o bookmark não se move automaticamente; se necessário, ele deve ser movido separadamente com jj bookmark move <nome> --to <revisão>
  • Ao fazer push, a criação de uma nova branch remota precisa ser permitida com a flag --allow-new
  • Se o bookmark estiver diferente do remoto, ele será mostrado com * e poderá ser sincronizado com jj git push

Conflicts

  • A forma de tratar conflitos no Jujutsu é mais flexível do que no Git
  • Em caso de conflito, a marcação conflicted aparece na revisão e também nas revisões descendentes
  • Arquivos com conflito recebem marcadores de conflito, e a resolução é feita removendo esses marcadores
  • Também é possível editar diretamente ou fazer mudanças em uma nova revisão e depois juntar tudo com jj squash

Conclusão

Até aqui, foi mostrado como realizar de forma mais simples no Jujutsu os 80% de tarefas mais comuns feitas com Git
No futuro, usos gerais e avançados devem ser apresentados em formato de handbook de referência rápida (Quick Reference)
Assim como no Git, o comando jj status também é suportado
Dúvidas ou feedback podem ser enviados para o e-mail mencionado no texto

1 comentários

 
GN⁺ 2025-07-23
Comentários do Hacker News
  • Para quem está se perguntando se vale a pena aprender jj, há um ponto que eu queria enfatizar
    Quando se fala de jj no Hacker News, as pessoas se dividem em dois grupos: as que ainda não tentaram e as que recomendam fortemente
    Quase nunca vi alguém usar jj por uma semana e depois voltar para o git
    Quase todo mundo que realmente usou com seriedade acabou ficando com jj
    Espero que hoje seja o dia em que você experimente jj
    A mudança é muito mais simples do que parece; eu consegui manter a produtividade já no primeiro dia e, em menos de uma semana, não precisei voltar aos comandos do git nenhuma vez
    Em pouco tempo fiquei mais produtivo e hoje só me pergunto como eu usava git antes

    • Para mim, o git não é nem um pouco incômodo em termos de produtividade
      Também não passo muito tempo por dia usando comandos do git e, na maioria dos casos, ele não atrapalha meu trabalho
      Se você precisa manipular muito o repositório com git, jj pode ser melhor, mas esse não é o meu caso
      É parecido com sugerirem que eu experimente obrigatoriamente o bim, que é muito parecido com o vim, mas com alguns recursos a mais
      Só que eu não me importo em digitar mais alguns i, nem preciso de autocomplete de Julia
      Quem acha jj melhor, que aproveite

    • jj é claramente um avanço na UI de VCS, mas, para usuários avançados de git, há algumas limitações
      Sem suporte a gitattributes, fica inconveniente se você precisa de filtros como git-crypt ou git-lfs
      A compatibilidade no Windows, incluindo tratamento de fim de linha, também pode ser pior
      Além disso, ferramentas externas como git-annex e git-bug não se integram ao oplog e podem bagunçar o histórico

    • Eu realmente usei por mais de uma semana e depois voltei para o git
      Pessoalmente, prefiro o workflow da staging area; a maioria das pessoas odeia o staging do git, mas, para mim, isso não foi um ganho grande o bastante para abandonar em troca do que o jj oferece
      Talvez eu consiga mudar de hábito, mas por enquanto não estou particularmente preso ao jj
      Continuo aberto a tentar de novo algum dia

    • Eu usei jj por alguns meses e voltei para o git por causa de problemas de desempenho
      As operações no jj levavam vários segundos, enquanto no git tudo era imediato, independentemente do tamanho do projeto
      Também tive a sensação de que usar jj me deixava mentalmente um pouco mais sobrecarregado, e voltar para o git foi um alívio
      Isso pode ter relação com a minha longa experiência usando git

    • Só existem dois tipos de pessoa, né? Isso por si só já soa como fala típica de evangelista de jj

  • O que me deixa maluco no jj é que as mudanças são sempre adicionadas automaticamente ao staging
    O SVN funcionava assim antigamente, e eu sempre senti que o git melhorou muito ao tornar o staging explícito
    Sempre existem mais mudanças no repositório, e no git é natural selecionar apenas o que você quer colocar no próximo commit
    No jj (e no SVN), isso exige trabalho manual incômodo, como tirar temporariamente alterações de cena antes de commitar

    • Para mim isso também é um dilema
      Staging sempre foi uma chateação, e eu sofria com isso até quando usava Mercurial
      Quando você precisa de auto add em mais de 90% dos casos, isso até ajuda, mas o problema são os arquivos que não dá para colocar no .gitignore
      Se você desliga o auto add, fica incômodo; se deixa ligado, também fica meio estranho
      Nenhum dos dois lados é totalmente limpo

    • O workflow do JJ é um pouco diferente; por exemplo, você cria primeiro um commit base e vai empilhando commits anônimos em cima para trabalhar
      Quando estiver pronto, organiza tudo com jj squash ou jj split

    • Eu uso jj commit -i, a opção -i em vários comandos e snapshot.auto-track="none()" na configuração
      Eu fazia algo parecido quando usava Mercurial
      Na prática, se você usa bastante o recurso absorb, arquivos ou chunks desnecessários costumam ser ignorados automaticamente

    • O comando jj new não seria adequado para o workflow que você quer?

    • O jj rastreia corretamente até branches que não estão no head da árvore, então rebase e merge funcionam de forma suave sem precisar de stash

  • Não é fácil se acostumar com a adição automática de mudanças
    Às vezes eu altero localmente certos arquivos só durante o desenvolvimento, sem intenção de commitar
    No git, se eu não fizer staging, sei que aquilo nunca vai ser commitado nem enviado por push
    No jj, parece que eu precisaria desfazer o staging de algo ou tomar mais cuidado
    Pode ser questão de hábito, mas eu me sinto mais confortável definindo claramente só o que vou commitar
    Talvez eu tenha entendido o jj de forma errada

    • No jj, você pode dividir as mudanças com jj split
      O que você selecionar vai para a primeira revisão, e o resto fica na segunda
      Se você trabalhou em várias coisas ao mesmo tempo e depois separou em revisões pequenas, isso é muito mais fácil do que no git
      Como no git, você pode criar uma nova revisão (jj new), fazer alterações e depois mover exatamente o que quiser com jj squash -i
      Conceitualmente, @ é a revisão atual e @- é a anterior, então dá para pensar nisso como a working copy e o stage do git

    • O auto staging do jj nem sempre é uma coisa boa
      Seria bom se a documentação oficial do jj e quem apresenta a ferramenta deixassem mais claro que o valor padrão pode ser desativado facilmente
      No ~/.jjconfig, basta colocar
      [snapshot]
      auto-track = "none()"
      assim

    • Eu normalmente reviso e organizo o que vai ser commitado com jj split depois de trabalhar
      Esse workflow funciona de forma parecida com add -p do git
      O commit do topo pode ser usado como uma espécie de working copy que você normalmente não envia por push
      Você também pode trocar de branch sem stash que o que estiver em andamento continua preservado

    • Sim, esse hábito também foi difícil de mudar para mim
      O argumento racional para mudar é que você não deveria rodar código em estado untracked
      Mudanças significativas devem ficar em commits, e o resto é melhor não registrar
      O problema aparece quando a configuração do repositório e a configuração local não ficam separadas, e o VSCode é um bom exemplo disso
      Nesses casos, você acaba precisando de mudanças específicas do ambiente que não devem ser commitadas, o que complica tudo

    • Se você quer esse tipo de workflow, pode tratar o @ do jj como o index do git e, na hora do commit, fazer squash em @- para obter algo parecido com git add --patch

  • Estou tentando migrar o time para jj, mas sem sucesso
    Seria ótimo ter uma página que mostrasse de forma imediata o quanto tarefas complexas do git ficam mais fáceis no jj
    Algo quase como um elevator pitch
    Também estou achando que talvez eu precise demonstrar isso pessoalmente

    • Parece que muitas das tarefas comuns do git não ficam necessariamente mais fáceis no jujutsu
      Em vez disso, o jujutsu oferece workflows novos que seriam impossíveis ou trabalhosos no git
      Isso pode não ser tão convincente para desenvolvedores já acostumados com o git

    • Eu também não gosto particularmente do git
      No passado eu só usava Mercurial, mas hoje o git já está completamente internalizado na minha cabeça
      Mesmo que o Jujutsu tenha alguma vantagem clara, ainda não senti que valha o esforço de cuidar da configuração inicial, como esquema de cores complexo e scripts com os quais já estou acostumado

    • Uma comparação de uma tarefa representativa entre jj e git me ajudou bastante a entender
      https://lottia.net/notes/0013-git-jujutsu-miniature.html

    • Também recomendo alguns links úteis
      https://v5.chriskrycho.com/essays/jj-init/
      https://v5.chriskrycho.com/journal/jujutsu-megamerges-and-jj-absorb/
      https://ofcr.se/jujutsu-merge-workflow

    • Acho que você vai gostar da próxima parte que vou adicionar a este post em breve
      Pretendo colocá-la embaixo na página e também em um post separado em pouco tempo

  • Usei jj por algumas semanas e até fiz um script de mensagem de commit automática
    Hoje fui portar o mesmo script para um repositório git antigo e percebi que, no git, eu precisava de código para detectar automaticamente se era um commit ou um amend
    No jj, por causa da estrutura de commits imutáveis, o script ficou muito simples
    Então simplesmente clonei o repositório de novo com jj
    Foi uma libertação instantânea da confusão entre commit e amend
    https://codeberg.org/jcdickinson/nix/src/branch/main/home/common/scripts/jj-auto.fish

    • Nem precisa fazer re-clone; dá para usar jj junto no repositório git que você já tem
  • O git funciona bem o suficiente
    A curva de aprendizado existe, mas, depois que você aprende, tudo faz sentido
    Sinceramente, em 95% dos casos, basta saber pull, add, reset, branch e commit

    • No meu workflow, stacked diff é essencial
      É ótimo para continuar empilhando trabalho futuro sem ficar bloqueado esperando review
      No git, configurar isso não é difícil, mas adicionar mudanças na parte de baixo da pilha e depois fazer restack de tudo é um verdadeiro inferno

    • Quando se trabalha em equipe, dominar rebase e squash é indispensável
      É impossível fugir disso até convencer o time inteiro a não usar
      Especialmente quando várias pessoas estão desenvolvendo às pressas na mesma branch, os hábitos do git começam a incomodar
      No básico ele é confortável, mas, em situações complexas, tem muitos problemas

    • Basta passar por alguns casos mais peculiares para perceber os pontos fracos do git

  • Estou usando jj há umas duas semanas e é a primeira vez que me sinto confortável usando controle de versão só pela linha de comando
    Quando eu usava git, quase sempre dependia da GUI (Git Graph no VSCode) e de clicar com o botão direito
    Com jj, bastou ler o tutorial para entrar direto em uma linha de comando coerente
    Mas, para evitar ficar copiando e colando IDs o tempo todo no log do jj, acho que vou precisar aprender a linguagem de revset

    • Estou numa situação parecida
      Usei git por muito tempo, mas sempre resolvia as coisas mais complexas pela UI
      Já faz quase um mês que uso só a CLI do jj e estou bem satisfeito
      Ainda assim, a documentação oficial do jj parece escrita assumindo conhecimento prévio, então às vezes pode confundir iniciantes
      Tomara que apareçam mais blogs e tutoriais
      Também quero aprender melhor revset e rebase
      Gosto bastante da CLI enxuta, da resolução de conflitos e do oplog

    • Eu também achava ruim ficar copiando e colando IDs, mas depois que comecei a usar o jjui(https://github.com/idursun/jjui) ficou muito mais fluido
      Acabei passando a trabalhar rapidamente, quase como se estivesse percorrendo o log

  • Acho que o melhor recurso do jj é o undo
    No git, desfazer coisas é difícil porque o comando muda conforme o tipo de erro
    No jj, basta um jj undo
    E você nem fica preso ao sistema de backend; dá para usar jj localmente sozinho sem afetar os colegas

  • Estou confuso sobre o que exatamente é o jj
    Será que é um frontend para quem se perde com git?
    Dizem que abstrai o backend, mas ele ainda parece tão influenciado por git que tenho dificuldade de imaginá-lo em sistemas como Perforce ou Piper, que impõem commits com numeração sequencial
    Esse design de working copy = commit me parece tirar o controle de qualidade
    O sentido original de commit é registrar apenas o que foi intencionalmente preparado, e com essa estrutura parece ficar ainda mais difícil distinguir "commits lixo"
    Tanto git quanto jj parecem frágeis para projetos grandes e não parecem impedir a proliferação de commits ruins
    Quero entender que problema o jj realmente resolve, ou se ele é só um frontend moldado pela preferência do autor

    • O backend do Piper, na verdade, funciona de forma ainda mais natural do que o backend do Git
      Os commits do jj não correspondem perfeitamente aos commits do git, então não precisa partir dessa premissa
      Na prática, quando se fala em “commit” aqui, a ideia é mais de um “diff com nome”, e mudanças antes do push podem ser reorganizadas e reescritas com muita facilidade
      Isso é muito mais prático do que rebase e edição de histórico no git
      Eu costumo criar vários commits experimentais, de documentação etc. durante o trabalho, e no git teria que enfiar isso em stash ou em branches temporárias

    • jj é mais do que um frontend para git
      É um sistema de controle de versão e é agnóstico ao backend
      O backend mais comum é o git, o que permite migrar imediatamente em repositórios já existentes
      Eu uso git desde antes do GitHub existir, mas depois de usar jj não consigo mais voltar para o git
      O jj é mais simples e ao mesmo tempo mais poderoso
      working copy = commit deve ser entendido mais como “o index também é um commit”
      Por exemplo, ao começar a trabalhar na feature x, você cria um novo commit com jj new -m "working on feature x" trunk e coloca mais um commit vazio por cima
      O trabalho entra na working copy (@) e você o “move” para o commit anterior (@-) com squash; em vez de opções complexas como add -p e reset do git, tudo é tratado como diff entre commits
      Essa estrutura torna a divisão e a organização de commits mais flexíveis e poderosas do que o index do git
      O problema da proliferação de commits está mais ligado à cultura de pull requests, e o jj só consegue resolver isso até certo ponto

    • A working copy não vai ser enviada cegamente para o GitHub; você pode revisar e organizar tudo ao adicionar a descrição do commit

  • Testei jj por alguns dias, mas já estou satisfeito o bastante com meu lazygit, meu workflow atual e meus scripts
    O jj é interessante e tem ideias boas, mas, a menos que você esteja começando agora com controle de versão, falta motivação para mudar

    • Com outras ferramentas como GitButler, o frontend importa menos, mas há alguns dias adotei Jujutsu e perguntei ao Claude sobre as operações principais — commit, troca de branch, push/pull no GitHub — e em 10 minutos peguei o jeito
      Ainda uso o diff do Lazygit, mas ficar em detached HEAD não é problema nenhum
      O JJ é muito compatível com git e facilita muito fazer tudo sem decorar comandos complexos
      O fato de arquivos não commitados se moverem automaticamente junto ao trocar de branch é, para mim, o melhor recurso de todos
      Fica muito fácil alternar entre desenvolvimento, correção de bug e mudanças de texto
      Se um agente de IA fizer alterações, dá para usar worktrees separados
      Também é ótimo poder colocar a descrição da mudança (= mensagem de commit) antes de terminar e já ver isso na árvore
      No geral, o JJ é excelente