2 Punkte von GN⁺ 2025-07-23 | 1 Kommentare | Auf WhatsApp teilen
  • Jujutsu (jj) ist ein Versionsverwaltungssystem mit einfacheren Konzepten und Befehlen als Git, bietet dabei aber leistungsstarke Funktionen
  • Da es Git als Backend nutzt, hat es den Vorteil, dass man es parallel verwenden oder leicht zu Git zurückkehren kann
  • Funktionen wie Stacked Diffs, einfaches Rebase und temporäre Revisionen sind ganz natürlich verfügbar
  • Es nutzt das Konzept von Bookmarks statt Branches, was für den Arbeitsalltag intuitiver ist
  • Die Art der Konfliktbehandlung ist flexibel und macht alltägliche Versionsverwaltungsaufgaben deutlich einfacher

Elevator Pitch

Jujutsu (jj) ist ein Versionsverwaltungssystem, das im Vergleich zu Git ein deutlich einfacheres Denkmodell und eine klarere Kommandozeilenschnittstelle bietet.
Ohne dafür Funktionen zu opfern – tatsächlich kann man es sogar als leistungsfähiger ansehen.
Stacked Diffs, einfaches Rebase und temporäre Revisionen funktionieren ganz selbstverständlich.
Da Git als Backend verwendet wird, kann man mit nur einer Zeile parallel zu einem Git-Repository loslegen und jederzeit wieder zu Git zurückkehren.
Auch die Art und Weise, wie andere Benutzer mit dem Repository arbeiten, wird dadurch nicht beeinflusst.

Getting Started

  • Nach der Installation des Kommandozeilenwerkzeugs jj werden Benutzerinformationen und Shell-Autovervollständigung empfohlen
  • Für die Nutzung in einem bestehenden Repository ist es sinnvoll, entweder neu zu klonen oder im unveränderten Zustand zu beginnen
  • In einem bestehenden Repository kann man mit jj git init --colocate . parallel ein Git- und ein Jujutsu-Repository anlegen
  • Die Repository-Daten von jj werden in einem separaten Ordner .jj/ gespeichert, getrennt von Gits .git
  • Die Datensynchronisierung zwischen Git und Jujutsu funktioniert standardmäßig problemlos
  • Allerdings löscht der Befehl git clean -fdx den Ordner .jj/, daher ist Vorsicht geboten
  • Auch das Tracking von Remote-Branches kann mit diesem Befehl auf einmal eingerichtet werden

How To Use It

Die Kommandozeilenschnittstelle von Jujutsu ist schmaler und kompakter als die von Git.
Die Grundkonzepte sind einfach, aber an den Arbeitsablauf muss man sich etwas gewöhnen.
Die wichtigsten Nutzungsweisen werden mit einfachen Abläufen und Beispielen erklärt.

Starting A New Revision

  • Neue Arbeit beginnt in Git normalerweise mit dem Erstellen eines Branches, in Jujutsu dagegen durch das Anlegen einer neuen Revision
  • Den neuesten Stand des Remote-Repositorys holen: jj git fetch
  • Repository-Historie ansehen: jj log
  • Revisionen in der Historie werden durch eine eindeutige Jujutsu-spezifische Revisions-ID und einen Git-Commit-Hash unterschieden
  • Einen neuen Arbeitsstand beginnt man mit jj new main, wodurch eine neue Revision auf dem aktuellen main erstellt wird
  • Die aktuell bearbeitete Revision wird mit dem Symbol @ gekennzeichnet
  • Wenn gemeinsame Präfixe wegfallen, ändern sich entsprechend auch die kurzen Präfixe der Revisions-IDs

Making Changes

  • Wenn Dateien geändert werden, werden sie sofort Teil dieser Revision (es gibt keine separate Staging Area)
  • Sind die Änderungen fertig, fügt man der Revision mit jj describe -m "Nachricht" eine Nachricht hinzu
  • Eine neue Revision erstellt man mit jj new (oder unter Angabe einer vorherigen Revision)
  • jj commit ist eine kombinierte Operation aus jj describe + jj new

Navigating

  • Mit jj new erzeugte leere Revisionen werden beim Wechseln automatisch verworfen
  • Revision explizit löschen: jj abandon <rev ID>
  • Löschen rückgängig machen: jj op undo
  • Zu einer bestehenden Revision zurückkehren: jj edit <rev ID>
  • Beim Referenzieren von Revisionen können auch Revset-Ausdrücke verwendet werden:
    • @: aktuelle Revision
    • x-: Eltern-Revision
    • y+: Kind-Revision
    • z::: alle Nachkommen von z

Branches (Bookmarks)

  • Jujutsu kennt anders als Git keinen Zustand, in dem man „auf einem Branch bleibt“
  • Stattdessen sind Bookmarks lediglich Zeiger auf eine bestimmte Revision
  • Neues Bookmark erstellen: jj bookmark create <Name> -r <Revision>
  • Auch nach einem Commit wird das Bookmark nicht automatisch verschoben; falls nötig, muss es mit jj bookmark move <Name> --to <Revision> separat verschoben werden
  • Beim Push muss mit dem Flag --allow-new das Erstellen eines neuen Remote-Branches erlaubt werden
  • Wenn ein Bookmark vom Remote-Stand abweicht, wird es mit * markiert und kann mit jj git push synchronisiert werden

Conflicts

  • Die Konfliktbehandlung von Jujutsu ist flexibler als die von Git
  • Bei Konflikten wird die Markierung „conflicted“ an der Revision und ihren Nachkommen angezeigt
  • In konfliktbehaftete Dateien werden Konfliktmarker eingefügt; gelöst wird der Konflikt, indem diese Marker entfernt werden
  • Man kann direkt bearbeiten oder die Änderungen in einer neuen Revision vornehmen und anschließend mit jj squash zusammenführen

Fazit

Damit ist gezeigt, wie sich die 80 % der in Git am häufigsten genutzten Aufgaben mit Jujutsu einfacher erledigen lassen.
Eine Referenz für allgemeine und fortgeschrittene Nutzung soll später in Form eines Quick Reference folgen.
Wie bei Git wird auch der Befehl jj status unterstützt.
Fragen oder Feedback sind über die im Text genannte E-Mail möglich.

1 Kommentare

 
GN⁺ 2025-07-23
Hacker-News-Kommentare
  • Für alle, die überlegen, ob es sich lohnt, jj zu lernen, möchte ich einen Punkt besonders hervorheben.
    Wenn man auf Hacker News über jj spricht, teilt es sich meist in zwei Gruppen: Leute, die es noch nicht ausprobiert haben, und Leute, die es stark empfehlen.
    Ich habe fast nie erlebt, dass jemand nach einer Woche mit jj wieder zu git zurückgekehrt ist.
    Wer es wirklich ernsthaft ausprobiert hat, ist fast immer bei jj geblieben.
    Ich hoffe, heute wird der Anlass, jj einmal auszuprobieren.
    Der Umstieg ist deutlich einfacher als gedacht, und ich blieb sogar am ersten Tag sofort produktiv; innerhalb einer Woche musste ich überhaupt nicht mehr zu git-Kommandos zurückkehren.
    Ich wurde in kurzer Zeit produktiver und kann kaum glauben, wie ich vorher mit git gearbeitet habe.

    • Ich empfinde git in Sachen Produktivität überhaupt nicht als störend.
      Ich nutze git-Kommandos auch nicht jeden Tag stundenlang, und in den meisten Fällen behindert es meine Arbeit nicht.
      Wenn man ein Repository viel direkt mit git manipulieren muss, ist jj vielleicht besser, aber das trifft auf meine Situation nicht zu.
      Es ist ähnlich wie der Vorschlag, unbedingt bim auszuprobieren, das vim sehr ähnelt, aber zusätzliche Funktionen hat.
      Mich interessiert aber nicht, ob ich ein paar Mal weniger oder mehr i tippen muss, und ich brauche auch kein Julia-Autocomplete.
      Wer jj besser findet, soll gern Freude daran haben.

    • jj ist in der VCS-UI definitiv ein Fortschritt, aber für fortgeschrittene git-Nutzer gibt es ein paar Einschränkungen.
      Durch die fehlende Unterstützung für gitattributes ist es unpraktisch, wenn man Filter wie git-crypt oder git-lfs braucht.
      Auch die Kompatibilität unter Windows, etwa bei Zeilenenden, kann schlechter sein.
      Außerdem integrieren externe Tools wie git-annex oder git-bug sich nicht in das oplog und können die Historie unübersichtlich machen.

    • Ich habe es tatsächlich länger als eine Woche benutzt und bin dann wieder zu git zurückgegangen.
      Persönlich gefällt mir der Workflow mit der Staging Area besser; die meisten mögen git-Staging nicht, aber für mich war der Vorteil nicht groß genug, um das in jj aufzugeben.
      Gewohnheiten lassen sich ändern, aber bisher bin ich nicht bereit, mich bewusst an jj zu binden.
      Ich bin aber offen dafür, es irgendwann noch einmal zu versuchen.

    • Ich habe jj einige Monate lang genutzt und bin dann wegen Performance-Problemen wieder zu git zurück.
      Operationen in jj dauerten mehrere Sekunden, während git unabhängig von der Projektgröße sofort reagierte.
      Außerdem fühlte sich die Arbeit mit jj für mich mental etwas komplexer an, und mit git wurde wieder alles leichter.
      Das kann auch einfach an meiner langen Erfahrung mit git liegen.

    • Schon die Aussage „Es gibt sowieso nur zwei Gruppen“ klingt nach dem typischen Spruch von jj-Evangelisten.

  • Was mich an jj wahnsinnig macht, ist, dass Änderungen immer automatisch gestaged werden.
    So war es früher schon bei SVN, und ich hatte bei git das Gefühl, dass das explizite Staging eine deutliche Verbesserung war.
    In einem Repository gibt es oft mehr Änderungen, und in den nächsten Commit will man nur eine Auswahl davon übernehmen; bei git ist das selbstverständlich.
    Bei jj (einschließlich SVN) braucht man vor dem Commit umständliche Handarbeit, etwa Änderungen vorübergehend auszulagern.

    • Dieses Thema ist für mich auch ein Dilemma.
      Staging war immer lästig, und selbst bei Mercurial fand ich das schwierig.
      Wenn man in über 90 % der Fälle automatische Aufnahme braucht, ist es sogar bequemer, aber problematisch sind Dateien, die man nicht in .gitignore packen kann.
      Wenn man Auto-Add ausschaltet, ist es unbequem, und wenn man es einschaltet, bleibt es irgendwie unbefriedigend.
      Keine der beiden Seiten ist wirklich sauber.

    • Der Workflow von JJ ist etwas anders: Man erstellt zum Beispiel zuerst einen Basis-Commit und stapelt darauf anonyme Commits für die Arbeit.
      Wenn alles bereit ist, räumt man mit jj squash oder jj split auf.

    • Ich nutze jj commit -i, die -i-Option bei verschiedenen Kommandos und in der Konfiguration snapshot.auto-track="none()".
      Bei Mercurial habe ich es ähnlich gemacht.
      In der Praxis werden unnötige Dateien oder Chunks ohnehin automatisch ignoriert, wenn man die Absorb-Funktion häufig nutzt.

    • Ist der Befehl jj new nicht genau für den Workflow gedacht, den du willst?

    • jj verfolgt auch Branches korrekt, die im Baum nicht am Head hängen, deshalb funktionieren Rebase und Merge reibungslos, ohne dass man stashes braucht.

  • Es fällt mir nicht leicht, mich an das automatische Hinzufügen von Änderungen zu gewöhnen.
    Manchmal ändere ich lokal bestimmte Dateien nur vorübergehend während der Entwicklung, ohne sie committen zu wollen.
    Bei git bin ich beruhigt, weil nichts jemals committet oder gepusht wird, solange ich es nicht stage.
    Bei jj habe ich das Gefühl, dass ich etwas unstage’n oder besonders aufpassen muss.
    Das mag ein Gewohnheitsthema sein, aber ich finde es angenehmer, klar festzulegen, was ich committen will.
    Vielleicht habe ich jj auch einfach falsch verstanden.

    • In jj kann man Änderungen mit jj split aufteilen.
      Was man auswählt, landet in der ersten Revision, der Rest in der zweiten.
      Wenn man mehrere Dinge gleichzeitig gemacht hat und sie in mundgerechte Revisionen zerlegen will, ist das viel leichter als in git.
      Man kann wie in git eine neue Revision mit jj new anlegen, Änderungen machen und mit jj squash -i genau die gewünschten Teile verschieben.
      Konzeptionell ist „@“ die aktuelle Revision und „@-“ die direkt davor, also kann man es ähnlich wie Working Copy und Stage in git verstehen.

    • Das automatische Staging von jj ist nicht immer gut.
      Ich wünschte, die offizielle jj-Dokumentation und Einsteiger-Guides würden deutlicher machen, dass man den Standard leicht abschalten kann.
      In ~/.jjconfig schreibt man einfach
      [snapshot]
      auto-track = "none()"
      so hinein.

    • Ich räume meine Commits meistens nach der Arbeit mit jj split auf, indem ich prüfe, was wirklich in den Commit soll.
      Dieser Workflow bewegt sich ähnlich wie add -p in git.
      Den obersten Commit kann man normalerweise wie eine Working Copy verwenden, die man nicht pusht.
      Auch ohne Stash bleibt laufende Arbeit beim Wechseln zwischen Branches gut erhalten.

    • Ja, diese Gewohnheit fiel auch mir nicht leicht zu ändern.
      Die rationale Begründung dafür, dass man sie ändern sollte, ist, dass man Code nicht in einem untracked Zustand ausführen sollte.
      Sinnvolle Änderungen sollte man in Commits festhalten, den Rest besser nicht dokumentieren.
      Problematisch wird es, wenn Einstellungen auf Repository-Ebene und lokale Einstellungen nicht getrennt sind, VSCode ist dafür ein typisches Beispiel.
      Dann braucht man Änderungen, die je nach Umgebung nicht committet werden dürfen, und das macht alles komplizierter.

    • Wenn du so einen Workflow willst, kannst du in jj „@“ wie den git-Index behandeln und zur Commit-Zeit nach „@-“ squashen; damit bekommst du einen ähnlichen Effekt wie mit git add --patch.

  • Ich versuche gerade erfolglos, mein Team zu jj zu bewegen.
    Es wäre gut, eine Seite zu haben, die auf einen Blick zeigt, wie einfach sich komplizierte Aufgaben aus git in jj erledigen lassen.
    So etwas wie ein Elevator Pitch, ganz knapp.
    Ich denke auch, dass ich es wahrscheinlich selbst vorführen müsste.

    • Viele der üblichen git-Aufgaben sind in jujutsu vermutlich nicht einfacher.
      Stattdessen gibt es in jujutsu neue Workflows, die in git unmöglich oder umständlich sind.
      Für Entwickler, die an bestehende git-Muster gewöhnt sind, ist das vielleicht nicht sofort eingängig.

    • Ich mag git auch nicht besonders.
      Früher habe ich nur Mercurial benutzt, aber heute ist git einfach tief in meinem Kopf verankert.
      Selbst wenn Jujutsu klare Vorteile hätte, ist es für mich noch nicht attraktiv genug, mich zusätzlich um das anfängliche Setup zu kümmern, etwa komplexe Farbeinstellungen oder vertraute Skripte.

    • Mir hat ein direkter Vergleich einer repräsentativen Aufgabe zwischen jj und git sehr geholfen.
      https://lottia.net/notes/0013-git-jujutsu-miniature.html

    • Ich empfehle auch ein paar gute Links, die hilfreich sein könnten.
      https://v5.chriskrycho.com/essays/jj-init/
      https://v5.chriskrycho.com/journal/jujutsu-megamerges-and-jj-absorb/
      https://ofcr.se/jujutsu-merge-workflow

    • Der nächste Abschnitt, den ich diesem Post bald hinzufügen werde, wird dir vermutlich gefallen.
      Ich werde ihn in Kürze unten auf der Seite und zusätzlich in einem separaten Post veröffentlichen.

  • Ich habe jj einige Wochen genutzt und mir sogar ein Skript für automatische Commit-Messages gebaut.
    Heute wollte ich dasselbe Skript auf ein altes git-Repository portieren und merkte, dass ich in git Code bräuchte, um automatisch zu erkennen, ob gerade ein Commit oder ein Amend stattfindet.
    Dank der immutable-Commit-Struktur von jj war das Skript dort sehr einfach.
    Ich habe das Repository einfach neu mit jj geklont.
    Damit war ich sofort von der Verwirrung zwischen Commit und Amend befreit.
    https://codeberg.org/jcdickinson/nix/src/branch/main/home/common/scripts/jj-auto.fish

    • Du musst nicht unbedingt neu klonen; du kannst jj einfach zusätzlich in einem bestehenden git-Repository verwenden.
  • git funktioniert gut genug.
    Es hat nur eine gewisse Lernkurve, aber wenn man es einmal verstanden hat, ergibt alles Sinn.
    Ehrlich gesagt reichen in 95 % der Fälle pull, add, reset, branch und commit völlig aus.

    • In meinem Workflow sind stacked diffs unverzichtbar.
      Man wird nicht durch wartende Reviews blockiert und kann künftige Arbeit gut vorab aufstapeln.
      Das Setup in git ist nicht schwer, aber untere Teile eines Stacks zu ändern und dann alles neu zu restacken, ist die Hölle.

    • Wenn man mit anderen zusammenarbeitet, ist es unverzichtbar, Rebase und Squash zu beherrschen.
      Man kann dem kaum ausweichen, solange man nicht das ganze Team überzeugt, es nicht mehr zu benutzen.
      Gerade wenn mehrere Personen hastig an einem Branch arbeiten, fühlen sich die git-Gewohnheiten schnell unerquicklich an.
      Im Alltag ist es bequem, aber in komplexen Situationen gibt es viele Probleme.

    • Schon wenn man nur ein paar ungewöhnliche Situationen erlebt, sieht man die Schwächen von git.

  • Ich nutze jj jetzt etwa seit zwei Wochen und habe zum ersten Mal das Gefühl, Versionsverwaltung bequem nur über die Kommandozeile zu bedienen.
    Mit git habe ich fast immer die GUI benutzt, vor allem per Rechtsklick in Git Graph in VSCode.
    jj dagegen konnte ich schon nach dem Lesen des Tutorials direkt konsistent über die CLI verwenden.
    Allerdings scheint es nötig zu sein, die Revset-Sprache zu lernen, wenn man verhindern will, ständig IDs aus dem jj-Log zu kopieren und einzufügen.

    • Bei mir ist es ähnlich.
      Ich nutze git schon lange, habe kompliziertere Dinge aber immer über eine UI erledigt.
      Seit fast einem Monat verwende ich nur noch die jj-CLI und bin ziemlich zufrieden.
      Allerdings ist die offizielle jj-Dokumentation so geschrieben, als setze sie Grundwissen voraus, was für Anfänger verwirrend sein kann.
      Ich hoffe, dass es mehr Blogs und Tutorials dazu geben wird.
      Ich möchte auch mehr über die Revset-Sprache und über Rebase lernen.
      Die schlanke CLI, die Konfliktlösung und das oplog gefallen mir alle sehr.

    • Ich fand das Kopieren und Einfügen von IDs auch lästig, aber seit ich jjui(https://github.com/idursun/jjui) nutze, läuft alles viel flüssiger.
      Man arbeitet fast so schnell, als würde man einfach durch das Log scrollen.

  • Ich finde, die beste Funktion von jj ist Undo.
    git macht Undo schwierig, weil man je nach Art des Fehlers unterschiedliche Kommandos braucht.
    In jj reicht einfach einmal jj undo.
    Es hängt auch nicht am Backend-System fest; selbst wenn man jj nur lokal für sich nutzt, hat das keine Auswirkungen auf Kollegen.

  • Ich bin verwirrt, was jj eigentlich ist.
    Ist es ein Frontend für Leute, die git verwirrend finden?
    Es abstrahiert zwar das Backend, ist aber so stark von git geprägt, dass ich mir schwer vorstellen kann, wie das bei Systemen wie Perforce oder Piper funktioniert, wo fortlaufend nummerierte Commits erzwungen werden.
    Das Design Working Copy = Commit scheint für mich keine Qualitätskontrolle zuzulassen.
    Der ursprüngliche Sinn eines Commits ist doch, nur bewusst Gewolltes aufzunehmen, und mit so einer Struktur wird es noch schwerer, „Müll-Commits“ zu unterscheiden.
    Sowohl git als auch jj wirken auf mich für sehr große Projekte schwach, und das Problem ausufernder Commits scheint damit auch nicht gelöst zu sein.
    Ich frage mich also, welches Problem jj tatsächlich lösen will, oder ob es einfach nur ein Frontend nach dem Geschmack seines Autors ist.

    • Das Piper-Backend funktioniert sogar natürlicher als das Git-Backend.
      jj-Commits entsprechen nicht eins zu eins git-Commits, deshalb muss man das nicht missverstehen.
      Mit „Commit“ ist in der Praxis eher ein „benannter Diff“ gemeint, und Änderungen vor dem Push lassen sich jederzeit leicht umwerfen und neu ordnen.
      Das ist viel bequemer als Rebase oder History-Bearbeitung in git.
      Ich erstelle während der Arbeit mehrere Commits für Experimente, Dokumentation usw., die ich in git sonst in Stashes oder temporäre Branches hätte quetschen müssen.

    • jj ist mehr als ein git-Frontend.
      Es ist ein Versionsverwaltungssystem und backend-agnostic.
      Das wichtigste Backend ist git, deshalb kann man sofort in bestehenden Repos umsteigen.
      Ich nutze git schon seit vor dem Erscheinen von GitHub, aber seit jj kann ich nicht mehr zu git zurück.
      jj ist einfacher und zugleich leistungsfähiger.
      Working Copy = Commit sollte man praktisch eher als „auch der Index ist ein Commit“ verstehen.
      Wenn man zum Beispiel mit Feature x beginnt, erstellt man mit jj new -m "working on feature x" trunk einen neuen Commit und legt darüber noch einen leeren Commit.
      Die eigentliche Arbeit landet in der Working Copy (@), und durch „Verschieben“ (squash) in den vorherigen Commit (@-) verarbeitet man alles über Diffs zwischen Commits statt über komplizierte git-Optionen wie add-p oder reset.
      Dadurch lassen sich Commits flexibler und mächtiger aufteilen und aufräumen als mit dem git-Index.
      Das Problem einer Commit-Flut hängt eher mit der Pull-Request-Kultur zusammen, und jj kann das nur teilweise lösen.

    • Die Working Copy wird nicht einfach blind zu GitHub gepusht; man kann sie beim Hinzufügen der Commit-Beschreibung noch prüfen und aufräumen.

  • Ich habe jj ein paar Tage ausprobiert, bin aber mit meinem bestehenden lazygit, meinem Workflow und meinem Skript-Setup vollkommen zufrieden.
    jj ist originell und durchaus gut, aber wenn man nicht gerade erst mit Versionsverwaltung anfängt, fehlt mir die Motivation zum Wechsel.

    • Wenn man andere Tools wie GitButler nutzt, ist das Frontend weniger wichtig, aber ich habe vor ein paar Tagen Jujutsu eingeführt, Claude nach den wichtigsten Aktionen gefragt (Commit, Branch-Wechsel, GitHub-Push/Pull) und war in zehn Minuten eingearbeitet.
      Ich nutze weiterhin die Diffs von Lazygit, aber selbst ein detached HEAD ist überhaupt kein Problem.
      JJ ist gut mit git kompatibel und macht alles deutlich einfacher, ohne dass man komplexe Kommandos auswendig lernen muss.
      Dass beim Wechsel zwischen Branches uncommittete Dateien automatisch mitwandern, ist die beste Funktion überhaupt.
      Es ist extrem bequem, zwischen Entwicklung, Bugfixes und Textänderungen hin- und herzuspringen.
      Wenn ein AI-Agent Änderungen macht, kann man dafür getrennte Worktrees verwenden.
      Es ist auch großartig, dass man vor Abschluss der Arbeit schon eine Änderungsbeschreibung (= Commit-Message) vergeben und sie im Baum vorab sehen kann.
      Insgesamt ist JJ wirklich ausgezeichnet.