Wie organisieren Sie Ihr Versionskontroll-Repository?


108

Zunächst weiß ich Folgendes: Wie würden Sie ein Subversion-Repository für interne Softwareprojekte organisieren? Als nächstes die eigentliche Frage: Mein Team restrukturiert unser Repository und ich suche nach Hinweisen zur Organisation. (SVN in diesem Fall). Folgendes haben wir uns ausgedacht. Wir haben ein Repository, mehrere Projekte und mehrere svn: externe Querverweise

\commonTools /*tools used in all projects. Referenced in each project with svn:externals*/
   \NUnit.v2.4.8
   \NCover.v.1.5.8
   \<other similar tools>
\commonFiles /*settings strong name keys etc.*/
   \ReSharper.settings
   \VisualStudio.settings
\trash /*each member of the team has trash for samples, experiments etc*/
   \user1
   \user2
\projects
   \Solution1 /*Single actual project (Visual Studio Solution)*/
      \trunk
         \src
             \Project1 /*Each sub-project resulting in single .dll or .exe*/
             \Project2
         \lib
         \tools
         \tests
         \Solution1.sln
      \tags
      \branches
   \Solution2
      \trunk
         \src
             \Project3 /*Each sub-project resulting in single .dll or .exe*/
             \Project1 /*Project1 from Solution1 references with svn:externals*/
         \lib
         \tools
         \tests
         \Solution2.sln
      \tags
      \branches

So löschen Sie den Wortschatz: Lösung bedeutet einzelnes Produkt, Projekt ist ein Visual Studio-Projekt (das zu einer einzelnen DLL oder einer einzelnen EXE-Datei führt)

So wollen wir das Repository gestalten. Das Hauptproblem ist, dass wir mehrere Lösungen haben, aber wir möchten Projekte unter Lösungen teilen. Wir dachten, dass es keinen Sinn macht, diese gemeinsam genutzten Projekte wirklich auf ihre eigenen Lösungen zu verschieben, und entschieden uns stattdessen, svn: externals zu verwenden, um Projekte zwischen Lösungen zu teilen. Wir möchten auch gemeinsame Tools und Bibliotheken von Drittanbietern an einem Ort im Repository aufbewahren und sie in jeder Lösung mit svn: externals referenzieren.

Was denkst du über dieses Layout? Besonders über die Verwendung von svn: externals. Es ist keine ideale Lösung, aber unter Berücksichtigung aller Vor- und Nachteile ist es das Beste, was wir uns vorstellen können. Wie würdest du es machen?


Bist du sicher, dass du "Thrash" meinst? Oder eher "Müll"?
SSC

Antworten:


92

Wenn Sie meinen Empfehlungen unten folgen (ich habe seit Jahren), können Sie:

- Platzieren Sie jedes Projekt an einer beliebigen Stelle in der Quellcodeverwaltung, solange Sie die Struktur aus dem Projektstammverzeichnis nach unten beibehalten

- Erstellen Sie jedes Projekt überall auf einer beliebigen Maschine mit minimalem Risiko und minimaler Vorbereitung

- Erstellen Sie jedes Projekt vollständig eigenständig, solange Sie Zugriff auf seine binären Abhängigkeiten haben (lokale Verzeichnisse "Bibliothek" und "Ausgabe").

- eine beliebige Kombination von Projekten erstellen und bearbeiten, da diese unabhängig sind

- Erstellen und arbeiten Sie mit mehreren Kopien / Versionen eines einzelnen Projekts, da diese unabhängig sind

- Vermeiden Sie es, Ihr Quellcodeverwaltungs-Repository mit generierten Dateien oder Bibliotheken zu überladen

