[linux-l] Re: VCS

Volker Grabsch vog at notjusthosting.com
Mi Apr 26 19:02:32 CEST 2006


On Tue, Apr 25, 2006 at 02:20:51AM +0200, Steffen Dettmer wrote:
> > > > Darcs z.B. kann das. Aber nur, wenn die darauffolgenden Patches unabhängig
> > > > sind. Bei neuen Features ist das aber i.d.R. der Fall.
> > > 
> > > "unabhängig"... Na, /dann/ kann CVS das auch. Da reverted man über ein
> > > Datum, ein Tag (oder alt zwei) oder notfalls über Revisionsnummern (oder
> > > commit-Ids oder wie auch immer das SCM sowas nennt) einfach per
> > > textueller zeilenweisen Patcherei, klar.
> > 
> > Darcs bietet dir nach und nach eine Liste von rückgängig-machbaren
> > Patches. Da wählst du eine oder mehrere Patches aus, und gut ist's.
> > UND: Diese Dinge werden nur aus dem Repository geworfen, nicht aus
> > dem Arbeitsverzeichnis, d.h. die Änderungen sind nach wie vor vorhanden,
> > tauchen nun aber als "loakle Änderungen" auf.
> 
> rückgängig-machbaren Patches?! Entscheidet das Tool, was ich reverten
> darf, und was nicht?! Warum sind nicht alle Patches ückgängig-machbar?

Ich glaube, du verstehst nicht, was ich mit "rückgängig machen" meine.

Erstmal grundsätzlich: Einen inversen Patch anwenden kann man immer, in
der Regel proviziert man dabei Konflikte. Das wird dann insgesamt ein
neuer Patch. Das heißt, vorher sah dein Log vielleicht so aus:

    * Feature A
    * Bugfix B
    * Feature C

Und nachdem du A rückgängig gemacht hast, sieht es so aus:

    * Feature A
    * Bugfix B
    * Feature C
    * Removed Feature A

Das geht immer. Mit jedem SCM.

Was dir jedoch darcs zusätzlich anbietet, falls B und C "unabhängig" von
A sind, ist folgendes: Du darfst den Changeset "Feature A" entfernen.
Als hätte es ihn nie gegeben. Danach sähe dein Log so aus:

    * Bugfix B
    * Feature C

Das darf man natürlich nicht immer machen, vorallem nicht wenn "Feature A"
schon in ein anderes Repository hochgeladen wurde. Ist also mehr ein
kleines praktisches Feature, das man nur lokal einsetzen darf. Es ist
nicht von praktischer Relevanz, ich wollte damit nur die Mächtigkeit
dieses Ansatzes demonstrieren.

> > Anders ausgedrückt: Das Arbeitsverzeichnis ändert sich bei dieser Aktion
> > nicht.
> 
> Das ist ja auch blöd, wie teste ich dann, ob's geklappt hat? Ich möchte
> doch kontrollieren, was dabei rauskommt, bevor ich das Repository
> ändere?

Nein, dafür ist es doch gar nicht gedacht. Aber du kannst damit z.B.
ältere Patches "unrecord"en, (es ändert sich nichts, die Änderungen
bleiben im Arbeitsverzeichnis), korrigierst etwas, und machst wieder
"record". So kannst du alte Patches korrigieren.

Aber wiegesagt, *nur* wenn noch keine neuren davon abhängen, und
du sie noch nirgendwohin hochgeladen hast, sonst geht's schief.

Natürlich ist der Normalfall, wiegesagt, dass du einen neuen Patch
rüberbügelst, der die entsprechenden Sachen korrigiert. Manchmal
ist aber der direkte Weg auch ganz praktisch.

> > > > So kann man dann die verschiedenen Branches einfach als verschiedene
> > > > Zusammenstellungen von Patches (d.h. changesets) betrachten.
> > > 
> > > Ja, OK, das ist bei CVS ja (mit etlichen Buch füllenden Einschränkungen)
> > > auch in etwa so.
> > 
> > Nee, nicht wirklich. ;-)
> 
> Doch, wirklich! :)
> 
> Technisch ist das ja auch so: für CVS ist das nur ne Folge von Patches,
> also ja auch eine Zusammenstellung von Patches. Seh da den essentiellen
> Unterschied immer noch nicht. Den einzigen Unterschied den ich sehe,
> dass ich bei CVS zwei Punkten/Stände oder einen Branch benennen muss,
> bei darcs aber "das zwischen" zwei Punkten benennen kann.

