2 Punkte von GN⁺ 15 일 전 | 1 Kommentare | Auf WhatsApp teilen
  • jj, die Kommandozeilenschnittstelle von Jujutsu, ist ein Tool auf Basis eines verteilten Versionsverwaltungssystems (DVCS)
  • Bietet einfachere und intuitivere, zugleich aber leistungsfähigere Funktionen als git
  • Kombiniert die Stärken von git und Mercurial und reduziert so die Zahl der Kernwerkzeuge bei zugleich engerer, organischer Verzahnung
  • Verwendet ein git-kompatibles Backend, sodass bestehende Kollaborationsumgebungen erhalten bleiben und dennoch unabhängige Experimente möglich sind
  • Für fortgeschrittene Nutzer ist besonders wichtig, dass sich zusätzliche Versionsverwaltungsfunktionen nutzen lassen, die mit git nur schwer umzusetzen sind

Einführung in jj und seine Merkmale

  • jj ist die CLI (Kommandozeilenschnittstelle) von Jujutsu, und Jujutsu ist ein verteiltes Versionsverwaltungssystem (DVCS)

    • Nutzer sind möglicherweise mit anderen DVCS wie git vertraut, und das Tutorial setzt die Perspektive von git-Nutzern voraus
    • jj wurde als einfacheres, leichter nutzbares und zugleich leistungsstarkes Tool als git konzipiert
    • Üblicherweise stehen sich „Leistungsfähigkeit“ und „Komplexität“ entgegen, doch jj präsentiert hierfür ein neues Gleichgewicht
    • jj vereint die Stärken von git und Mercurial (hg) und bildet damit eine neue Form von DVCS
    • Es reduziert die Zahl der Kernwerkzeuge und bietet durch die organische Verzahnung der einzelnen Werkzeuge eine effiziente Arbeitsumgebung
    • Fortgeschrittene Nutzer können zusätzliche Versionsverwaltungsfunktionen verwenden, die mit git nur schwer möglich sind
    • jj nutzt ein git-kompatibles Backend, sodass unabhängige Experimente möglich sind, ohne die Kollaborationsumgebung zu verändern
    • Die Kompatibilität mit bestehenden git-Repos bleibt erhalten, und bei Bedarf lässt sich leicht zu git zurückkehren
    • Das Tutorial kündigt an, anhand dieser Eigenschaften direkt zu zeigen, warum jj ein beachtenswertes Tool ist