Ich empfehle (hier ist das Rindfleisch):

  1. Definieren Sie jedes Projekt, um ein einzelnes primäres Ergebnis zu erstellen, z. B. eine DLL, eine EXE-Datei oder eine JAR-Datei (Standard bei Visual Studio).

  2. Strukturieren Sie jedes Projekt als Verzeichnisbaum mit einem einzigen Stamm.

  3. Erstellen Sie für jedes Projekt in seinem Stammverzeichnis ein automatisiertes Erstellungsskript, das es von Grund auf neu erstellt, ohne von einer IDE abhängig zu sein (verhindern Sie jedoch nicht, dass es in der IDE erstellt wird, wenn dies möglich ist).

  4. Erwägen Sie nAnt für .NET-Projekte unter Windows oder ähnliches, basierend auf Ihrem Betriebssystem, Ihrer Zielplattform usw.

  5. Lassen Sie jedes Projekterstellungsskript auf seine externen Abhängigkeiten (von Drittanbietern) von einem einzelnen lokalen gemeinsam genutzten "Bibliotheksverzeichnis" verweisen, wobei jede solche Binärdatei VOLLSTÄNDIG durch die Version identifiziert wird: %DirLibraryRoot%\ComponentA-1.2.3.4.dll, %DirLibraryRoot%\ComponentB-5.6.7.8.dll.

  6. Machen Sie jedes Projekt Build - Skript das primäre lieferbare zu einem einzigen lokalen gemeinsamen „output“ Verzeichnis veröffentlichen: %DirOutputRoot%\ProjectA-9.10.11.12.dll, %DirOutputRoot%\ProjectB-13.14.15.16.exe.

  7. Lassen Sie jedes Projekterstellungsskript über konfigurierbare und vollständig versionierte absolute Pfade (siehe oben) in den Verzeichnissen "Bibliothek" und "Ausgabe" auf seine Abhängigkeiten verweisen, UND NOCH WO SONST.

  8. Lassen Sie ein Projekt NIEMALS direkt auf ein anderes Projekt oder einen seiner Inhalte verweisen - erlauben Sie nur Verweise auf die primären Ergebnisse im Verzeichnis "Ausgabe" (siehe oben).

  9. Lassen Sie jedes Projekt-Build-Skript über einen konfigurierbaren und vollständig versionierten absoluten Pfad auf die erforderlichen Build-Tools verweisen: %DirToolRoot%\ToolA\1.2.3.4, %DirToolRoot%\ToolB\5.6.7.8.

  10. Erstellen Sie für jeden Projekt-Build-Skript-Referenzquellinhalt einen absoluten Pfad relativ zum Projektstammverzeichnis : ${project.base.dir}/src, ${project.base.dir}/tst(Syntax variiert je nach Build-Tool).

  11. IMMER ist ein Projekterstellungsskript erforderlich, um JEDE Datei oder jedes Verzeichnis über einen absoluten, konfigurierbaren Pfad zu referenzieren (der in einem Verzeichnis verwurzelt ist, das durch eine konfigurierbare Variable angegeben wird): ${project.base.dir}/some/dirsoder ${env.Variable}/other/dir.

  12. Erlauben Sie einem Projekterstellungsskript NIEMALS, auf ALLES mit einem relativen Pfad wie .\some\dirs\hereoder zu verweisen. ..\some\more\dirsVerwenden Sie IMMER absolute Pfade.

  13. Lassen Sie NIEMALS zu, dass ein Projekterstellungsskript unter Verwendung eines absoluten Pfads, der kein konfigurierbares Stammverzeichnis hat, wie C:\some\dirs\hereoder , auf ALLES verweist \\server\share\more\stuff\there.

  14. Definieren Sie für jedes konfigurierbare Stammverzeichnis, auf das von einem Projekterstellungsskript verwiesen wird, eine Umgebungsvariable, die für diese Referenzen verwendet wird.

  15. Versuchen Sie, die Anzahl der Umgebungsvariablen zu minimieren, die Sie zum Konfigurieren der einzelnen Computer erstellen müssen.

  16. Erstellen Sie auf jedem Computer ein Shell-Skript, das die erforderlichen Umgebungsvariablen definiert, die für DIESEN Computer spezifisch sind (und möglicherweise für diesen Benutzer, falls relevant).

  17. Stellen Sie das maschinenspezifische Konfigurations-Shell-Skript NICHT in die Quellcodeverwaltung. Legen Sie stattdessen für jedes Projekt eine Kopie des Skripts im Projektstammverzeichnis als Vorlage fest.

  18. ERFORDERN Sie jedes Projekterstellungsskript, um jede seiner Umgebungsvariablen zu überprüfen, und brechen Sie mit einer aussagekräftigen Nachricht ab, wenn sie nicht definiert sind.

  19. ERFORDERN Sie jedes Projekterstellungsskript, um die ausführbaren Dateien des abhängigen Build-Tools, der externen Bibliotheksdateien und der vom Projekt bereitgestellten Dateien zu überprüfen und mit einer aussagekräftigen Meldung abzubrechen, wenn diese Dateien nicht vorhanden sind.

  20. Widerstehen Sie der Versuchung, generierte Dateien in die Quellcodeverwaltung zu übernehmen - keine Projektergebnisse, keine generierte Quelle, keine generierten Dokumente usw.

  21. Wenn Sie eine IDE verwenden, generieren Sie alle Projektsteuerungsdateien, die Sie können, und verpflichten Sie sie nicht zur Quellcodeverwaltung (dies schließt Visual Studio-Projektdateien ein).

  22. Richten Sie einen Server mit einer offiziellen Kopie aller externen Bibliotheken und Tools ein, die auf Entwicklerarbeitsstationen kopiert / installiert und Maschinen erstellt werden sollen. Sichern Sie es zusammen mit Ihrem Quellcodeverwaltungs-Repository.

  23. Richten Sie einen Continuous Integration Server (Build Machine) ohne jegliche Entwicklungstools ein.

  24. Betrachten Sie ein Tool zum Verwalten Ihrer externen Bibliotheken und Liefergegenstände, z. B. Ivy (verwendet mit Ant).

  25. Verwenden Sie Maven NICHT - es wird Sie zunächst glücklich machen und Sie schließlich zum Weinen bringen.

Beachten Sie, dass nichts davon spezifisch für Subversion ist und das meiste davon generisch für Projekte ist, die auf ein Betriebssystem, eine Hardware, eine Plattform, eine Sprache usw. abzielen. Ich habe ein wenig betriebssystem- und werkzeugspezifische Syntax verwendet, aber nur zur Veranschaulichung. -Ich vertraue darauf, dass Sie in Ihr Betriebssystem oder Tool Ihrer Wahl übersetzen.

Zusätzlicher Hinweis zu Visual Studio-Lösungen: Stellen Sie sie nicht in die Quellcodeverwaltung! Bei diesem Ansatz benötigen Sie sie überhaupt nicht oder können sie generieren (genau wie die Visual Studio-Projektdateien). Ich finde es jedoch am besten, die Lösungsdateien einzelnen Entwicklern zu überlassen, um sie nach eigenem Ermessen zu erstellen / zu verwenden (aber nicht in die Quellcodeverwaltung eingecheckt). Ich behalte eine Rob.slnDatei auf meiner Workstation, von der aus ich auf meine aktuellen Projekte verweise. Da meine Projekte alle eigenständig sind, kann ich Projekte nach Belieben hinzufügen / entfernen (dh keine projektbasierten Abhängigkeitsreferenzen).

Bitte verwenden Sie keine Subversion-Externals (oder ähnliches in anderen Tools), sie sind ein Anti-Pattern und daher nicht erforderlich.

