Git Notes: Das coolste und meistgehasste Feature von Git (2022)
(tylercipriani.com)- Git notes ist ein Feature, mit dem sich Metadaten in einem separaten Namespace an Git-Objekte anhängen lassen, ohne diese zu verändern; wegen geringer Benutzerfreundlichkeit und begrenzter Verbreitung wird es jedoch kaum genutzt
- Damit lassen sich neue Informationen ergänzen, ohne alte Commit-Nachrichten ändern zu müssen – gut geeignet für Einträge automatisierter Systeme wie Review-, Build- und Ticket-Informationen
- Das Git-Projekt und Gerrit nutzen notes tatsächlich, um Diskussionen auf Mailinglisten, Testergebnisse und Reviewer-Informationen pro Commit in
git logsichtbar zu machen - Googles git-appraise implementiert verteiltes Code-Review auf Basis von git notes und ermöglicht Review-Anfragen, Kommentare, Reviews und Merges lokal
- GitHub stellte 2014 die Anzeige von Commit-Notes ein; Blob- und Tree-Notes setzen Vertrautheit mit internen Git-Befehlen voraus und sind trotz ihres Potenzials zur Verteilung der Projekthistorie schwer nutzbar
Metadaten, die Git-Objekte nicht verändern
- Git notes ist ein Feature, mit dem Git separate Metadaten zu von Git verfolgten Objekten speichern kann
- Ziele sind nicht nur Commits, sondern auch Blobs und Trees
- Informationen werden in einem separaten Namespace angehängt, ohne das Objekt selbst zu verändern
- Commit-Nachrichten, die bereits Teil der Historie sind, lassen sich normalerweise nur schwer sicher ändern; mit notes kann man auch alten Commits neue Informationen hinzufügen
- Mit
git notes add -mlässt sich wie folgt eine Notiz anhängengit notes add -m 'Acked-by: <tyler@tylercipriani.com>' - Danach erscheint sie in
git logunter dem jeweiligen Commit alsNotes:-Block
- Mit
- Scott Chacon sah notes 2010 auf GitHub.blog weniger als Mittel für Gespräche mit anderen Entwicklern, sondern eher als Feature zum Anhängen automatisierter Aufzeichnungen wie Ticket- und Build-Systeme
Praktische Nutzung und Stolperstellen
- Das Git-Projekt verwendet notes, um einzelne Commits mit Diskussionen auf der Mailingliste zu verknüpfen
- Die
Notes (amlog)eines Beispiel-Commits enthalten eineMessage-Id; dieser Wert führt zum Patch-Diskussionsthread
- Die
- notes werden auch für Zeiterfassung pro Commit oder Branch, das Hinzufügen von Review- und Testinformationen zu
git logsowie für vollständig verteiltes Code-Review genutzt - Gerrits reviewnotes-Plugin macht Code-Review-Metadaten innerhalb von Git offline sichtbar
- Die Befehle zum Abrufen und Anzeigen von notes lauten:
git fetch origin refs/notes/review:refs/notes/review git log --show-notes=review - Zu den angezeigten Informationen gehören
Verified+1,Verified+2,Code-Review+2,Submitted-by,Submitted-at,Reviewed-on,Project,Branchund weitere
- Die Befehle zum Abrufen und Anzeigen von notes lauten:
- Googles git-appraise ist ein „fully distributed code review“-System, das auf git notes aufbaut
- Es funktioniert unabhängig von Code-Forges wie GitHub oder GitLab
- Review-Anfragen für Änderungen, Kommentare zu Änderungen, Reviews und Merges können auf dem lokalen Rechner durchgeführt werden
- Eine Weboberfläche ist ebenfalls enthalten
- Die größte Schwäche ist die Benutzerfreundlichkeit
- GitHub stellte 2014 die Anzeige von Commit-Notes ein
- Für Commit-Notes lassen sich automatisches Fetching und die Anzeige in
git logpergitconfig-Einstellungen einigermaßen einfach einrichtengit config --add \ remote.origin.fetch \ '+refs/notes/*:refs/notes/*' git config \ notes.displayRef \ 'refs/notes/*' - Wer notes zu Blobs oder Trees speichern will, muss mit Git-Plumbing vertraut sein
- Git verteilt die Code-Historie, doch ein großer Teil des Werts eines Git-Repositories ist in Forges wie GitHub eingeschlossen
- git notes könnten ein Weg sein, nicht nur Code, sondern die gesamte Projekthistorie zu verteilen
1 Kommentare
Meinungen auf Hacker News
Eine weitere wenig bekannte Funktion sind git trailers: https://alchemists.io/articles/git_trailers
Das sind strukturierte Schlüssel-Wert-Daten, die man beim Erstellen eines Commits einfügen kann; einige Systeme nutzen sie zum Anhängen von Metadaten. Gerrit verwendet sie zum Beispiel, um eine Change-Id anzuhängen.
Damit kann man Text an verschiedene Datenbankobjekte in PostgreSQL hängen. Es wäre schön, wenn PostgreSQL ebenfalls eine editierbare, strukturierte Schlüssel-Wert-Form von Metadaten für Datenbankobjekte hätte.
[skip ci]verwendet, vermutlich damit Subsysteme, die Commit-Nachrichten konsumieren, sie leichter entfernen können: https://docs.github.com/en/actions/managing-workflow-runs-an...Ich weiß nicht, warum erzwungen wird, dass es der letzte Trailer sein muss; vielleicht liegt es an einer Regex.
Das war nützlich, wenn ich mit einem Open-Source-Upstream gearbeitet und meinen Branch mit
git rebase -iperfekt aufräumen wollte. Heute scheint es mir besser, diese Information in git trailers zu packen. Was Change-Id angeht: Es wäre gut, wenn Git selbst solche Identifier hätte, damit Tools sie verstehen können. Commits über die Commit-Nachricht zu identifizieren ist fragil, besonders in MRs, wenn man die Nachricht ändern kann. Die Commit-ID identifiziert einen Commit eindeutig, ist aber kein nützlicher Identifier, wenn dieselbe Änderung auf einen anderen Commit verschoben werden kann. Allerdings sind trailers Teil des tatsächlichen Commits und notes nicht, daher wären sie für meinen Anwendungsfall kein guter Ersatz.Ich frage mich, ob es funktional dasselbe ist, sie manuell in die Commit-Nachricht zu schreiben oder das Flag
--trailerzu verwenden.Ich habe versucht, lokal eine Instanz hochzufahren und sie mit einem auf GitHub gehosteten Repository zu integrieren, und war am Ende nur frustriert. Ich frage mich, ob es eine Alternative gibt, die Änderungsverfolgung über Commits hinweg und Ähnliches besser handhabt als GitHub, zugleich aktiver entwickelt wird und GitHub-freundlich integriert ist. GitHubs Code-Review-Tools hasse ich wirklich.
Forgejo unterstützt es ebenfalls seit Version 10, die im Januar dieses Jahres erschienen ist: https://forgejo.org/2025-01-release-v10-0/#new-features
https://codeberg.org/forgejo/forgejo/pulls/4753
Es sieht wirklich cool aus, aber ich frage mich, wie notes mit Funktionen zum Umschreiben der Historie wie amend oder rebase zusammenspielen, die Commits faktisch durch geänderte Kopien ersetzen.
Es klingt so, als würden notes an bestimmte Commit-, Tree- oder Blob-IDs gehängt. Ich frage mich, ob
git rebaseund Ähnliches schlau genug sind, notes auf die neuen Commits zu kopieren, oder ob sie einfach verschwinden. Unklar ist auch, was passiert, wenn man in einem interaktiven rebase mehrere Commits zu einem squasht. Notes an Blobs und Trees zu hängen scheint dasselbe Problem zu haben. Es fühlt sich an, als würde man Metadaten an Dateien oder Verzeichnisse im Repository hängen, tatsächlich hängt man sie aber an bestimmte Inhalte. Wenn ich zum Beispiel eine note an einen Blob hänge, der den String"Hello world!"enthält, verbindet Git diese note dann mit allen Dateien, die diesen Inhalt haben? Und verliere ich die notes, wenn ich eine Datei zu"Hello, world!"ändere?notes.rewriteingit-config(1).Ich benutze Git wahrscheinlich seit etwa zehn Jahren und wusste nicht, dass es git notes gibt. Cool.
Die Forderung „alle Forges sollen Code-Review-Metadaten innerhalb von Git offline verfügbar machen“ dürfte bei kommerziellen Forges wie GitHub kaum verfangen. Wie schon gesagt wurde, liegt ein großer Teil des Werts eines Git-Repositorys eben in einer Forge wie GitHub eingeschlossen. Gewinnorientierte Unternehmen sind normalerweise nicht besonders erpicht darauf, ihren Mehrwert zu verallgemeinern. Ich will GitHub damit nicht kritisieren; sie bieten einen hervorragenden Dienst und einen sehr großzügigen Free Tier, und ich finde es gut, dass man alle Daten per API extrahieren kann, wenn man umziehen möchte. Das ist einfach die Natur kommerziellen Betriebs.
Git notes sind nur dann wirklich cool, wenn man häufig Text zu einem Commit hinzufügen will, nachdem er bereits erstellt wurde und andere ihn gesehen haben.
Die Beispiele mit Acked-By und Links zu Mailinglisten-Diskussionen scheinen keine guten Beispiele zu sein. Beides weiß man wahrscheinlich schon, wenn man den Commit erstellt. Git-Commit-Messages haben praktisch kaum eine Längenbegrenzung, also könnte man die commitbezogene Diskussion aus einem Forge auch direkt in die Commit-Message kopieren. Ein besseres Beispiel wäre meiner Meinung nach, wenn man einem Commit, der später revertet wurde, eine Git note hinzufügt.
Vielleicht bin ich da seltsam, aber ich habe zu viele Kollegen gesehen, die Kommentare oder annotate nicht wirklich ansehen, um herauszufinden, warum Code ursprünglich geschrieben wurde. Sie ändern einfach drauflos und hoffen, dass das Problem nicht auf sie zurückfällt. Aber wenn man schon einmal mit verärgerten Kunden zu tun hatte, die nur auf den Bugfix gewartet haben, und kurz darauf erlebt, dass derselbe Bug wieder hereinkommt, wird man bei Bugfixes vorsichtiger. Um mehrere Bugs auf einmal zu beheben, ist oft Refactoring nötig, und Refactoring eröffnet manchmal Chancen für neue Features oder Performance-Verbesserungen.
Wenn es darum geht, einen später reverteten Commit zu markieren, ist die Commit-Message besser. Wenn man für eine Datei blame ausführt, sieht man die jüngste Änderung an dieser Datei, und wenn ein Commit die Änderungen eines anderen Commits revertet hat, erscheint der neuere Revert-Commit im blame.
Das ist kein Wissensdefizit, sondern ein UI-Problem. Wenn die GitHub-UI notes anzeigen würde, würde die Nutzung sofort deutlich zunehmen.
Es gibt viele „coolste, aber ungeliebte Funktionen von Git“. Zum Beispiel bisect, pickaxe, reflog, range-diff, archive, annotated tags usw.
Es ist schade, dass viele Leute Git nur als eine Art schickes Google Drive betrachten und solche Funktionen deshalb oft vergessen werden.
Trotzdem finde ich das in Ordnung. Die Unix-Philosophie lautet, sich auf eine Sache zu konzentrieren und sie gut zu machen.
Im LibreOffice-Projekt wurden Git notes verwendet, um jeden Commit des Apache-OpenOffice-Repositorys nachzuverfolgen.
Während dieses Repository als Branch im LibreOffice-Git-Repository gespiegelt wurde, wurde für jeden Commit festgehalten, ob es sich um eine irrelevante Änderung handelte, etwa eine Änderung am Build-System, die LibreOffice schon vor langer Zeit durch etwas Besseres ersetzt hatte, ob sie eine Änderung duplizierte, die bereits in LibreOffice vorhanden war, oder ob sie in seltenen Fällen in LibreOffice übernommen wurde und mit welchem Commit sie cherry-picked wurde. Man kann das immer noch direkt unter https://cgit.freedesktop.org/libreoffice/core/log/?h=aoo/tru... sehen, und dieses Git-Frontend zeigt notes weiterhin an. Vor einigen Jahren wurde diese Änderungsverfolgung eingestellt, vermutlich weil das Änderungstempo von Apache OpenOffice sehr langsam geworden ist und der Nutzen, die wenigen Änderungen per cherry-pick zu übernehmen, gering geworden ist.
Das ist nicht die coolste, aber ungeliebte Funktion, sondern eher eine Gimmick-Funktion, die in sehr speziellen Fällen cool gewesen sein könnte, etwa in einem Team, in dem das ganze Unternehmen nur von Entwicklern betrieben wird.
Was nötig ist, gehört in die Commit-Message, und Tickets in einem separaten System zu referenzieren ist kein Bug, sondern ein Feature. JIRA oder andere Systeme werden nämlich für die Kommunikation mit Nichtentwicklern genutzt. Ein Business Analyst hat zum Beispiel keinerlei Zugriff auf Code oder Repositorys, und Support-Mitarbeiter haben ebenfalls keinen Zugriff auf Repositorys und Code. Man könnte zwar ein Frontend bauen, über das Nichtentwickler notes ansehen und bearbeiten können, aber das hätte trotzdem kaum Sinn. BAs, Supportteams usw. interessieren sich nicht für einzelne Commits, und ein Feature kann zwar genau einem Commit entsprechen, tut es aber meistens nicht. Wenn mehrere Repositorys genutzt werden und ein Feature sich über mehrere Services erstreckt, werden git notes ziemlich nutzlos, und am Ende braucht man doch eine Referenz auf ein externes System.
Aber genau das ist der Mainstream. Gelegentlich stellt mir ein Analyst aus einem anderen Team, das dasselbe Monorepo nutzt, eine Frage, die sich mit einer einzigen Codezeile direkt beantworten ließe. Dieser Analyst ist eher technisch und kann auch SQL, und unser Code ist sehr idiomatisch und auf hohem Niveau geschrieben. Trotzdem kann sich Kultur wegen ihrer inhärenten Ineffizienzen nicht selbst ändern, bis sie daran zugrunde geht.
[^1] https://news.ycombinator.com/item?id=44348438
Ein neun Jahre alter Feature-Request für notes-Support in GitLab wurde kürzlich geschlossen: https://gitlab.com/gitlab-org/gitlab/-/issues/15029
Leider muss man zum Lesen eingeloggt sein, aber ein beliebiger gitlab.com-Account sollte reichen.