Jak organizujesz repozytorium kontroli wersji?


108

Po pierwsze, wiem o tym: Jak zorganizowałbyś repozytorium Subversion dla wewnętrznych projektów oprogramowania? Następnie właściwe pytanie: Mój zespół restrukturyzuje nasze repozytorium i szukam wskazówek, jak to zorganizować. (W tym przypadku SVN). Oto, co wymyśliliśmy. Mamy jedno repozytorium, wiele projektów i wiele odsyłaczy svn: externals

\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

Aby wyczyścić słownictwo: rozwiązanie oznacza pojedynczy produkt, projekt jest projektem programu Visual Studio (co daje pojedynczy plik .dll lub pojedynczy plik .exe)

Tak planujemy rozplanować repozytorium. Głównym problemem jest to, że mamy wiele rozwiązań, ale chcemy dzielić się projektami między rozwiązaniami. Pomyśleliśmy, że tak naprawdę nie ma sensu przenosić tych współdzielonych projektów do własnych rozwiązań, a zamiast tego zdecydowaliśmy się użyć svn: externals do dzielenia projektów między rozwiązaniami. Chcemy również przechowywać wspólny zestaw narzędzi i bibliotek zewnętrznych w jednym miejscu w repozytorium i odwoływać się do nich w każdym rozwiązaniu za pomocą svn: externals.

Co myślisz o tym układzie? Zwłaszcza jeśli chodzi o użycie svn: externals. To nie jest idealne rozwiązanie, ale biorąc pod uwagę wszystkie zalety i wady, jest to najlepsze, o czym możemy pomyśleć. Jak byś to zrobił?


Czy na pewno masz na myśli „thrash”? A może raczej „śmieci”?
ssc

Odpowiedzi:


92

Jeśli zastosujesz się do moich zaleceń poniżej (mam od lat), będziesz mógł:

- umieść każdy projekt w dowolnym miejscu w kontroli źródła, o ile zachowasz strukturę z katalogu głównego projektu

- buduj każdy projekt w dowolnym miejscu na dowolnej maszynie, przy minimalnym ryzyku i minimalnym przygotowaniu

- buduj każdy projekt całkowicie samodzielnie, o ile masz dostęp do jego binarnych zależności (lokalna "biblioteka" i "wyjściowe" katalogi)

- budować i pracować z dowolną kombinacją projektów, ponieważ są one niezależne

- budować i pracować z wieloma kopiami / wersjami jednego projektu, ponieważ są one niezależne

- unikaj zaśmiecania repozytorium kontroli źródła wygenerowanymi plikami lub bibliotekami