Wenn Sie eine kontinuierliche Integration implementieren oder den Release-Prozess nur automatisieren möchten, erstellen Sie ein Skript dafür. Erstellen Sie ein einzelnes Shell-Skript, das: Parameter des Projektnamens (wie im Repository aufgeführt) und des Tag-Namens verwendet, ein temporäres Verzeichnis in einem konfigurierbaren Stammverzeichnis erstellt und die Quelle auf den angegebenen Projektnamen und Tag-Namen überprüft (indem Sie das erstellen Die entsprechende URL (im Fall von Subversion) zu diesem temporären Verzeichnis führt einen sauberen Build durch, der Tests ausführt und das Ergebnis packt. Dieses Shell-Skript sollte für jedes Projekt funktionieren und im Rahmen Ihres Projekts "Build Tools" in die Quellcodeverwaltung eingecheckt werden. Ihr Continuous Integration Server kann dieses Skript als Grundlage für das Erstellen von Projekten verwenden oder es sogar bereitstellen (aber Sie möchten möglicherweise immer noch Ihr eigenes).

@VonC: Sie möchten NICHT immer mit "ant.jar" anstatt mit "ant-abcdjar" arbeiten, nachdem Sie verbrannt wurden, wenn Ihr Build-Skript kaputt geht, weil Sie es unwissentlich mit einer inkompatiblen Version von Ant ausgeführt haben. Dies ist besonders häufig zwischen Ant 1.6.5 und 1.7.0. Verallgemeinernd möchten Sie IMMER wissen, welche spezifische Version JEDER Komponente verwendet wird, einschließlich Ihrer Plattform (Java ABCD) und Ihres Build-Tools (Ant EFGH). Andernfalls wird es irgendwann zu einem Fehler kommen und Ihr erstes großes Problem besteht darin, herauszufinden, welche Versionen Ihrer verschiedenen Komponenten betroffen sind. Es ist einfach besser, dieses Problem im Voraus zu lösen.


6
So viele Punkte zu kritisieren ... genügt zu sagen, dass dies kein universelles Rezept ist! Insbesondere die Punkte 5 und 6 sind ach so falsch, wenn das Projekt groß ist und die Anzahl der Dritten wichtig ist: Sie möchten jederzeit mit 'ant.jar', nicht mit 'ant1.5.4.jar' oder dem Produkt myProduct arbeiten .exe, nicht 1.3.exe
VonC

5
Dennoch +1 für viele andere Punkte, die Sie ansprechen, die gültig sind und für Ihre große Erfahrung in diesem Thema sprechen.
VonC

3
Ich würde gerne Ihre Kritik hören und mit ihr interagieren - jeder Punkt basiert auf der Lösung schlechter Erfahrungen mit großen Projekten. Zum Beispiel das Problem, welche Versionen durch Xxx.jar und Yyy.exe dargestellt werden, insbesondere wenn buchstäblich ein Dutzend Kopien referenziert werden.
Rob Williams

2
@Rob - Können Sie Ihr Thema "Externe Antimuster" erläutern? Ich habe es hier als Frage aufgeworfen: stackoverflow.com/questions/338824/…
Ken

3
@ Makis: Sie wären richtig, wenn # 12 nicht durch # 13 ausgeglichen wären. Jeder Verweis auf eine Datei oder ein Verzeichnis in jedem Projekt sollte über einen absoluten Pfad erfolgen, der mit einer konfigurierbaren Stammverzeichnisvariablen beginnt, z. B. $ {basedir} /sub/dir/file.txt in Ant.
Rob Williams


3

Wir haben unsere so eingestellt, dass sie fast genau mit dem übereinstimmen, was Sie gepostet haben. Wir verwenden die allgemeine Form:

\Project1
   \Development (for active dev - what you've called "Trunk", containing everything about a project)
   \Branches (For older, still-evolving supported branches of the code)
       \Version1
       \Version1.1
       \Version2
   \Documentation (For any accompanying documents that aren't version-specific

Ich nehme an, es ist nicht so vollständig wie Ihr Beispiel, aber es hat bei uns gut funktioniert und lässt uns die Dinge getrennt halten. Ich mag die Idee, dass jeder Benutzer auch einen "Thrash" -Ordner hat - derzeit landen diese Projekttypen nicht in der Quellcodeverwaltung, und ich hatte immer das Gefühl, dass dies der Fall sein sollte.


3
Ich bin überrascht, dass Sie ein separates Verzeichnis für Dokumente haben, die sich nicht zwischen den Versionen ändern ... Ich hatte noch nie das Vergnügen, an einem solchen Produkt zu arbeiten! :)
ARKBAN

1

Warum alles in einem Repository? Warum nicht einfach ein separates Repository für jedes Projekt haben (ich meine "Lösung")?

Nun, zumindest habe ich mich an den Ein-Projekt-pro-Repository-Ansatz gewöhnt. Ihre Repository-Struktur scheint mir zu kompliziert.

Und wie viele Projekte planen Sie in dieses eine große Repository zu stellen? 2? 3? 10? 100?

Und was machen Sie, wenn Sie die Entwicklung eines Projekts abbrechen? Löschen Sie es einfach aus dem Repository-Baum, damit es in Zukunft schwer zu finden ist. Oder für immer herumliegen lassen? Oder wenn Sie ein Projekt ganz auf einen anderen Server verschieben möchten?

Und was ist mit dem Durcheinander all dieser Versionsnummern? Die Versionsnummern eines Projekts lauten 2, 10, 11, während das andere 1, 3, 4, 5, 6, 7, 8, 9, 12 ...

Vielleicht bin ich dumm, aber ich mag ein Projekt pro Repository.


1. Ein Repository ist eine Unternehmensrichtlinie, kann das nicht ändern. 2. Wir werden ungefähr ein Dutzend Lösungen haben. 3. Mit Versionsnummern meinen Sie Revisionen? Das ist für uns kein Thema.
Krzysztof Kozmic

Eine gute Projektstruktur sollte den Rest der Repository-Struktur nicht berücksichtigen, insbesondere in Bezug auf ein oder mehrere Repositorys. Bitte beachten Sie meine ausführliche Antwort.
Rob Williams

1
Beachten Sie, dass das Vorhandensein mehrerer Repositorys in vielen (den meisten?) Tools zur Quellcodeverwaltung SEHR teuer sein kann, z. B. wenn Sie Sicherheit implementieren.
Rob Williams

0

Ich denke, der Hauptnachteil der vorgeschlagenen Struktur besteht darin, dass die gemeinsam genutzten Projekte nur mit der ersten Lösung versioniert werden, zu der sie hinzugefügt wurden (es sei denn, svn: externals ist schicker als ich es mir vorstelle). Wenn Sie beispielsweise eine Verzweigung für die erste Version von Solution2 erstellen, wird Project1 nicht verzweigt, da es in Solution1 gespeichert ist. Wenn Sie zu einem späteren Zeitpunkt aus diesem Zweig erstellen müssen (QFE-Version), wird zum Zeitpunkt des Zweigs die neueste Version von Project1 anstelle der Version von Project1 verwendet.

Aus diesem Grund kann es vorteilhaft sein, die gemeinsam genutzten Projekte in einer oder mehreren gemeinsam genutzten Lösungen (und damit in Verzeichnissen der obersten Ebene in Ihrer Struktur) abzulegen und sie dann mit jeder Version einer beliebigen Lösung zu verzweigen .


Sie haben bis zu einem gewissen Grad Recht. Aber wir können die Referenz aktualisieren, wenn wir wollen. Und gemeinsame Projekte in ihre eigene Lösung zu integrieren, macht auch wenig Sinn. Obwohl ich gerne eine bessere Lösung als svn finden würde: Externe überall.
Krzysztof Kozmic

Was meinst du mit "Referenz aktualisieren, wenn wir wollen"? Ich sehe nicht ein, wie Sie Project1 verzweigen könnten (was wünschenswert erscheint, wenn Sie Solution2 verzweigen), ohne Solution1 zu verzweigen.
C. Dragon 76

Bitte lesen Sie meine ausführliche Antwort, insbesondere, um Visual Studio-Lösungen NICHT in die Quellcodeverwaltung zu integrieren.
Rob Williams

0

So fügen Sie dem relativen Pfadproblem Folgendes hinzu:

Ich bin mir nicht sicher, ob es sich um ein Problem handelt:
Checken Sie einfach Solution1 / trunk unter dem Verzeichnis "Solution1" aus, ebenso wie Solution2: Das Ziel von "Verzeichnissen", die tatsächlich Zweige darstellen, besteht darin, nach dem Import in einen Arbeitsbereich nicht sichtbar zu sein. Daher sind relative Pfade zwischen 'Lösung1' (tatsächlich 'Lösung1 / Amtsleitung') und 'Lösung2' (Lösung2 / Amtsleitung) möglich.


Dies würde sehr leicht brechen, siehe meine ausführliche Antwort.
Rob Williams

0

RE: Der relative Pfad und das Problem mit gemeinsam genutzten Dateien -

Es scheint, dass dies SVN-spezifisch ist, aber das ist kein Problem. Eine andere Person hat bereits separate Repositories erwähnt, und das ist wahrscheinlich die beste Lösung, die ich mir vorstellen kann, wenn Sie unterschiedliche Projekte haben, die sich auf beliebige andere Projekte beziehen. Wenn Sie keine freigegebenen Dateien haben, funktioniert die OP-Lösung (wie auch viele andere) einwandfrei.

Wir arbeiten noch daran und ich habe 3 verschiedene Bemühungen (verschiedene Clients), die ich jetzt lösen muss, da ich die Einrichtung einer nicht vorhandenen oder schlechten Versionskontrolle übernommen habe.


Wenn Projekte auf andere Projekte verweisen, entsteht ein Alptraum für die Wartung, da die Abhängigkeiten exponentiell zunehmen und die Verweise SEHR fragil sind. Bitte beachten Sie meine ausführliche Antwort.
Rob Williams

0

Ich habe ein ähnliches Layout, aber mein Kofferraum, meine Zweige und Tags befinden sich ganz oben. Also: / trunk / main, / trunk / utils, / branch / release / usw.

Dies war sehr praktisch, als wir andere Versionskontrollsysteme ausprobieren wollten, da viele der Übersetzungstools am besten mit dem SVN-Layout des Grundlehrbuchs funktionierten.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.