1 Kommentare

 
GN⁺ 15 일 전
Hacker-News-Kommentare
  • Viele der Diskussionen konzentrieren sich auf die Unterschiede zwischen git und jj, aber ich denke, es ist besser, git einfach zu vergessen und sich auf den grundlegenden Workflow von jj zu konzentrieren
    In einem sauberen Repository kann man mit jj den Status prüfen, und nach Änderungen einfach mit jj commit -m "made changes" committen
    Wenn man einen Fehler gemacht hat, korrigiert man ihn und fügt ihn mit jj squash dem letzten Commit hinzu
    Nur wenn man wie bei einem neuen Branch auf einer bestimmten Revision arbeiten will, braucht man jj new -r lmnop
    Die git-Historie kann man mit git log ansehen, und die internen Abläufe von jj sind nicht sichtbar

    • Ich wollte etwas Ähnliches und habe deshalb git-Aliasse wie alias.save="!git add -A; git commit -m" angelegt, die ich dann als $ git save "made changes" nutze
  • JJ fühlt sich für mich so an, als würde es verlangen, rückwärts zu denken
    In git schreibt man nach den Änderungen die Commit-Nachricht, während man in jj zuerst einen neuen Commit erstellt und ihn dann beschreibt
    Ich bin es gewohnt, aus einem schmutzigen Zustand mit mehreren vermischten Features nur die nötigen Änderungen auszuwählen und zu committen, und nach dem jj-Tutorial bin ich nicht sicher, ob das möglich ist

    • jj new ist so etwas wie ein leerer git-Staging-Bereich
      In jj existiert immer ein Commit, und dieser Commit hat anhand des Ordnerinhalts eine berechnete stabile Change-ID
      Wenn man mehrere Änderungen aufteilen und separat committen möchte, kann man jj split verwenden
    • Ich erstelle häufig mit jj new temporäre Commits und lasse die Nachricht leer
      Später, wenn alles bereit ist, squashe ich mehrere Commits zu einem und füge eine Nachricht hinzu
      Diese Methode funktioniert wie eine Art Undo-Historie und macht Experimente viel angenehmer
    • Tatsächlich bedeutet jj new einfach nur „oben einen neuen Commit erstellen“, also muss man nicht sofort eine Beschreibung schreiben
      Ich habe am Anfang auch versucht, mir das anzugewöhnen, aber das war eher ineffizient
    • In JJ ist diese Arbeitsweise Standard
      Auch für Git wurde ein ähnlicher Workflow empfohlen, und mit dem Squash Workflow lässt sich ein Ablauf aufbauen, der dem Git-Index ähnelt
    • Wenn ich an mehreren Änderungen arbeite, vermischen sich oft unterschiedliche Features
      Deshalb nutze ich mehrere Workspaces und häufig die shelve-Funktion von IntelliJ
      Manchmal speichere ich Diffs auch temporär als git-Patch
      Diesen chaotischen Prozess versuche ich vor meinen Kollegen zu verbergen, um etwas professioneller zu wirken
  • Was mir an jj nach dem Ausprobieren nicht gefällt, ist, dass Dateibearbeitungen automatisch committet werden
    Wenn ich zum Durchsehen alter Commits ein Checkout mache und dann Dateien ändere, wird dieser Commit verändert und die gesamte nachfolgende Historie neu rebased
    Deshalb muss ich vorsichtshalber einen neuen leeren Commit anlegen
    Bei git ist das angenehmer, weil sich das Repository nicht verändert, bis ich ausdrücklich committe

    • Das dachte ich früher auch, aber nachdem ich jj evolog kennengelernt habe, hat sich das geändert
      jj hatte bereits eine bessere Lösung als Staging
      Meine Vertrautheit mit der git-CLI war eher ein Hindernis beim Lernen von jj
      Interessanterweise versteht man mit jj auch die Architektur der Storage-Engine von git besser
    • Wenn man statt edit jj new verwendet, lassen sich Änderungen sauber verfolgen
      Das fühlt sich viel besser an, als mit dem git-stash zu jonglieren
    • jj edit ist die größte Falle von jj
      Stattdessen sollte man jj new verwenden, und wenn etwas schiefgeht, kann man es mit jj undo wiederherstellen
      jj behandelt Commits als billige Snapshots, daher sollte man sich eher auf „Änderungen“ als auf Commits konzentrieren
      Automatisches Rebase wird nach dem Push unveränderlich fixiert und ist damit sicher
    • Dass Dateibearbeitungen automatisch committet werden, ist eine Kernfunktion von jj
      Mit jj new und jj squash kann man das wie die Branch-Heads in git verwalten
      jj macht es leicht, in einem Detached-Head-Zustand zu arbeiten
    • Vermutlich hast du mit jj edit einen älteren Commit ausgecheckt
      Wenn du auf jj new umsteigst, sollte das Problem verschwinden
  • Der letzte Absatz zu jj ist der Kernpunkt
    Es verwendet ein vollständig kompatibles Backend zu git, daher kann man es allein ausprobieren, ohne dass das ganze Team umsteigen muss
    Wenn es einem nicht gefällt, kann man jederzeit zu git zurückkehren

    • Außer natürlich in Organisationen, die LFS, Submodule oder Hooks verwenden
    • Es ist nicht vollständig kompatibel. Interoperabel ja, aber nicht vollkommen nahtlos
      Git-Operationen werden nicht im jj-Log erfasst und müssen manuell importiert werden
      Für ein Projekt wird empfohlen, nur eine Schnittstelle zu verwenden
    • Früher habe ich git auch so zusammen mit CVS und Subversion verwendet
    • Aber wenn man git und jj gleichzeitig im selben Verzeichnis verwendet, kann es kaputtgehen
  • Mein Lieblingsfeature ist eindeutig jj absorb
    Es verschiebt Änderungen aus der aktuellen Revision automatisch in frühere passende Commits
    Das ist nützlich, wenn man zum Beispiel vergessen hat, die Konfigurationsdatei oder .gitignore anzupassen
    Man macht jj new, nimmt die Änderungen vor und führt dann jj absorb aus
    Und das Beste daran ist, dass man sich nicht mit Merge-Konflikten herumschlagen muss

    • Wenn jj absorb etwas falsch zuordnet, kann man es mit jj undo rückgängig machen
      Dank dieser Funktion wirken selbst komplexe Rebases nicht mehr einschüchternd
    • Übrigens gibt es in git auch git absorb
  • Ich konnte das Tutorial lange nicht aktualisieren, benutze jj aber immer noch täglich
    Im Startup ersc.io war ich zu beschäftigt, um an Upstream zu arbeiten
    Fragen sind jederzeit willkommen

    • Der entscheidende Punkt ist der Unterschied der DAG-Unveränderlichkeit zwischen git und jj
      jj verwendet stabile Change-IDs, git dagegen unveränderliche Commit-IDs
      Deshalb fühlen sich Undo und Rebase in jj viel flexibler an
    • jj blendet „uninteressante“ Änderungen automatisch aus
      Manchmal möchte ich aber mehr Änderungen sehen und frage mich, ob es eine Option gibt, sie alle auf einmal anzuzeigen
  • jj unterscheidet sich genug von git, dass es einen Versuch wert ist
    Schon allein eine andere Herangehensweise kennenzulernen, erweitert den ingenieurtechnischen Horizont
    Man muss nicht alles ausprobieren, aber es ist wichtig, die Trade-offs verschiedener Workflows zu verstehen

    • Natürlich kann in 99 % der Fälle ein Versuch mit geringem Nutzen auch einfach Zeitverschwendung sein
  • Die Beziehung zwischen git und jj fühlt sich an wie die zwischen C und Python
    git ist forensische Nachverfolgung, jj eher Kapitel einer Geschichte
    Manchmal muss man frühe Kapitel umschreiben, damit spätere natürlicher wirken

    • Was jj macht, ist in git auch möglich, aber die eingeübte Denkweise von git steht im Weg
      jj ist mit der Philosophie entworfen, dass „der Working Tree selbst ein Commit ist“ und dass man „sogar Konflikte committen kann“
  • Bei der Behauptung „mächtiger und einfacher“ finde ich, dass konkrete Beispiele nötig sind

    • Einige Vorteile von jj wären zum Beispiel:
      • Rebase-/Merge-Konflikte müssen nicht sofort gelöst werden
      • Commit-Manipulationen sind sehr einfach, besonders mit jjui
      • jj hat ein Operation Log, das Zustandsänderungen von git nachverfolgt
      • Namenlose Branches machen experimentelle Arbeit unkompliziert
      • Es ist vollständig mit git kompatibel, sodass gemischte Nutzung im Team möglich ist
    • Als wir von SVN zu git gewechselt sind, haben wir eine große Verbesserung gespürt, aber im heutigen git-Workflow haben wir keine großen Probleme
    • Man kann in einem Repository gleichzeitig an mehreren PRs arbeiten und jede passend pushen
      Wenn man so etwas nicht braucht, spürt man den Wert von jj vielleicht nicht
    • Der Reiz von jj liegt nicht in den Befehlen, sondern im intuitiven Workflow
      Man versteht das erst, wenn man es selbst benutzt
    • Schon jj undo allein ist den Einsatz wert
      In git landet man leicht in einem Zustand, der sich nicht wiederherstellen lässt, während in jj ein paar Undo-Schritte oft genügen
  • Dank jj bin ich viel sicherer im Umgang mit nichtlinearen DAGs geworden
    Ich gehe frei mit Änderungen um, die mehrere Eltern oder Kinder haben
    Früher habe ich unnötig eine Reihenfolge erzwungen, jetzt kann ich Abhängigkeiten klar ausdrücken
    Auch Review und Einreichung sind dadurch deutlich effizienter

    • Ich frage mich, ob ihr auf solchen verzweigten Änderungen einen Mega-Merge + absorb-Workflow verwendet