Devo mudar do Git para o Jujutsu · Evan Todd

Devo mudar do Git para o Jujutsu · Evan Todd


Jujutsu é um novo sistema de controle de versão compatível com versões anteriores do Git. Todas as crianças legais estão delirando com isso. Neste artigo tentarei ajudá-lo a decidir se vale a pena investigar.

Se você usar git rebasea resposta à pergunta deste artigo é provavelmente sim. Você provavelmente vai adorar Jujutsu. Prossiga para a Parte Dois. Não passe, vá. Não colete duzentos dólares.

Se você não usar git rebasevocê ainda pode gostar de Jujutsu, mas pode se perguntar: por que eu me importaria com todas essas coisas sofisticadas? Tudo o que faço com o Git é confirmar e ocasionalmente sincronizar com main… o que mais eu poderia querer?

Para projetos pessoais solo, Jujutsu não tem muito a oferecer. Apenas viva sua vida e continue se comprometendo diretamente com main.

Mas se você trabalha com outras pessoas, provavelmente terá que lidar com o problema mais difícil da ciência da computação:

Devo mudar do Git para o Jujutsu · Evan Todd

A revisão de código é dolorosa, esteja você revisando ou sendo revisado.

Ao revisar uma solicitação pull com alguém no Github (por exemplo), você verá todas as alterações de todos os commits na solicitação pull agrupadas em uma visualização e classificadas em ordem alfabética por nome de arquivo, assim:

  1. file_a
  2. file_b
  3. file_c

Muitas vezes é confuso ler isso porque, na realidade, você pode ter modificado os arquivos em uma ordem diferente:

  1. file_b
  2. file_c
  3. file_a

Para tornar a revisão mais tranquila, você pode clicar nos commits individuais e lê-los um de cada vez. Mas muitas vezes isso não ajuda muito, porque os commits ficam assim:

  1. Enorme refatorador incompreensível
  2. Corrigir testes
  3. Apaziguar linter
  4. Sincronizar do branch principal
  5. Revisão do código de IA de endereço
  6. Sincronizar do branch principal
  7. Corrigir erros de digitação
  8. Adicione mais testes
  9. Sincronizar do branch principal
  10. Sincronizar do branch principal

Se você pudesse organizar seus commits para contar uma história agradável e compreensível, você poderia passar pela revisão do código com muito mais rapidez e facilidade.

Quando alguém revisa seu código, você deseja que cada etapa seja direta e óbvia, como se você estivesse andando em linha reta de onde está até onde deseja ir. Se você viu commits como esse, parece que o autor pode prever o futuro.

Você pode ler o primeiro commit e pensar: “Não vejo como isso se relaciona com a tarefa em questão”. Mas à medida que você continua lendo os commits, fica claro por que aquele primeiro commit foi necessário. É como se o autor soubesse que eles teriam problemas mais tarde, então eles tiveram que fazer essa mudança primeiro. É um espetáculo para ser visto.

O problema é que, na realidade, não posso prever o futuro. E, portanto, não trabalho em linha reta.

Linha reta vs espaguete

Chego na metade de algo e percebo que preciso mudar de direção. Troco golpes com linters. E a linha ondulada resultante é muito mais difícil de ler e revisar.

Então, como posso obter essa linda linha reta?

Eu reescrevo a história.

Vou dizer aos meus filhos em 2045 que este foi Obama

Isto é o que git rebase faz. Ele permite que você reescreva o histórico e torne seus commits compreensíveis.

Se tudo o que você faz é confirmar e sincronizar a partir do branch principal, esperamos que isso deixe claro por que você pode estar interessado em um fluxo de trabalho um pouco mais sofisticado. Isso torna a revisão do código menos dolorosa.

O modelo de dados subjacente do Git é bonito e elegante, mas as ferramentas para manipulá-lo são notoriamente pouco intuitivas. Jujutsu pretende resolver isso.

