5 Punkte von GN⁺ 2024-02-14 | 1 Kommentare | Auf WhatsApp teilen
  • Es gibt viele weniger bekannte Funktionen, die selbst langjährige Git-Nutzer leicht übersehen; das stellt die Annahme infrage, dass fortgeschrittenes Kommandozeilenwissen allgemein verbreitet sei
  • Anders als die Generation, die von SVN oder CVS gewechselt ist, hatten Entwickler, die ausschließlich Git genutzt haben, weniger Anlass, bestimmte fortgeschrittene Nutzungsweisen zu lernen
  • Git hat im Laufe der Zeit immer wieder kleine, aber nützliche Funktionen ergänzt; solche Änderungen können in bestimmten Situationen praktischen Wert haben
  • Für fortgeschrittene Nutzer wird das Thema in eine kurze dreiteilige Serie aufgeteilt: alte, aber nützliche Funktionen, kürzlich hinzugekommene Features sowie Themen rund um große Repositories und Monorepos
  • Wer über vertraute Git-Gewohnheiten hinaus noch einmal auf die Funktionen schaut, die leicht unsichtbar bleiben, kann alltägliche Repository-Arbeiten effizienter erledigen

Warum sich ein neuer Blick auf Git lohnt

  • Bei jüngsten Vorträgen zu Git und GitButler wurde deutlich, dass viele Entwickler bei Git vieles nicht kennen
  • Früher gab es Vorträge zu fortgeschrittenem Git, doch in den vergangenen rund zehn Jahren wurde angenommen, dass die Leute fortgeschrittene Kommandozeilenfunktionen bereits kennen
  • Eine Generation von Entwicklern, die nur Git verwendet hat, musste nicht von Tools wie SVN oder CVS zu Git wechseln oder frühere Konzepte neu lernen
  • Auch Git hat mit der Zeit neue Funktionen dazugelernt; die meisten sind subtil oder auf bestimmte Anwendungsfälle zugeschnitten, können in der Praxis aber hilfreich sein
  • Die Blogserie basiert auf dem FOSDEM-2024-Vortrag little known Git stuff

Dreiteilige Serie mit Git-Tipps

  • Zielgruppe sind fortgeschrittene Git-Nutzer; behandelt werden Funktionen, die man auch nach langer Git-Nutzung übersehen haben kann
  • Statt alles in einen einzigen Beitrag zu packen, ist die Serie in drei kurze Artikel mit jeweils einigen Themen aufgeteilt
  • Enthaltene Themen:
  • Der erste Artikel führt weiter zu Oldies but Goodies

1 Kommentare

 
GN⁺ 2024-02-14
Kommentare auf Hacker News
  • Als Autor gebe ich zu, dass ich vieles davon erst ziemlich kürzlich gelernt habe. Die Funktionen rund um große Repositories wurden in den letzten Jahren von Microsoft und GitHub nach und nach in den Git-Core eingebracht, weshalb es schwierig ist, eine Ressource zu finden, die ihre Arbeit an einem Ort zusammenfasst.
    Ich hatte auch interessante Gespräche mit den Leuten aus der Mercurial-Ecke; offenbar erzielen sie derzeit erstaunliche Geschwindigkeitsverbesserungen, indem sie Teile der Hg-Interna in Rust schreiben.
    Ich denke auch über eine 3. Ausgabe von Pro Git nach. Wenn es also Dinge gibt, die ihr beim mühsamen Lernen von Git herausgefunden habt oder über die ihr gern mehr wissen würdet, lasst es mich wissen.
    • Vielleicht kennt ihr es schon, aber difftastic eignet sich gut als Ersatz für Gits diff: https://difftastic.wilfred.me.uk/
      Als häufig genutzte gitconfig-Aliasse verwende ich fza, gone und root. git fza zeigt geänderte/neue Dateien in einem fzf-Fenster an und übergibt die ausgewählten Dateien an git add: https://github.com/junegunn/fzf
      git gone löscht lokale Branches, die es auf dem Remote nicht mehr gibt, und git root gibt die Repository-Wurzel aus, was praktisch ist, um aus tiefen Verzeichnissen dorthin zurückzukehren. Heutzutage nutze ich dafür häufiger zoxide, daher brauche ich es weniger: https://github.com/ajeetdsouza/zoxide
    • Beim Abschnitt zu Whitespace-Unterschieden wäre es gut, auch ignore-revs-file aufzunehmen. Man committet eine ignore-revs-Datei ins Repository, und wer eine große Reformatierung vornimmt, fügt den entsprechenden SHA hinzu, damit git blame nicht unbrauchbar wird.
      https://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revltrevgt
    • Eine Sache, die ich bei Git auf die harte Tour gelernt habe: Operationen wie Mergen, Cherry-Picking und Rebase arbeiten nicht mit Snapshots, sondern mit Diffs und Patches, genauer gesagt mit 3-Wege-Merges. Pro Git betont Gits Snapshot-Speichermodell sehr gut, aber wenn man nur in diesem Modell denkt, kann das besonders beim Rebase verwirrend sein.
      Zum Beispiel habe ich nicht verstanden, warum sich alle nachfolgenden Commits ändern, wenn ich während eines Rebase nur einen einzelnen Commit lösche. Erst als mir klar wurde, dass die Speicherung zwar Snapshot-basiert ist, die Operationen aber Diff-basiert sind, habe ich Rebase verstanden. In Schulungen würde es helfen, diesen Punkt stärker zu betonen.
  • Ich will keine Git-Kunststücke lernen, sondern Git so einfach wie möglich verwenden. Ich will nur Code pushen, mit Git fertig sein und weiterarbeiten.
    Ich respektiere Leute, die Git mögen, aber für mich ist es einfach ein Werkzeug, das ich benutzen muss.
    • Ein Teil der Komplexität von Git kommt daher, dass Git ursprünglich als Low-Level-Plumbing entworfen wurde. Man erwartete, dass auf dem Git-Datenmodell eine freundlichere Oberfläche für Nutzer, also Porcelain, entstehen würde. Wenn man eine einfache und konsistente UI will, ist diese Richtung vielleicht auch heute noch die bessere. Jujutsu und Got (game of trees) könnten Beispiele dafür sein.
    • Ich verstehe das Gefühl, aber Git ist nicht ganz so schwierig. Wenn man über die grundlegenden checkout/commit/push hinaus ein paar Dinge kennt, insbesondere History-Rewriting, kann sich die Qualität der Commit-Historie stark verbessern, und andere Engineers im Projekt können den Ablauf leichter nachvollziehen.
      Git wirkt wie eine Konstante, die der Branche noch lange erhalten bleibt, und es ist eines der Werkzeuge, die man in der täglichen Entwicklung am häufigsten berührt. Es lohnt sich also, sich ein wenig damit zu beschäftigen.
    • Manche Details liegen im Problem selbst begründet, andere nicht. Ich denke, man neigt dazu, die inhärenten Schwierigkeiten zu unterschätzen.
      Deshalb finde ich es in Ordnung, dass Git bis zu einem gewissen Grad Komplexität hat.
    • Das klingt ähnlich wie zu sagen, man wolle nicht programmieren lernen und Computer so einfach wie möglich benutzen. Nach dem Motto: einfach sagen, was erledigt werden soll, und fertig.
    • Das Git-Interface fühlt sich wie eine leaky abstraction an. Ich wollte keine Git-Tricks lernen, aber am Ende wusste ich doch mehr darüber, als ich eigentlich wollte.
  • Ich habe gerade etwas Neues über core.fsmonitor gelernt. Aus Sicht eines großen Monorepos wäre es schön, wenn git clone eine Resume-Option hätte.
    In den 2000ern hatte ich dasselbe Problem, als ich über eine Verbindung mit geringer Bandbreite das Kernel-Repository klonen wollte. Nachdem ich auf der Mailingliste um Hilfe gebeten hatte, stellte schließlich jemand das gesamte Repository als komprimiertes Tar-Archiv auf seine private Website, und erst so konnte ich es herunterladen.
    Auch heute passiert mir bei großen Repository-Klons manchmal dasselbe, wenn das Firmen-VPN kurz aussetzt. Man stelle sich vor, das 300-GB-Windows-Repository ist zu 95 % heruntergeladen und dann bricht das WLAN kurz ab.
    Es ist seltsam, dass die beiden bandbreitenhungrigsten Werkzeuge moderner Entwicklungs-Stacks, Git und Docker, das Fortsetzen von Downloads nicht richtig unterstützen.
    • Was du suchst, klingt ziemlich nach git bundle. Allerdings setzt das voraus, dass überhaupt jemand vorher ein Bundle erstellt.
      https://git-scm.com/docs/git-bundle
    • Es müsste wohl möglich sein, erst einen shallow clone zu machen und ihn dann mehrfach zu erweitern. Trotzdem geht das fetch/push-Protokoll im Grunde eher von kleineren Repositories oder sehr guten Internetverbindungen und Servern aus.
  • Sehr interessant. Ich würde gern sehen, wer das Problem, dass mehrere Personen zu unterschiedlichen Releases, Features und Hotfixes beitragen, Releases taggen und in die Vergangenheit zurückgehen, um Bugs zu finden, mit einer einfacheren Schnittstelle lösen kann.
    Das ist ähnlich wie der Wunsch nach einer Low-Level-Sprache, die die Systemkomplexität verbirgt; beides schließt sich im Grunde gegenseitig aus. Git ist zufriedenstellend und nicht so schwer zu lernen, also müssen manche einfach Git lernen.
    • Deshalb empfehle ich GitKraken inzwischen sehr nachdrücklich. Es ist ein kostenpflichtiges Produkt, daher bin ich vorsichtig, aber ich habe viele Tools ausprobiert, und keines hat die Mächtigkeit so gut zugänglich gemacht wie GitKraken.
      Es räumt die Blackbox beiseite, die viele Entwickler im Terminal empfinden, stellt den Graphen in den Vordergrund und zeigt Rebase-Vorgänge visuell so natürlich, dass Git Spaß macht.
      CLI-Kompetenz bleibt wertvoll, aber es ist frustrierend zu sehen, wie Entwickler mit zehn Jahren Erfahrung an grundlegenden Problemen scheitern oder die Projekthistorie ruinieren, weil die Stimmung herrscht: „Ein echter Engineer benutzt nur die Git-CLI.“
      Heutzutage sage ich Leuten: Selbst wenn ihr die CLI nutzt, lasst euch den ganzen Tag in einem anderen Fenster den Graphen anzeigen. Das geht kostenlos in VS Code, JetBrains und sogar in der CLI.