Genau, man adressiert Changesets anstelle von Versionen. (obwohl
letzteres via Tags natürlich auch geht, für Releases, etc.)

Aber außerdem ist die Reihenfolge der Changesets variabel (in gewissen
Grezen, wie ich versuchte, zu erklären). Zwei Repositories werden
dadurch verglichen, dass man ihre Patch-Listen (Changeset-Listen)
vergleicht. Man kann sich so (in gewissen Grenzen, wiegesagt) auch
nur einzelne Patches von jemand anderem holen oder ihm senden, oder
eben alles abgleichen, wie man will.

Innerhalb eines einzigen Repositories ist der Unterschied, den du
siehst, wirklich nur die Variabilität der Reihenfolge (in gewissen
Grezen).

Aber bei mehreren Repositories bekommt man die Vorteile ganz deutlich
zu spüren, vorallem wenn man eben nicht nur stur "alles auf den gleichen
Stand bringen" will. Jedes Repository beherbergt Bausteine (Changesets),
gruppiert in Häufchen (Branches), die du von Repository zu Repository
schieben kannst.

Vielleicht ein kleines Beispiel, das du mit zentralen Versionsnummern
nur über Umwege hinbekommst:

Jemand arbeitet an einem Feature. Dort macht er unter anderem einen
Bugfix. Dieser Bugfix stellt sich als nicht-Feature-stepzifisch heraus.
Du brauchst Teile des Features und den Bugfix, aber wirklich nur so
wenig wie möglich, da das Feature u.U. noch nicht stabil ist.

Du holst es dir von ihm, direkt mit einem Befehl. Fertig. Naja,
eventuell noch nen Konflikt lösen, aber wenn du alle "Vorgänger-Patches"
(unbedingt nötigen Voraussetzungen) automatisch mit holst, geht's
eigentlich.

Du kannst jetzt weiterarbeiten. Du hast schon ein paar Patches von
ihm, andere nicht. Irgendwann ist sein Feature fertig und stabil.
Ihr alle holt euch einfach das Feature von ihm. Wenn du das
entsprechende Kommando ausführst, bekommst du alle restlichen
Patches (bis auf die, die du schon von ihm hast). Alle anderen bekommen
*sämtliche* Feature-Patches.

Der Witz an dieser Sache ist, dass es sehr komplizierte Branch/Merge-
Operationen geben müsste, wenn man immer von Version zu Version
vergleichen würde. Arbeitet man von vornherein nur mit Changesets,
ist das ganze fast nur noch ein Listenabgleich. Jeder kriegt die Patches,
die ihm noch fehlen.

Die Abhängigkeiten zwischen den Patches, und Konfliktlösungspatches
(falls zwei unabhängige Patches kollidieren), werden automatisch richtig
verwaltet. Die Patches werden intern nicht mehr linear, sondern in einer
baumartigen Struktur verwaltet. Wären alle Patches linear aufgefädelt,
hättest du viel weniger Flexibilität, vorallem bräuchtet ihr zentrale
Versionsnummer. Bei der dezentralen Arbeitsweise braucht man kein
Zentrum (jedenfalls nicht unbedingt), kann Patchlisten auseinandergehen
lassen (Branches), und wieder zusammenführen (Merges), ganz wie man
will, von Repository zu Repository.

Ein dezentrales (Changeset-basiertes) SCM stellt sicher, dass dabei
alles mit rechten Dingen zugeht, es weiß immer genau, was es wie zu
mergen hat, und die Konflikte, die auftreten, wären auch bei einem
zentralen SCM aufgetreten. Das ist eine viel höhere technische
Anforderung an das SCM, aber ist genauso technisch sauber lösbar,
und erhöht den komfort ungemein.

Wie Darcs, Mercurial, GIT, etc. mit Changesets umgehen, ist überhaupt
nicht mehr vergleichbar mit CVS oder Subversion. Sicher geht es auch
dort alles "irgendwie", aber z.T. nur mit großem Aufwandt und einer
Disziplin, die man wegautomatisieren möchte ... und kann! Das, was
dabei rauskomt, nennt man Changeset-basiertes SCM. :-)


Ich hoffe, das war nun halbwegs verständlich erklärt.

Viele Grüße,

    Volker

-- 
Volker Grabsch
---<<(())>>---
Administrator
NotJustHosting GbR



Mehr Informationen über die Mailingliste linux-l