Aqui estão as principais áreas onde o Jujutsu diverge do Git. Isso não fez sentido para mim imediatamente. Eu apenas os deixei tomar conta de mim e, eventualmente, eles fizeram sentido enquanto eu absorvia os detalhes.

  • Tudo está sempre comprometido. Não há área de preparação no Jujutsu. Você não escolhe quais coisas comprometer. Tudo é sempre salvo no commit atual.

  • As confirmações são mutáveis. Como tudo é salvo automaticamente no commit atual, esse commit necessariamente mudará com o tempo. Jujutsu pode até mostrar o histórico de como cada commit mudou ao longo do tempo, um pouco como o recurso Timeline do VSCode.

  • Você pode desfazer! Você já bagunçou tanto um repositório Git que teve que excluí-lo e baixá-lo novamente? Com Jujutsu você apenas digita jj undo. O controle de versão finalmente entrou na década de 1960. Só isso é suficiente para fazer o Jujutsu valer a pena.

  • Reescrever a história é um cidadão de primeira classe. Este é o grande problema. No Jujutsu, você está constantemente reescrevendo a história por padrão. Você faz isso sem perceber. Não é uma operação assustadora como git rebaseé algo que todos podem fazer, para que todos possamos parecer gênios na revisão de código.

No Git você tem a cópia de trabalho, a área de teste (também conhecida como índice), o HEAD commit e, em seguida, todo o histórico de commits. Existem vários comandos diferentes que você pode usar para mover alterações entre essas áreas. Você tem git add e git commitmas também há git checkout, git restoreetc., etc. Há também o stash, que possui seus próprios comandos e sinalizadores separados. E se você quiser mexer nos commits anteriores, você tem que usar git rebase.

Diferentes áreas do Git e os comandos para manipulá-las

Em Jujutsu, a cópia de trabalho é o commit atual. Você faz alterações e, sempre que executa qualquer comando do Jujutsu, essas alterações são automaticamente capturadas no commit atual. É isso. Todos os outros comandos do Jujutsu tratam da manipulação de commits.

A cópia de trabalho é um commit comum

Agora, se você é como eu, pode achar isso assustador. Costumo fazer alterações que não quero confirmar. Como evito poluir meu histórico com elas?

No Jujutsu, você geralmente está trabalhando em uma espécie de “esboço” de commit de trabalho em andamento. Ele pode conter coisas que você deseja salvar e coisas que não deseja. Quando estiver pronto para concluí-lo, você cria um novo commit “stub” de trabalho em andamento e, em seguida, edita ambos os commits, escolhendo quais alterações serão transportadas para seu novo commit WIP e quais merecem ser salvas no histórico. No Git, isso seria uma operação muito assustadora, mas no Jujutsu isso acontece por padrão.

Esta é uma maneira pela qual o Jujutsu facilita a reescrita da história. Você pode mudar para qualquer commit e editá-lo diretamente:

Quaisquer alterações feitas são salvas automaticamente nesse commit.

E se você editar um commit no passado e ele entrar em conflito com um commit posterior?

Digamos que seu histórico de commits seja assim, do mais recente ao mais antigo:

  • Confirmação 3: renomear Foo para Bar
  • Confirmação 2: mudança não relacionada
  • Confirmação 1: mudança não relacionada

Digamos que você corra jj edit 1 e depois renomeie Foo para Baz? O que acontece?

No Git, você estaria em uma situação de crise. Você teria que resolver o conflito imediatamente ou então abortar toda a operação.

Mas no Jujutsu, isso é o que você verá:

  • Confirmar 3 (conflito): renomear Foo para Bar
  • Confirmação 2: mudança não relacionada
  • Confirmação 1: mudança não relacionada

Ele simplesmente marca o commit 3 como conflitante e segue em frente com a vida. Você pode continuar trabalhando nos commits 1 e 2 e se preocupar com isso mais tarde.

Quando estiver pronto, você pode jj edit 3abra o arquivo em conflito e você verá algo assim:

<<<<<<< Conflict 1 of 1
%%%%%%% Changes from base to side #1
-Foo
+Bar
+++++++ Contents of side #2
Baz
>>>>>>> Conflict 1 of 1 ends

Remova os marcadores de conflito no seu editor, execute jj novamente e está tudo pronto. Ele até resolve automaticamente o conflito em todos os commits posteriores no histórico, ao contrário git rebaseo que muitas vezes faz com que você resolva o mesmo conflito repetidamente em cada commit.

Como o Jujutsu funciona com o Git

Os commits do Git são imutáveis, então para “editar” um, você realmente precisa destruí-lo e recriá-lo. Ele recebe um novo hash, junto com cada commit que depende dele. Isso é o que git rebase faz, e é isso que Jujutsu faz nos bastidores.

Para rastrear o histórico de um commit ao longo do tempo, Jujutsu o identifica com um “ID de alteração” permanente que (ironicamente) nunca muda, mesmo quando seu hash muda.