Polecam (tu wołowina):

  1. Zdefiniuj każdy projekt w celu utworzenia jednego podstawowego elementu dostarczanego, takiego jak .DLL, .EXE lub .JAR (domyślnie w programie Visual Studio).

  2. Strukturyzuj każdy projekt jako drzewo katalogów z jednym korzeniem.

  3. Utwórz zautomatyzowany skrypt kompilacji dla każdego projektu w jego katalogu głównym, który zbuduje go od podstaw, bez żadnych zależności od IDE (ale nie uniemożliwiaj budowania go w IDE, jeśli to możliwe).

  4. Rozważ nAnt dla projektów .NET w systemie Windows lub czegoś podobnego w zależności od systemu operacyjnego, platformy docelowej itp.

  5. Spraw, aby każdy skrypt budowania projektu odwoływał się do zewnętrznych (zewnętrznych) zależności z jednego lokalnego katalogu „biblioteki”, z każdym takim plikiem binarnym W PEŁNI identyfikowanym przez wersję: %DirLibraryRoot%\ComponentA-1.2.3.4.dll, %DirLibraryRoot%\ComponentB-5.6.7.8.dll.

  6. Spraw, aby każdy skrypt kompilacji projektu publikował podstawowy element dostarczany w pojedynczym lokalnym udostępnionym katalogu „wyjściowym”: %DirOutputRoot%\ProjectA-9.10.11.12.dll, %DirOutputRoot%\ProjectB-13.14.15.16.exe.

  7. Spraw, aby każdy skrypt budowania projektu odwoływał się do jego zależności za pośrednictwem konfigurowalnych iw pełni wersjonowanych ścieżek bezwzględnych (patrz wyżej) w katalogach „biblioteka” i „wyjście”, ORAZ ŻADNYCH INNYCH.

  8. NIGDY nie pozwól, aby projekt bezpośrednio odwoływał się do innego projektu lub jakiejkolwiek jego zawartości - zezwalaj tylko na odniesienia do podstawowych elementów dostarczanych w katalogu „output” (patrz powyżej).

  9. Spraw, aby każdy skrypt kompilacji projektu odwoływał się do wymaganych narzędzi kompilacji za pomocą konfigurowalnej iw pełni wersjonowanej ścieżki bezwzględnej: %DirToolRoot%\ToolA\1.2.3.4, %DirToolRoot%\ToolB\5.6.7.8.

  10. Dokładamy wszelkich build skryptu zawartość źródła odniesienia bezwzględną ścieżkę w stosunku do głównego katalogu projektu: ${project.base.dir}/src, ${project.base.dir}/tst(składnia zależy od budowy narzędzia).

  11. ZAWSZE wymagaj, aby skrypt budowania projektu odnosił się do KAŻDEGO pliku lub katalogu za pośrednictwem bezwzględnej, konfigurowalnej ścieżki (zakorzenionej w katalogu określonym przez konfigurowalną zmienną): ${project.base.dir}/some/dirslub ${env.Variable}/other/dir.

  12. NIGDY nie zezwalaj skryptowi budowania projektu na odwoływanie się do CZEGOKOLWIEK za pomocą ścieżki względnej, takiej jak .\some\dirs\herelub ..\some\more\dirs, ZAWSZE używaj ścieżek bezwzględnych.

  13. NIGDY nie zezwalaj skryptowi budowania projektu na odwoływanie się do CZEGOKOLWIEK przy użyciu ścieżki bezwzględnej, która nie ma konfigurowalnego katalogu głównego, takiego jak C:\some\dirs\herelub \\server\share\more\stuff\there.

  14. Dla każdego konfigurowalnego katalogu głównego, do którego odwołuje się skrypt kompilacji projektu, zdefiniuj zmienną środowiskową, która będzie używana dla tych odwołań.

  15. Spróbuj zminimalizować liczbę zmiennych środowiskowych, które musisz utworzyć, aby skonfigurować każdy komputer.

  16. Na każdym komputerze utwórz skrypt powłoki, który definiuje niezbędne zmienne środowiskowe, specyficzne dla TEGO komputera (i ewentualnie specyficzne dla tego użytkownika, jeśli ma to zastosowanie).

  17. NIE umieszczaj skryptu powłoki konfiguracyjnej specyficznej dla komputera w kontroli źródła; zamiast tego dla każdego projektu zatwierdź kopię skryptu w katalogu głównym projektu jako szablon.

  18. WYMAGAJĄ każdego skryptu budowania projektu, aby sprawdził każdą z jego zmiennych środowiskowych i przerywał, wysyłając znaczący komunikat, jeśli nie są zdefiniowane.

  19. WYMAGAJĄ każdego skryptu budowania projektu, aby sprawdził każdy z jego zależnych plików wykonywalnych narzędzia do budowania, plików bibliotek zewnętrznych i zależnych plików dostarczalnych projektów i przerwał, wyświetlając znaczący komunikat, jeśli te pliki nie istnieją.

  20. OPIERAJ SIĘ przed pokusą przekazania JAKICHKOLWIEK wygenerowanych plików do kontroli źródła - żadnych elementów projektu, żadnego wygenerowanego źródła, żadnych wygenerowanych dokumentów itp.

  21. Jeśli używasz środowiska IDE, wygeneruj dowolne pliki kontrolne projektu, które możesz, i nie zatwierdzaj ich do kontroli źródła (dotyczy to plików projektu programu Visual Studio).

  22. Stwórz serwer z oficjalną kopią wszystkich zewnętrznych bibliotek i narzędzi, które mają być kopiowane / instalowane na stacjach roboczych programistów i maszynach budowlanych. Utwórz kopię zapasową wraz z repozytorium kontroli źródła.

  23. Stwórz serwer ciągłej integracji (maszynę budującą) BEZ żadnych narzędzi programistycznych.

  24. Rozważ narzędzie do zarządzania zewnętrznymi bibliotekami i materiałami dostarczanymi, takie jak Ivy (używane z Ant).

  25. NIE używaj Mavena - początkowo cię uszczęśliwi, a ostatecznie doprowadzi do płaczu.

Zauważ, że nic z tego nie jest specyficzne dla Subversion, a większość z nich jest ogólna dla projektów nakierowanych na dowolny system operacyjny, sprzęt, platformę, język itp. Użyłem trochę składni specyficznej dla systemu operacyjnego i narzędzia, ale tylko dla ilustracji - - Ufam, że przełożysz na swój system operacyjny lub wybrane narzędzie.

Dodatkowa uwaga dotycząca rozwiązań Visual Studio: nie umieszczaj ich w kontroli źródła! Dzięki takiemu podejściu w ogóle ich nie potrzebujesz lub możesz je wygenerować (podobnie jak pliki projektu programu Visual Studio). Uważam jednak, że najlepiej jest pozostawić pliki rozwiązania poszczególnym programistom do tworzenia / używania według własnego uznania (ale nie w kontroli źródła). Rob.slnNa mojej stacji roboczej przechowuję plik, z którego odwołuję się do mojego bieżącego projektu (ów). Ponieważ wszystkie moje projekty są samodzielne, mogę dowolnie dodawać / usuwać projekty (oznacza to brak odniesień do zależności opartych na projektach).

Proszę nie używać zewnętrznych elementów Subversion (lub podobnych w innych narzędziach), są one anty-wzorcem i dlatego są niepotrzebne.

Jeśli wdrażasz ciągłą integrację, a nawet chcesz zautomatyzować proces wydawania, utwórz dla niej skrypt. Stwórz pojedynczy skrypt powłoki, który: pobiera parametry nazwy projektu (zgodnie z listą w repozytorium) i nazwę znacznika, tworzy katalog tymczasowy w konfigurowalnym katalogu głównym, sprawdza źródło dla podanej nazwy projektu i nazwy znacznika (poprzez utworzenie odpowiedni adres URL w przypadku Subversion) do tego katalogu tymczasowego, wykonuje czystą kompilację, która uruchamia testy i pakuje element dostarczany. Ten skrypt powłoki powinien działać w każdym projekcie i powinien zostać wpisany do kontroli źródła jako część projektu „narzędzi do budowania”. Twój serwer ciągłej integracji może używać tego skryptu jako podstawy do tworzenia projektów, a nawet może go udostępniać (ale nadal możesz chcieć własnego).

@VonC: NIE chcesz pracować przez cały czas z "ant.jar" zamiast "ant-abcdjar" po wypaleniu skryptu kompilacji, ponieważ nieświadomie uruchomiłeś go z niekompatybilną wersją Ant. Jest to szczególnie częste między Ant 1.6.5 i 1.7.0. Ogólnie rzecz biorąc, ZAWSZE chcesz wiedzieć, jaka konkretna wersja KAŻDEGO komponentu jest używana, w tym Twoja platforma (Java ABCD) i narzędzie do budowania (Ant EFGH). W przeciwnym razie w końcu napotkasz błąd, a Twoim pierwszym DUŻYM problemem będzie śledzenie, jakie wersje różnych komponentów są zaangażowane. Po prostu lepiej jest rozwiązać ten problem z góry.


6
Tyle punktów do skrytykowania ... wystarczy powiedzieć, że nie jest to przepis uniwersalny! W szczególności punkty 5 i 6 są tak błędne, gdy projekt jest duży, a liczba osób trzecich jest ważna: chcesz zawsze pracować z „ant.jar”, ​​a nie z „ant1.5.4.jar” lub produktem myProduct .exe, a nie 1.3.exe
VonC

5
Mimo to +1 za wiele innych punktów, które robisz, które są ważne i dobrze świadczą o twoim ogromnym doświadczeniu w tym temacie.
VonC

3
Chciałbym usłyszeć Twoją krytykę i nawiązać z nią interakcję - każdy punkt opiera się na rozwiązywaniu złych doświadczeń z dużymi projektami. Na przykład rozwiązanie problemu, które wersje są reprezentowane przez Xxx.jar i Yyy.exe, zwłaszcza gdy przywoływane są dosłownie tuzin kopii.
Rob Williams

2
@Rob - Czy możesz rozwinąć temat swojego „zewnętrznego antywzorca”? Podniosłem to jako pytanie tutaj: stackoverflow.com/questions/338824/…
Ken,

3
@Makis: Miałbyś rację, JEŚLI numer 12 nie został zbalansowany przez numer 13. Każde odwołanie do pliku lub katalogu w każdym projekcie powinno być dokonywane poprzez ścieżkę bezwzględną, która zaczyna się od konfigurowalnej zmiennej katalogu głównego, np. $ {Basedir} /sub/dir/file.txt w Ant.
Rob Williams,


3

Ustawiliśmy nasze tak, aby prawie dokładnie odpowiadały temu, co opublikowałeś. Używamy ogólnej formy:

\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

Chociaż przypuszczam, że nie jest tak kompletny jak twój przykład, działał dobrze dla nas i pozwala nam oddzielić rzeczy. Podoba mi się pomysł, aby każdy użytkownik miał również folder „Thrash” - obecnie tego typu projekty nie trafiają do kontroli wersji źródłowej i zawsze uważałem, że powinni.


3
Dziwię się, że masz osobny katalog na dokumenty, które nie zmieniają się między wersjami… Nigdy nie miałem przyjemności pracować nad takim produktem! :)
ARKBAN

1

Po co to wszystko w jednym repozytorium? Dlaczego po prostu nie mieć osobnego repozytorium dla każdego projektu (mam na myśli „Rozwiązanie”)?

Cóż, przynajmniej przyzwyczaiłem się do podejścia „jeden projekt na repozytorium”. Twoja struktura repozytorium wydaje mi się zbyt skomplikowana.

A ile projektów planujesz umieścić w tym jednym dużym repozytorium? 2? 3? 10? 100?

A co robisz, gdy anulujesz rozwój jednego projektu? Po prostu usuń go z drzewa repozytorium, aby w przyszłości trudno było go znaleźć. Albo zostawić to na zawsze? A może chcesz całkowicie przenieść jeden projekt na inny serwer?

A co z bałaganem wszystkich tych numerów wersji? Numery wersji jednego projektu to 2, 10, 11, podczas gdy drugi to 1, 3, 4, 5, 6, 7, 8, 9, 12 ...

Może jestem głupi, ale lubię jeden projekt na repozytorium.


1. Jedno repozytorium to polityka firmy, nie można tego zmienić. 2. Będziemy mieć kilkanaście Rozwiązań. 3. przez numery wersji masz na myśli poprawki? To nie jest dla nas problem.
Krzysztof Kozmic

Dobra struktura projektu nie powinna uwzględniać pozostałej części struktury repozytorium, szczególnie w odniesieniu do jednego lub wielu repozytoriów. Zobacz moją szczegółową odpowiedź.
Rob Williams

1
Należy pamiętać, że posiadanie wielu repozytoriów w wielu (większości?) Narzędziach kontroli źródła może być BARDZO kosztowne, na przykład podczas wdrażania zabezpieczeń.
Rob Williams

