Dienstag, 25. Oktober 2011

Einmal Commit und wieder zurück

Gelegentlich soll es ja passieren, daß man Sachen in sein Git Repository eincheckt, die man nicht einchecken will. Zum Beispiel hat eine Datei mal falsche Rechte, was nicht sofort auffällt, aber unschön ist. Was tun, wenn schon committed wurde? Oder wenn gar die Commit-Message falsch war? Richtig: Man guckt erstmal, was zum Thema bei stackoverflow steht. Und das ist:

Der einfachste Weg: Egal, ein Commit hinterher, der die Situation bereinigt. Vorteil: Unkompliziert. Nachteil: Es sieht nicht gerade hübsch aus. (Ok, das steht nicht bei stackoverflow, das ist also mein Beitrag zum Weltwissen.)

Zweite Variante:
git commit --amend
Vorteil: Git läßt einen die Commit-Message nochmal eingeben. Nachteil: Die falsche Datei kann man so nicht korrigieren.

Dritte Variante:
git reset --soft HEAD^
gefolgt von der Korrektur und einem abschließenden
git commit -c ORIG_HEAD
Vorteil: Es können wirklich alle Änderungen ausgeführt werden. Mit -c ORIG_HEAD werden Author-Informationen und der Timestamp vom ursprünglichen Commit übernommen.

Sonntag, 23. Oktober 2011

Wie man nicht bei Auktionen steigern sollte

Aus aktuellem Anlass zwei Dinge, die man nicht tun sollten, wenn man ein wertvolles Schiller-Manuskript per Auktion für sein Museum ersteigern will:

  1. Interesse im Radio ankündigen. Es ist nicht weise, der Welt zu verkünden, daß das Objekt der Begierte eine absolute Sensation ist -- das ist die Aufgabe des Verkäufers.
  2. Finanzrahmen ankündigen. Die stolze Aussage, man habe zweihundertausend Euro für die Aktion zusammengescharrt, sagen jedem Konkurrenzbieter, wieviel Geld er braucht.
An dieser Stelle steht das Scheitern der geplanten Aquise eigentlich schon fest. Folglich ist es unsinnig, sich anschließend zu beschweren, das Bieter aus der Privatwirtschaft mehr Geld für den Ankauf aufbringen konnten.

Bleibt die Frage: Was passiert jetzt mit den zweihunderttausend Euro?

Freitag, 21. Oktober 2011

Über Versionsnummern

Dritter Anlauf: Über Versionsnummern. Wie jedem schnell klar wird, der in einem größeren Softwareprojekt mit Versionsnummern zu tun hatte, ist das Thema kompliziert. In erster Linie, weil man schnell übersehen kann, daß ein einzelnes Stück Software viele Versionsnummern hat.

Da wäre zunächst einmal die Produktversion. Das ist die Bezeichnung, die draußen draufsteht. Wenn Microsoft ein Windows 7 verkauft, heißt das nicht, daß es sieben Versionen von Windows gibt. Vielmehr heißt es, Microsoft eine "Aggregation" aus Softwarekomponenten unter dem Namen "7" verkauft, die sich funktional von allen anderen Aggregationen unterscheidet. Entscheidend ist hier, daß 7 "anders" ist als beispielsweise Vista oder XP.

Eine Produktversion kann man eng oder lose definieren. Im Idealfall beschreibt eine Produktversion genau eine Kombination aus Komponentenversionen, aber das kommt letztlich darauf an, was Marketing und Rechtsabteilung draus macht. Wir haben uns mittlerweile an verwaschene Produktversionen gewöhnt, ja wir erwarten mittlerweile, daß eine Software regelmäßig kostenlos aktualisiert wird, womit Aussagen wie "Das ist ein nacktes Windows 7." an zwei unterschiedlichen Tagen zwei unterschiedliche Softwarestände beschreiben.

Technische Versionen sind da spezifischer: Sie beschreiben einen exakten Sachverhalt. Die Version 2.2.21 des Apache Webservers beispielsweise beschreibt einen exakten Stand von Quelltextversionen. Mit der Versionsnummer als Schlüssel läßt sich daraus jedes einzelne Zeichen in jeder einzelnen Zeile jeder einzelnen Datei der Software ableiten. ("Holistisch" klingt hier zwar gut, stimmt aber leider nicht. Trotzdem habe ich das Wort jetzt in meinem Artikel.) Je nachdem, wie sorgfältig die Entwickler bei der Festlegung der externen Abhängigkeiten waren, läßt sich auch die technische Version aller verwendeten Softwarepakete ableiten, obwohl die Schärfe der Definition aus praktischen Gründen an den Rändern immer weiter abnimmt.

Aber so vernünftig das auch klingt: Diese Versionsnummern werden willkürlich vergeben. Die Regeln zur exakten Bildung der Versionsnummer mögen strenger sein, aber im Grunde ist die Versionsnummer 2.2.21 nichts als ein einzelnes Symbol, ein Name, die einem spezifischen Quelltextstand bewußt zugeordnet wurde. Am besten paßt hier eigentlich die Bezeichnung "Release".

Anders die Buildnummern und die Versionsnummern einzelner Dateien im Source Code Management. Die Versionsnummern einzelner Dateien folgen keinem bewußten Willen, vielmehr klettern die Versionsnummern einiger Dateien schneller als die anderer. Teile des Codes bleiben jahrelang unberührt, andere werden im Minutentakt verändert. Die Versionen einer einzelnen Datei zu nummerieren hat keinen Wert und verleitet zu falschen Annahmen (weshalb sich verteilte SCMs das Leben leichter machen und es gleich ganz unterlassen, Versionen zu nummerieren). Buildnummern hingegen steigen kontinuierlich an, daher läßt sich aus zwei vorhandenen Nummern eine Reihenfolge der Builds ableiten. Nach wie vor ist es natürlich gefährlich, eine andere Bedeutung in diese Nummern zu interpretieren als die, daß Build 2 nach Build 1 ausgeführt wurde, insbesondere sind alle Annahmen zur Korrelation zwischen Nummer und Qualität unsinnig.

Wenn man über Versionsnummern spricht, muß man also wissen, was man damit meint. Benutzer von Software meinen, wenn sie von Versionen sprechen, oftmals die Produktversion, seltener eine technische Version ("Release"), normalerweise nicht die Buildnummer und praktisch nie die Dateiversion.
Es sollte klar sein, daß Produktversionen und technische Versionen sowie technische Versionen und Build- oder SCM-Versionen nur lose zusammenhängen und nicht synonym verwendet werden können. Wenn jetzt continuous builds auf traditionelle Testcenter treffen, wird die Sache spannend genug für einen eigenen Artikel.

Freitag, 7. Oktober 2011

Raubkopien

Und wieder einmal zeigt sich, daß die größte Gefahr für ein IT-System nicht von außen, sondern von innen kommt: heise.de: Größter Fall von Softwarepiraterie weltweit.

Spaß beiseite: In großen Unternehmen ist das Problem "Unterlizensierung" wahrscheinlich viel schwerer in den Griff zu bekommen. Undurchsichtige Lizenzvarianten, Interoperabilitätsprobleme, Mondpreise und die weitverbreiteten lokalen Adminrechte machen es selbst engagierten IT-Abteilungen schwer, ihr Netz "sauber" zu halten. Aber von den vier Problemen liegen eigentlich 3,5 im Verantwortungsbereich der Softwarehersteller und sind entweder gewollt oder lassen sich nicht mehr einfach abschaffen.

Die Situation ist offenbar unbefriedigend: Der Einsatz von Raubkopien ist ein Risiko (bezeichnenderweise sind die gefundenen Produkte von Adobe und Autodesk, Quasi-Monopolisten in ihren Segmenten und nicht gerade Preisbrecher). Ich vermute ja, daß früher oder später SaaS zu bezahlbaren Preisen sich den Markt mit massenhafter Niedrigpreissoftware teilt, Hochpreissoftware wird's nur noch in Segmenten geben, die für Raubkopierer zu klein sind.

P.S.: Preis sagt nichts über Qualität, und Qualität nichts über Akzeptanz.

Mittwoch, 28. September 2011

Lieferumfang

Wenn es darum geht, eine entwickelte Software auszuliefern, gibt es zwei Extreme: Eine Lieferung der kompletten (virtuellen) Appliance, am besten versiegelt, und eine Lieferung von nackten Komponenten mit Handbuch. Die Realität ist irgendwo dazwischen: Die Appliance ist sicherlich ein für Hersteller und Support attraktiv, verbietet sich aber oft durch Probleme bei der Integration in bestehende Infrastruktur, und nackte Komponenten sind nicht unbedingt das, was Kunden kaufen wollen.