Os IDs de alteração consistem apenas em caracteres que não podem aparecer em um hash do Git, portanto, são sempre exclusivos e fáceis de distinguir. Você pode fazer referência a commits por ID ou hash, e jj exibe os dois.

Ele também destaca os primeiros caracteres se eles forem suficientes para identificar exclusivamente o commit. Quando termino uma solicitação pull, muitas vezes já sei de cor os commits, já que os IDs são muito curtos, geralmente com apenas dois caracteres:

jj edit yz
jj edit qu
# etc.

Fluxo de trabalho típico

  1. Obtenha as alterações mais recentes:
  1. Inicie um novo commit vazio no topo do branch principal:
  1. Adicione alguns commits. Observe que você não cria um branch. Na verdade, você nunca está “em” um ramo de Jujutsu. Você está apenas em um commit. Parece alarmante, mas você se acostuma muito rápido.

  2. Quando estiver pronto para enviar push, crie um “marcador”:

jj bookmark set -r @- my-branch

Isso é basicamente equivalente a um branch no Git, exceto que se você adicionar novos commits, o marcador permanecerá no lugar. Você pode manualmente defina o marcador em outro commit, mas isso não acontece automaticamente. Mais sobre este comando em um momento.

  1. Envie o novo marcador para o Git:

Idioma Revset

Vejamos esse comando de marcador novamente:

jj bookmark set -r @- my-branch

Veja o -r bandeira? Somos nós dizendo ao Jujutsu que se compromete a colocar o marcador. Este é um exemplo da poderosa linguagem revset que Jujutsu usa para identificar commits. Aqui estou configurando o marcador @-que é o commit imediatamente anterior ao atual. (Lembre-se, normalmente o commit atual é uma espécie de área de teste. O Jujutsu tem alguns blocos úteis para evitar que você envie acidentalmente esse tipo de commit.)

Como tudo no Jujutsu, esta linguagem é altamente ortogonal, o que significa que você aprende alguns blocos de construção e depois se pergunta “posso combiná-los?” esse caminho?” e a resposta é sim. Por exemplo, eu queria fazer um experimento que incorporasse alterações de dois marcadores diferentes.

O fluxo de trabalho do Jujutsu começa com jj newque, como a maioria dos comandos, aceita vários revsets. Então eu pensei, posso fazer um novo commit com base nesses dois marcadores?
E a resposta é sim:

jj new bookmark1 bookmark2

Como parece para todos os outros

Depois de enviar seu favorito, ele parece um branch normal do Git para todos os outros.

Digamos que você precise corrigir alguns erros de linter e falhas de teste após enviar. Você pode editar seus commits existentes e então jj git push. Para os outros, parecerá que você rebaseou o branch.

Se você tiver vários favoritos, jj git push empurra todos de uma vez. Isso torna muito fácil configurar uma pilha de solicitações pull com um marcador cada. Você pode fazer edições para cima e para baixo na pilha e jj git push para atualizar todas as solicitações pull de uma vez.

Conselhos práticos para começar

Se você quiser experimentar Jujutsu, recomendo o tutorial de Steve Klabnik. Os documentos oficiais também são muito bons.

Você provavelmente desejará usar o Jujutsu com um repositório Git existente. Veja como fazer isso:

jj git init --git-repo /path/to/repo

Algumas armas de pé a serem observadas:

  • Desative toda a integração do Git no seu IDE. A recomendação oficial é tratar o repositório Git como somente leitura. Todas as operações de gravação devem ser feitas através do Jujutsu, não do Git. Se você usar o Git para criar um commit ou algo assim, o Jujutsu fará o possível para sincronizar-se com essas alterações, mas pode ficar um pouco complicado. Você pode acabar vendo alterações em um estado “conflitante”, onde uma única alteração está associada a dois commits diferentes. Descobri que o VSCode realiza muitas operações do Git automaticamente em segundo plano.

  • Os submódulos não são suportados e são completamente ignorados pelo Jujutsu. Achei que isso funcionava bem no monorepo em $WORK, mas se você mudar para um commit que tenha um submódulo adicionado ou removido de onde você estava anteriormente, as coisas podem ficar permanentemente complicadas. Para ser justo, isso não é muito diferente da experiência normal do submódulo Git.

Boa sorte!



Source link

Postagens Similares

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *