it-swarm.com.de

Warum enthalten Git-Commits nicht den Namen des Zweigs, in dem sie erstellt wurden?

Wenn ich mit Git in einem Team arbeite, das Feature-Zweige verwendet, fällt es mir oft schwer, die Zweigstruktur in der Geschichte zu verstehen.

Beispiel :

Angenommen, es gab einen Feature-Zweig Feature/Make-Coffee, und die Fehlerbehebung wurde am Master parallel zum Feature-Zweig fortgesetzt.

Die Geschichte könnte so aussehen:

*     merge feature/make-coffee
|\
| *   small bugfix
| |
* |    fix bug #1234
| |
| *    add milk and sugar
| |
* |    improve comments
| |
* |    fix bug #9434
| |
| *    make coffe (without milk or sugar)
| |
* |    improve comments
|/
*

Problem

Auf den ersten Blick fällt es mir schwer zu sagen, auf welcher Seite sich der Feature-Zweig befindet. Normalerweise muss ich auf beiden Seiten mehrere Kommentare durchsuchen, um eine Vorstellung davon zu bekommen, welche welche ist. Dies wird komplizierter, wenn mehrere Feature-Zweige parallel sind (insbesondere wenn es sich um eng verwandte Features handelt) oder wenn zwischen Feature-Branch und Master in beide Richtungen zusammengeführt wurde.

Im Gegensatz dazu ist dies in Subversion erheblich einfacher, da der Filialname Teil des Verlaufs ist. Daher kann ich sofort feststellen, dass ursprünglich ein Commit für "Feature/Make-Coffee" vorgenommen wurde.

Git könnte dies vereinfachen, indem der Name des aktuellen Zweigs beim Erstellen eines Commits (zusammen mit Autor, Datum usw.) in die Commit-Metadaten aufgenommen wird. Git macht dies jedoch nicht.

Gibt es einen fundamentalen Grund, warum dies nicht getan wird? Oder wollte nur niemand die Funktion? Wenn es das letztere ist, gibt es andere Möglichkeiten, den Zweck historischer Zweige zu verstehen, ohne den Namen zu sehen?

20
sleske

Wahrscheinlich, weil Filialnamen nur innerhalb eines Repositorys von Bedeutung sind. Wenn ich im Team make-coffee Bin und alle meine Änderungen über einen Gatekeeper übergebe, wird mein Zweig master möglicherweise in den Zweig make-coffee-gui Des Gatekeepers gezogen, den er mit seinem zusammenführt Zweig make-coffee-backend, Bevor auf einen Zweig make-coffee Zurückgegriffen wird, der in den zentralen Zweig master zusammengeführt wird.

Selbst innerhalb eines Repositorys können und müssen sich Zweigstellennamen ändern, wenn sich Ihr Workflow weiterentwickelt. master kann sich später ändern und beispielsweise development heißen.

Wie CodeGnome anspielte, hat git eine starke Designphilosophie, etwas nicht in die Daten zu backen, wenn es nicht benötigt wird. Von Benutzern wird erwartet, dass sie Optionen in git log Und git diff Verwenden, um die Daten nachträglich nach ihren Wünschen auszugeben. Ich empfehle, einige auszuprobieren, bis Sie ein Format gefunden haben, das für Sie besser funktioniert. git log --first-parent Zeigt beispielsweise nicht die Commits eines Zweigs an, in dem zusammengeführt wird.

14
Karl Bielefeldt

Verfolgen Sie den Zweigverlauf mit --no-ff

In Git hat ein Commit Vorfahren, aber ein "Zweig" ist wirklich nur der aktuelle Leiter einer Entwicklungslinie. Mit anderen Worten, ein Commit ist eine Momentaufnahme des Arbeitsbaums zu einem bestimmten Zeitpunkt und kann zu einer beliebigen Anzahl von Zweigen gleichzeitig gehören. Dies ist Teil dessen, was die Git-Verzweigung im Vergleich zu anderen DVCS so leicht macht.

Git-Commits enthalten keine Zweiginformationen, da sie für den Git-Verlauf nicht erforderlich sind. Zusammenführungen, die nicht schnell vorgespult werden, können jedoch sicherlich zusätzliche Informationen darüber enthalten, welcher Zweig zusammengeführt wurde. Sie können sicherstellen, dass Ihr Verlauf diese Informationen enthält, indem Sie immer das --no-ff Flag zu Ihren Zusammenführungen. git-merge (1) sagt:

   --no-ff
       Create a merge commit even when the merge resolves as a
       fast-forward. This is the default behaviour when merging an
       annotated (and possibly signed) tag.

Dadurch wird im Allgemeinen eine Zusammenführungsnachricht erstellt, die Merge branch 'foo', sodass Sie normalerweise Informationen zu "Ahnenzweigen" mit einer Zeile ähnlich der folgenden finden können:

$ git log --regexp-ignore-case --grep 'merge branch'
5
CodeGnome

Warum enthalten Git-Commits nicht den Namen des Zweigs, in dem sie erstellt wurden?

Nur eine Designentscheidung. Wenn Sie diese Informationen benötigen, können Sie einen Prepare-Commit-Msg- oder Commit-Msg-Hook hinzufügen, um dies in einem einzelnen Repository zu erzwingen.

Nach der BitKeeper-Katastrophe entwickelte Linus Torvalds ein Git, das dem Entwicklungsprozess des Linux-Kernels entspricht. Dort wird ein Patch, bis er akzeptiert wird, mehrmals überarbeitet, bearbeitet, poliert (alle per Mail), abgemeldet (= ein Commit bearbeiten), von Kirschen gepflückt, zu Zweigen des Leutnants gewandert, vielleicht oft neu basiert, mehr bearbeitet, Kirsche -Picks und so weiter, bis sie schließlich von Linus stromaufwärts zusammengeführt werden.

In einem solchen Workflow gibt es möglicherweise keinen bestimmten Ursprung eines Commits, und häufig wird ein Commit nur in einem temporären Debugging-Zweig in einem unwichtigen privaten zufälligen Repository mit lustigen Zweignamen erstellt, da git verteilt wird.

Vielleicht ist diese Designentscheidung nur zufällig gefallen, aber sie passt genau zum Entwicklungsprozess des Linux-Kernels.

3
villekulla

Die einfachste Antwort ist, dass die Namen der Zweige kurzlebig sind. Was wäre, wenn Sie beispielsweise einen Zweig umbenennen würden (git branch -m <oldname> <newname>)? Was würde mit all den Commits gegen diesen Zweig passieren? Oder was ist, wenn zwei Personen Zweige mit demselben Namen in verschiedenen lokalen Repositories haben?

Das einzige, was in git eine Bedeutung hat, ist die Prüfsumme des Commits selbst. Dies ist die Grundeinheit der Verfolgung.

Die Informationen sind da, Sie fragen einfach nicht danach und es ist nicht genau da.

Git speichert die Prüfsumme des Kopfes jedes Zweigs in .git/refs/heads. Zum Beispiel:

 ... /. Git/refs/Heads $ ls Test 
 - rw-rw-r-- 1 michealt michealt 41 Sep 30 11:50 Test 
 .../.git/refs/Heads $ cat test 
 87111111111111111111111111111111111144 

(Ja, ich mache meine Git-Prüfsummen kaputt, es ist nichts Besonderes, aber es sind private Repositories, die ich mir gerade ansehe und in denen nichts versehentlich durchgesickert sein muss).

Wenn Sie sich dies ansehen und jedes Commit zurückverfolgen, das dies als Elternteil oder das Elternteil oder das Elternteil hat, können Sie herausfinden, in welchen Zweigen sich ein bestimmtes Commit befindet. Es ist nur ein großes Diagramm zum Rendern.

Das Speichern, wo sich speziell der Name eines Zweigs (der sich wie oben erwähnt ändern kann) eines Commits im Commit selbst befindet, ist ein zusätzlicher Aufwand für das Commit, der ihm nicht hilft. Speichern Sie die Eltern des Commits und dessen Gut.

Sie können die Zweige anzeigen, indem Sie den Befehl git log mit dem entsprechenden Flag ausführen.

 git log --branches --source --pretty = oneline --graph 
 git log --all --source --pretty = oneline --graph 

Es gibt viele verschiedene Möglichkeiten, um auszuwählen, was Sie dafür wollen - sehen Sie sich die Dokumentation git log an - die -all Abschnitt und die wenigen folgenden Optionen.

 * 871111111111111111111111111111111111d4 test Füge den Zweig 'test1' in den Test 
 |\
 | Zusammen * 421111111111111111111111111111111111118 test1 update: füge Sachen hinzu 
 * | dd111111111111111111111111111111111159 test Füge den Zweig 'test3' in test 
 |\\ 
 ein.

Dieser 'Test', 'Test1' und 'Test2' sind die Zweige, denen diese verpflichtet waren.

Beachten Sie, dass die Dokumentation zum Git-Protokoll riesig ist und es durchaus möglich ist, fast alles herauszuholen, was Sie wollen.

3
user40980

Denn in Git werden Commits wie "Kaffee kochen" als Teil von beide Zweigen betrachtet, wenn der Feature-Zweig zusammengeführt wird. Es gibt sogar einen Befehl, um dies zu überprüfen:

% git branch --contains @
  feature/make-coffee
  master

Außerdem sind Filialen billig, lokal und ätherisch. Sie können einfach hinzugefügt, entfernt, umbenannt, verschoben und vom Server gelöscht werden.

Git folgt dem Prinzip, dass alles gemacht werden kann, weshalb Sie einen Zweig einfach von einem Remote-Server entfernen und den Verlauf einfach neu schreiben können.

Nehmen wir an, ich war in der 'Master'-Filiale und habe zwei Commits gemacht:' Kaffee kochen 'und' Milch und Zucker hinzufügen '. Dann entscheide ich mich, dafür eine neue Filiale zu verwenden, also setze ich' Master 'zurück auf' Origin ' /Meister'. Kein Problem, die ganze Geschichte ist immer noch sauber: 'Kaffee kochen' und 'Milch und Zucker hinzufügen' sind nicht Teil des Meisters, sondern nur Feature/Kaffee machen.

Mercurial ist das Gegenteil; es will nichts ändern. Zweige sind permanent, das Umschreiben des Verlaufs ist verpönt. Sie können einen Zweig nicht einfach vom Server löschen.

Kurz gesagt: Git ermöglicht es Ihnen, alles zu tun, Mercurial möchte die Dinge einfach machen (und macht es wirklich schwierig, Sie tun zu lassen, was Sie wollen).

2
FelipeC