Hierzu eine Anmerkung: Der Lieferumfang eines Produktes sollte immer so strikt wie möglich definiert sein, also nur die absolut notwendigen Bestandteile umfassen. Beispiel: Wenn ich eine Web-Applikation liefere, dann enthält mein Lieferpaket im Idealfall nur die unvermeidlichen Bestandteile meine-webapp.war und Handbuch-für-meine-webapp.pdf, in dem steht, auf welcher Plattform meine-webapp.war deployed werden kann.

Warum? Weil man für alles, was man liefert, verantwortlich ist. Im schlimmsten Falle also für jeden Programmfehler im verwendeten Tomcat, sofern man sich erweichen ließ und einen Tomcat ins Lieferarchiv gepackt hat. In diesem Falle muß man also regelmäßig Updates der ursprünglichen Lieferung schicken, die alle getestet werden müssen -- und obwohl die eigene Kreation sich möglicherweise schon lange nicht mehr geändert hat, entsteht hier ein regelmäßiger Aufwand. Ist man mit den Verträgen ungeschickt, sind womöglich Probleme mit der Gewährleistung nicht ausgeschlossen. Schön, das ist ein Schreckensszenario, welches so schnell nicht eintreten sollte, aber es bleibt ein potentielles Problem.

Das hat auch eine Auswirkung auf die Softwareentwicklung: Der Verzicht auf das "Anpassen" (aka "customizing") der Plattform vereinfachen Deployment und Betrieb und erlaubt, die Plattform "out-of-the-box" zu verwenden. Damit entfällt ein wichtiger Grund, die Plattform mitzuliefern, den Lieferumfang deutlich strafft.

Dienstag, 20. September 2011

Über Keyword Substitution

Mal wieder Git, aber diesmal ein Thema, was Git nicht kann: Keyword Substitution. Wer RSC, CVS oder SVN kennt, ist früher oder später über die praktischen kleinen Helferchen gestolpert, die in jede Datei die Versionsnummer fest einbrennen, und auch ältere SCM-Fossile verfügen über diese Fähigkeit. Ich selbst habe in meiner Zeit als CVS-Anwender in jeden Dateiheader sklavisch ein $Id$ gehackt und das gleich zur persönlichen Best Practice erklärt, denn schließlich ist es ja wichtig, jederzeit zu wissen, in welcher Dateiversion man unterwegs ist. Daher hat es mich etwas verstört, daß Git nicht nur keine Keyword Substitution kennt, sondern die Git-Entwickler sich auch noch strikt weigern, eine solche einzubauen. Was denken die sich dabei?

Wie sich herausstellt, haben sie gute Gründe -- am einfachsten von Linus Torvalds in einer ausreichend undiplomatischen eMail zusammengefaßt. Die Argumente im einzelnen:

Zunächst einmal ist klar, daß externe Tools von $Id$-Strings verwirrt werden, schließlich haben die keine Möglichkeit, die zu vergleichenden Texte ohne die Substitution zu vergleichen. Aber das ist vielleicht nicht so schlimm, denn erstens kann man ja alle zu vergleichenden Texte vorher durch einen Filter schicken, der die Strings entfernt -- genau so wie es CVS und SVN beim Einchecken tun.

Der zweite Punkt leuchtet auch sofort ein: Ein SCM, welches eine Keyword Substitution vornimmt, muß genau wissen, was man gerade eincheckt. Warum ist das ein Problem? Wir wissen ja schließlich auch, daß man Binärdateien nicht mergen kann, und schrecken trotzdem nicht vor dem Mergen zurück! Der Grund liegt in der Art, wie ein SCM Dateien mit Keywords speichern muss: Nämlich erstaunlicherweise ohne Keywords! Die Keywords werden tatsächlich während des Auscheckens ersetzt, da ansonsten zwei Versionen eines Textes garantiert unterschiedlich wären, selbst wenn sich inhaltlich nichts geändert hat. Irrt sich jetzt das SCM beim Einchecken, so zerstört es die zu sichernde Datei und speichert einen großen Haufen Müll, was im schlimmsten Falle erstmal niemanden auffällt (unbedingt mal ausprobieren: Ein PDF in VSS einchecken -- wird als 7-Bit-EBCDIC-Text erkannt und rettungslos verstümmelt). Dem Nutzer wird das erst bewußt, wenn er mal Dateien aus dem SCM abrufen will. Aber dann sind seine vorherigen Bemühungen bereits zerstört.