0

Myślę, że główną wadą proponowanej struktury jest to, że udostępnione projekty będą wersjonowane tylko z pierwszym rozwiązaniem, do którego zostały dodane (chyba, że ​​svn: externals jest bardziej wyszukany, niż sobie wyobrażam). Na przykład podczas tworzenia gałęzi dla pierwszej wersji rozwiązania 2 projekt 1 nie zostanie rozgałęziony, ponieważ znajduje się w rozwiązaniu 1. Jeśli będziesz musiał skompilować z tej gałęzi w późniejszym czasie (wydanie QFE), użyje ona najnowszej wersji Project1, a nie wersji Project1 w czasie rozgałęzienia.

Z tego powodu korzystne może być umieszczenie współdzielonych projektów w jednym lub kilku współdzielonych rozwiązaniach (a tym samym katalogach najwyższego poziomu w twojej strukturze), a następnie rozgałęzianie ich z każdym wydaniem dowolnego rozwiązania.


Do pewnego stopnia masz rację. Ale możemy zaktualizować odniesienie, jeśli chcemy. A umieszczanie udostępnionych projektów we własnym rozwiązaniu również nie ma większego sensu. Chociaż chciałbym znaleźć lepsze rozwiązanie niż svn: zewnętrzne w każdym miejscu.
Krzysztof Kozmic

Co rozumiesz przez „zaktualizuj odniesienie, jeśli chcemy”? Nie rozumiem, jak można byłoby rozgałęzić Projekt1 (co wydaje się pożądane za każdym razem, gdy rozgałęziasz Rozwiązanie2) bez rozgałęziania Rozwiązania1.
C. Dragon 76,

Zobacz moją szczegółową odpowiedź, szczególnie, aby NIE umieszczać rozwiązań Visual Studio w kontroli źródła.
Rob Williams

0

Aby dodać do problemu ze ścieżką względną:

Nie jestem pewien, czy to jest problem: po
prostu sprawdź Rozwiązanie1 / trunk w katalogu o nazwie „Rozwiązanie1”, tak samo jak Rozwiązanie2: celem „katalogów” reprezentujących gałęzie jest niewidoczne po zaimportowaniu do obszaru roboczego. W związku z tym możliwe są ścieżki względne między „rozwiązaniem1” (właściwie „rozwiązaniem1 / trunk”) a „rozwiązaniem2” (rozwiązaniem2 / trunk).


To bardzo łatwo by się zepsuło, zobacz moją szczegółową odpowiedź.
Rob Williams

0

RE: względna ścieżka i problem z udostępnionym plikiem -

Wygląda na to, że jest to specyficzne dla svn, ale nie stanowi to problemu. Jeszcze jedna osoba wspomniała już o oddzielnych repozytoriach i jest to prawdopodobnie najlepsze rozwiązanie, jakie przychodzi mi do głowy w przypadku, gdy masz różne projekty odnoszące się do dowolnych innych projektów. W przypadku, gdy nie masz udostępnionych plików, rozwiązanie OP (jak również wiele innych) będzie działać dobrze.

Nadal nad tym pracujemy i mam 3 różne wysiłki (różni klienci), które muszę teraz rozwiązać, ponieważ przejąłem konfigurowanie nieistniejącej lub słabej kontroli wersji.


Posiadanie projektów odwołujących się do innych projektów tworzy koszmar konserwacji, ponieważ zależności rosną wykładniczo, a odniesienia są BARDZO delikatne. Zobacz moją szczegółową odpowiedź.
Rob Williams,

0

Mam podobny układ, ale mój pień, gałęzie, metki na samej górze. A więc: / trunk / main, / trunk / utils, / branches / release / itp.

Ostatecznie okazało się to bardzo przydatne, gdy chcieliśmy wypróbować inne systemy kontroli wersji, ponieważ wiele narzędzi do tłumaczenia działało najlepiej z podstawowym układem SVN w podręczniku.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.