Wenn ein Teammitglied einen PR mergt, sehe ich das sofort und rebasiere meinen Branch; dadurch ist der Branch immer aktuell auf Basis von main, und ich hinterlasse weder Merge-Hölle noch schreckliche „fix conflicts“-Commits.

  • Als ich die Top 10 der Dateien suchte, die seit ihrer Erstellung gestern am häufigsten geändert wurden, stieß ich auf https://github.com/tj/git-extras/blob/main/Commands.md
    Dort gibt es viele nützliche zusätzliche Git-Befehle.

  • Ich verstehe nicht so recht, warum die meisten Entwickler unbedingt auf der Git CLI bestehen, obwohl moderne UI-Clients wie GitKraken durchaus brauchbar und hilfreich sind: https://www.gitkraken.com/

    • CLI-Wissen führt zum Schreiben von Skripten, und das in Skripten gelernte Git-Wissen fließt wieder in die tägliche Nutzung zurück. Ich möchte nicht nur deshalb handlungsunfähig sein, weil ich per SSH auf einen Raspberry Pi gehe, der als Server dient, und dort die CLI nutzen muss.
      Ich bin nicht grundsätzlich gegen GUIs, aber im Moment ist die CLI effizienter, und ich möchte keine Zeit damit verbringen, eine GUI zu finden, die folgende Bedingungen erfüllt:
      Sie muss gut aussehen, eine native App sein und kein eingebetteter altmodischer Webbrowser, keine Telemetrie haben oder sie standardmäßig deaktivieren, vollständig Open Source sein und erwarten lassen, dass sie in fünf Jahren nicht verschwunden ist.
      Außerdem darf sie die Dinge nicht noch verwirrender machen. In einer früheren Firma musste ich Visual Studio benutzen; dort war ein Button, der eigentlich „als Konflikt gelöst markieren“ bedeutete, unheilvoll mit „Accept merge“ beschriftet.
      Wer bereits erwartet, dass ein bestimmtes Wort eine bestimmte Bedeutung hat, darf nicht verwirrt werden; ebenso ist es schwer, einem „Commit changes“-Button zu vertrauen, der aus Nettigkeit gleich noch auf den Remote pusht.
    • Die CLI ist ebenfalls völlig brauchbar. Ich nutze auch Editor-Plugins, aber wenn ich ohnehin schon in der Kommandozeile bin, erledige ich es dort.
      Wenn ich für einen einzelnen Commit in ein anderes Programm wechseln muss, sinkt meine Motivation, häufig zu committen.
    • Sofern es kein sehr spezielles Problem gibt, halte ich meine Arbeit mit Git minimal. Bei mir sind es praktisch nur push, pull und checkout, daher fühlt sich eine GUI überdimensioniert an.
    • Es sieht aufgeräumt aus, aber grafische Oberflächen werden zu leicht ablenkend. Am Ende scheint es eine Frage persönlicher Vorlieben zu sein, und die CLI ist schnell, hat aber eine steile Lernkurve.
      Auch wenn man Git in der CLI nutzt, sind es meistens keine besonderen Dinge, sondern nur ein paar Befehle; selten genutzte Tipps und Tricks schreibe ich in eine Textdatei.
  • -committerdate kannte ich, aber ich wusste nicht, dass man es als Standardsortierung setzen kann; das ist sehr nützlich. Ein paar Notizen:
    git columns wird ziemlich verwirrend, wenn nicht alles auf den Bildschirm passt und man scrollen muss; Zahlen wären schön.
    git maintenance sieht gut aus, aber weil ich viel rebasiere, macht es mir Sorgen. Ich frage mich, ob man lose Objekte schneller verliert als mit gc. Ich sehe, dass gc deaktiviert ist, aber es ist nicht eindeutig.
    Zu git blame gibt es ein wenig bekanntes, aber nützliches Skript: https://github.com/gnddev/git-blameall. Es ist so unbekannt, dass ich es selbst nach Python 3 portieren musste, und ich bin nicht einmal Python-Entwickler.

    • Bei geplanter Maintenance ist gc deaktiviert. Wenn man maintenance run explizit ausführt, wird es als Task aktiviert.
      Lose Objekte werden nicht schneller eingesammelt als mit gc. Letztlich wird einfach gc ausgeführt.
    • Ich frage mich, ob eine Sortierung in umgekehrter Reihenfolge möglich ist. Die einfache Lösung für das Problem, dass Branches aus dem Bildschirm herausrutschen, scheint zu sein, die neuesten Branches ans Ende zu setzen. Ich mache das mit einem Userskript so.
    • Man verliert sie nicht schneller. Es werden nur häufiger Daten vom Remote geholt und Daten neu gepackt. Wenn GC deaktiviert ist, werden keine Daten gelöscht.
      git-blameall sieht ganz gut aus; das sollte ich mal ausprobieren.
  • Mit ein paar Aliasen, die in mehreren Umgebungen funktionieren, habe ich meinen Git-Flow stark vereinfacht.
    git synced synchronisiert den aktuellen Branch per Rebase mit dem Upstream, falls es einen gibt, sonst mit origin. Es verwendet master oder main, wobei main bevorzugt wird.
    git pub veröffentlicht Änderungen auf dem Remote origin und nutzt Force-Push mit Lease.
    git pr öffnet die passende PR-URL auf GitHub und benötigt keinen GH-Client. Wenn ein Upstream definiert ist, wird der PR dorthin geschickt.
    git hub öffnet die GitHub-Seite des Repositorys.
    https://softwaredoug.com/blog/2022/11/09/idiot-proof-git-aliases.html

    • Ich frage mich, warum dieser seltsame, behaarte Pfeil als Trennzeichen gewählt wurde.
  • Ich habe aufgehört, so zu tun, als wüsste ich, was ich mache, und nutze visuelle Git-Tools. Dinge wie SmartGit oder die in IntelliJ integrierten Tools. Git-„Kommandozeilenhelden“ wirken auf mich eher wie Angeberei.
    Die Befehlsebene für Nutzer kann ärgerlich verwirrend sein. Zum Beispiel können Yours und Theirs je nach Kontext genau das Gegenteil bedeuten.
    Der gesamten Benutzeroberfläche fehlt ein gemeinsamer Stil oder ein gemeinsames Thema; damit Menschen nicht wahnsinnig werden, braucht es eine neue visuelle Ebene.

    • Geht mir genauso. Ich mag es, immer die Unterschiede sehen und auf einen Blick visuell prüfen zu können, was passieren wird. Man muss auch nicht mehrere zusätzliche Befehle ausführen.
      Ich kenne die App und Git insgesamt nur so weit, wie ich es für die Arbeit brauche; wenn ich selten mehr brauche, kann ich es nachschlagen. Über mehrere Jahre hinweg kam das nur ein- oder zweimal vor.
    • Für die tägliche Arbeit nutze ich immer ein visuelles Git-Tool, insbesondere Tortoise Git.
      Auch bei komplizierten Aufgaben, bei denen ich Fehler anderer oder meine eigenen korrigiere, schaue ich mir zuerst mit einem visuellen Tool History, Commits, Reflog und Diffs an, um zu verstehen, was schiefgelaufen ist und was sich retten lässt.
      Wenn es nur einen Commit gibt, zu dem ich zurückkehren muss, mache ich reset --hard; wenn ich etwas aus mehreren Commits zusammenführen muss, nutze ich in der Regel die Kommandozeile.
  • Beides schließt sich nicht gegenseitig aus. Für Dinge wie Diffs oder Konflikte nutze ich ausschließlich visuelle Tools, aber ich habe viel daraus gelernt, mich mit Commit-Objekten, dem Reflog, dem, was Rebase im Hintergrund macht, interaktivem Rebase, Hard/Soft Reset usw. zu beschäftigen.