Der dritte Punkt klingt erstmal etwas altklug: Natürlich weiß das SCM viel besser, welche Version ich gerade ausgecheckt habe, aber ich will das doch auch sehen! Nun, tatsächlich kann ich das ja auch sehen, aber die Frage ist: Wann muß ich es wissen? Nicht beim Schreiben von Code, denn da arbeitet man ohnehin auf dem HEAD. Interessant wird die Version einer Datei bei der Analyse von Code, und hier spielt die Version einer einzelnen Datei eine verblüffend geringe Rolle. Wichtiger ist hier der Kontext: Welche Dateien gehören zusammen, welche Änderungen bilden einen inhaltlich zusammengehörigen Change Set? An dieser Stelle klickt wieder ein Puzzleteil an die richtige Stelle: Git hat ohnehin keine handlichen Versionsnummern, nur SHA1-Identifier für Change Sets, und die vermißt wirklich niemand im Quelltextheader.

Nun, vielleicht nicht im Quelltextheader, aber wie ist es mit der "About this Application"-Box? Ah, richtig, die ausgelieferten Versionen müssen natürlich irgendwie kenntlich gemacht werden. Aber hier kommt ein anderes Prinzip zum Tragen: Die Produktversion hat nichts mit der technischen Version des SCM zu tun. Wirklich nicht. Und wenn die Produktversion nicht von der SCM-Version abhängt, muß die SCM-Version auch nicht im Produkt stehen. Hier bieten sich Build-Nummern an, die ihrerseits Tags im SCM steuern (das SCM ist also nicht das führende System).

Zuletzt aber noch ein Argument, für das ich im Moment kein Zitat finde (auch das ist von Torvalds, nur beweisen kann ich's nicht): Ein SCM muß Dateien immer unverändert speichern, und wenn sich zwei Versionen einer Datei nur in der Versionsnummer unterscheiden, hat das SCM einen fundamentalen Fehler. Warum? Weil ein SCM schließlich Inhalte speichern muß und nicht einfach nur Nummern hochzählt (das können Taschenrechner besser). Folglich muß ein funktionierendes SCM zwei Dateien, die sich nicht unterscheiden, immer die selbe Versionsnummer zuweisen.

An dieser Stelle muß man erstmal kurz anhalten und ausführlich nachdenken. Es stimmt, natürlich, und es hat Konsequenzen: Demnach sind nicht nur die Keyword Substitutions schlecht, sondern auch alle automatischen Umkodierungen (Unix/DOS, ASCII/UTF-8, ...). Und wer schon ein Weilchen mit verschiedenen Plattformen und SCMs zu tun hatte, weiß, wie viele Probleme sich mit dieser Regel in Luft auflösen.


P.S.: Ich bin sehr froh, recht schnell eingesehen zu haben, daß Torvalds Recht hat. Ich wäre nicht gerne Anhänger einer furchtbaren Idee, noch dazu idiotisch, welche seit Dekaden fundamental fehlgeleitete SCM-Designs bestimmte. Denn ich habe das Licht gesehen. Leider muß ich jetzt zurück in den Keller zu SVN.

Donnerstag, 19. Mai 2011

Git auf CentOS 5.x

Warum ist Git eigentlich kein Bestandteil von RedHat Enterprise Linux? Wäre es Bestandteil von RedHat, dann wäre es auch Bestandteil von CentOS, und dieser Eintrag wäre überflüssig. So aber ist es leider immer noch etwas anstrengend, git auf RHEL und Derivate zu bekommen.

Auf superuser.com gibt es eine Kurzanleitung, die ein Vorgehen beschreibt. Allerdings habe ich noch einen fertigen gist, den ich, wie ich stolz anmerken möchte, schon lange vor besagter Kurzanleitung aus Informationen von Howto-Linux zusammengestellt habe (damals noch für CentOS 5.2). Das Script kann mit

wget https://gist.github.com/raw/146206/bb90b1bff3abb9ac6843aba2b9cce89f36aebeff/install_git_on_centos.sh

heruntergeladen werden und sieht dann so aus:


Zuerst sollte die Proxy-Einstellung und die gewünschte Git-Version geprüft und ggf. angepaßt werden, dann wird das Script noch mit chmod +x install_git_on_centos.sh ausführtbar gemacht, und kann dann gestartet werden. Wenige Minuten später ist ein Git in der gewünschten Version installiert.

Noch ein Nachwort zur veralteten Version: Der gist wird von mir gelegentlich aktualisiert. In der Vergangenheit hat es bei mir keine Probleme beim Zusammenspiel der verschiedenen Git-Versionen, also aktualisiere ich das nur recht selten.