Inżynieria Oprogramowania

Transkrypt

Inżynieria Oprogramowania
Inżynieria Oprogramowania
Subversion – system zarządzania wersjami (konfiguracjami)
Narzędzie nr 1: TortoiseSVN
Narzędzie TortoiseSVN jest rozszerzeniem do Windowsa, które umożliwia pracę z repozytorium
bardzo „przezroczyście”. Użytkownik traktuje zarządzanie wersjami jako element naturalny
systemu, co ma tą zaletę, że uczy dobrych praktyk – nie tylko w programowaniu, ale również w
wersjonowaniu np. dokumentów.
Znakomita większość operacji jest dostępna z menu kontekstowego, tj. menu dostępnego po
naciśnięciu prawego przycisku myszy – najczęściej na pliku lub folderze.
Ćwiczenie 1.1. Checkout z repozytorium
1. Utworzyć katalog repo, np. w c:\temp\infXXXXX zamieniając XXXXX swoim numerem
indeksu. Po zajęciach oczywiście po sobie sprzątamy i usuwamy taki katalog.
2. Na katalogu repo wybrać z menu kontekstowego SVN Checkout…
3. Wypełnić okienko wstawiając URL:
https://ophelia.cs.put.poznan.pl/svn/io2009/infXXXXX/lab03
i wybrać przycisk OK.
4. Gdy pojawi się pytanie o użytkownika i hasło, wpisać otrzymane od prowadzącego dane.
5. Komunikat typu Completed oraz odpowiednia ikonka na folderze repo (po odświeżeniu)
informują nas, że operacja zakończyła się powodzeniem.
6. Sprawdzić, czy w repo pojawiły się katalogi branches, tags oraz trunk. Jest to skutek
używania zalecanej struktury repozytorium i ma znaczenie przy tworzeniu gałęzi (o tym
w części 3).
Ćwiczenie 1.2. Tworzenie folderów i zapis plików
1. W katalogu repo/trunk utworzyć katalog test. Nowopowstały folder nie będzie wyróżniony
żadnym symbolem, gdyż folder ten nie znajduje się jeszcze na serwerze, w repozytorium.
2. Na nowym folderze wybieramy TortoiseSVN/Add… i OK. Wskazany folder został oznaczony do
dodania (ale tylko lokalnie, ciągle nie ma go w repozytorium!).
3. Do założonego katalogu należy zapisać plik Fibonacci.java.
4. Z menu kontekstowego Fibonacci.java wybieramy TortoiseSVN/Add… i OK.
5. Zapis nowej wersji pliku na serwer można wykonać wybierając na katalogu test (lub repo
albo trunk) SVN Commit… W okienku należy wpisać komentarz do dodawanej wersji pliku,
np. „pierwsza wersja klasy”. I wybrać OK.
Ćwiczenie 1.3. Modyfikacja plików
1. Zasymulujemy modyfikację pliku nadpisując go zmienioną wersją (z pliku Fibonacci2.java,
zmieniając nazwę na Fibonacci.java).
2. Zmiana powinna zostać wykryta:
3. Wprowadzoną zmianę (wypisywanie 20 a nie 10 liczb) można zapisać na serwerze przy pomocy
operacji SVN Commit. W komentarzu wersji należy wpisać: „wypisywanie 20 liczb”.
Ćwiczenie 1.4. Wypisywanie logu zmian pliku
1. Na Fibonacci.java wybieramy TortoiseSVN/Show log
2. System wyświetli listę zmian, które są powiązane z danym plikiem.
Ćwiczenie 1.5. Różnice
1. Zmodyfikuj plik Fibonacci.java zmieniając
Created on 2004-10-04
na
Created on 04-10-2004
2. Na „naszym” Fibonaccim wybieramy TortoiseSVN/Diff. Pokaże się wówczas okienko, które
obrazuje, jakie są różnice wersji lokalnej w stosunku do wersji ostatnio pobranej z repozytorium.
Ćwiczenie 1.6. Cofnięcie do wersji z repozytorium
1. Powiedzmy, że wprowadzone zmiany były niepoprawne i chcielibyśmy pobrać poprzednią
wersję.
2. Klikamy prawym na naszym pliczku i wybieramy TortoiseSVN/Revert…
3. Wyświetlając zawartość pliku zobaczymy poprzednią wersję: Created on 2004-10-04.
Pamiętajmy, że powrót do poprzedniej wersji nie oznacza uaktualnienia do najnowszej wersji!
Operacja cofnięcia jest operacją lokalną, nie nawiązuje kontaktu z repozytorium.
Ćwiczenie 1.7. Symulowanie konfliktów
Konflikt w Subversion może się pojawić, jeżeli dwóch użytkowników pobrało w pewnym czasie
określoną wersję danego pliku, po czym obaj dokonali w nim zmian i dokonują operacji Commit w
tej samej linii w pliku. Pierwszy programista dokona operacji bez problemu, jednak w przypadku
drugiego zostanie wykryta sytuacja niezgodności wersji na podstawie której dokonywał on zmian z
wersją aktualnie znajdującą się w Subversion (dopiero co zapisaną przez pierwszego programistę).
Sytuacja konfliktowa wymaga automatycznego lub ręcznego połączenia zmian wprowadzonych
przez obu programistów.
Do zasymulowania konfliktu potrzebny będzie drugi katalog roboczy.
1. Utwórzmy c:\temp\infXXXXX\repo2.
2. Pobierzmy repozytorium tak jak opisano w Ćwiczeniu 1.1.
3. Zmieńmy zawartość c:\temp\infXXXXX\repo2\trunk\temp\Fibonacci.java
zastępując go treścią pliku Fibonacci3a.java. Po tej zmianie można wykonać
TortoiseSVN/Diff, żeby zobaczyć, jakie zmiany wprowadzono w pliku.
4. Zapiszmy nową wersję do repozytorium SVN nadając następujący opis: „poprawka do liczby
liczb w dokumentacji”.
5. Wracamy do pracy w katalogu c:\temp\infXXXXX\repo.
6. Znajduje się tam już teraz nieaktualna wersja, o czym jednak nie wie programista nad nią
pracujący.
7. Zmieńmy zawartość c:\temp\infXXXXX\repo\trunk\temp\Fibonacci.java zastępując
ją treścią z pliku Fibonacci3b.java. Po tej zmianie można wykonać TortoiseSVN/Diff, żeby
zobaczyć, jakie zmiany wprowadzono w pliku.
8. Przy próbie Commita zmienionego pliku wyświetlony zostanie komunikat o błędzie: nie można
utworzyć nowej wersji na serwerze, ponieważ mogłoby to usunąć zmiany, które już tam są, a nie
są uwzględnione w naszej kopii lokalnej.
Ćwiczenie 1.8. Rozwiązywanie konfliktów
1. W celu rozwiązania konfliktu i połączenia zmian wprowadzonych w lokalnej wersji pliku i
nowej wersji z repozytorium (tj. wprowadzonej w repo2) należy wywołać operację SVN
Update… z menu kontekstowego pliku Fibonacci.java.
2. W wyniku operacji zostanie dokonana operacja połączenia dwóch wersji plików – lokalnej i
najnowszej w repozytorium – tam, gdzie się da automatycznie. Tam gdzie to będzie niemożliwe
zostanie to pozostawione do rozstrzygnięcia użytkownikowi.
3. W katalogu pojawią się pliki (z innymi rozszerzeniami wskazującymi na faktyczne numery
wersji):
Fibonacci.java.mine – kopia lokalna w momencie łączenia,
Fibonacci.java.213 – wersja z repozytorium, w stosunku do której były dokonywane
zmiany lokalne (213),
Fibonacci.java.214 – najnowsza wersja z repozytorium (214).
Sam plik Fibonacci.java zawierać będzie zawartość uzyskaną przez automatyczne
połączenie wersji (tam gdzie zmienione sekcje się nie nakładały) oraz fragmenty pozostawione
do ręcznego zsynchronizowania.
4. Należy otworzyć plik Fibonacci.java do edycji. Jak widać z jego zawartości dokonane
zostało automatyczne połączenie części zmian. Najważniejszy jest fragment dotyczący
konfliktowej zmodyfikowanej w obu wersjach linii:
<<<<<<< .mine
* Created on 2004-11-24
=======
* Created on 2004-11-23
>>>>>>> .r214
Zawiera on zawartość zmodyfikowanej linii z lokalnej kopii pliku (powyżej ======) oraz
konfliktującej wersji 214 z repozytorium (poniżej ======).
5. Rozwiązanie konfliktu sprowadza się do wyboru wersji linii, która ma zostać użyta. Zastępujemy
zatem powyższy fragment, pojedynczą linią:
* Created on listopad 2004
oraz wybierając operację TortoiseSVN/Resolved. Plik uzyskuje status zmienionego lokalnie, bez
konfliktów.
6. Możemy sprawdzić, że wszystko jest OK wybierając TortoiseSVN/Diff.
7. Dokonujemy operacji Commit wpisując odpowiedni komentarz.
Narzędzie nr 2: Eclipse
Eclipse sam w sobie nie jest oczywiście narzędziem do zarządzania wersjami, jednak od początku
w jego projekcie przewidziana jest możliwość „wpięcia” plug-inów do komunikowania się z
systemami zarządzania wersjami.
Standardowo w Eclipse 3.3 dostarczane są wtyczki do obsługi repozytoriów CVS (od wersji 3.4
również SVN). Aby korzystać z Subversion należy doinstalować wtyczki Subversive albo
Subclipse. Na zajęciach korzystamy z tego pierwszego.
Poniższe ćwiczenia polegają z grubsza na tym samym co już przeprowadzone z narzędziem
TortoiseSVN, więc ich opis jest bardziej uproszczony. Tam gdzie to istotne zaznaczono specyfikę
Eclipse'a. Warto pamiętać, że większość operacji będzie wyglądała podobnie podczas pracy z
innymi wtyczkami (Subclipse, praca z CVS), dzięki temu, że mechanizm zarządzania wersjami jest
elementem platformy Eclipse.
Ćwiczenie 2.1. Utworzenie projektu w repozytorium
1. W Eclipse utworzyć nowy projekt Java: File/New/Project... i Java/Java Project.
2. Podać nazwę, np. test-svn; upewnić się, że ustawienia rozdziału plików .java i .class są
takie jak poniżej:
3. Kliknąć Finish.
4. Z menu kontekstowego projektu wybrać Team/Share project...
5. Wybieramy typ repozytorium SVN
6. Dalej podajemy URL i dane użytkownika (patrz ćwiczenie 1.1.).
Uwaga: Proszę podać dokładnie taki URL jak w ćwiczeniu 1.1.
7. Po poprzednim kroku mamy utworzoną informację o repozytorium. Może w nim być wiele
projektów. Dlatego na następnym ekranie podajemy katalog, w którym ma być umieszczony
nasz projekt, w ramach zdefiniowanego repozytorium.
Możliwych jest wiele schematów układu katalogów projektów w repozytorium. Proszę użyć
ustawień jak na rysunku poniżej; skutkują one strukturą uwzględniającą gałęzie i tagi na
poziomie repozytorium (czyli w lab03, a poniżej projektu test-svn).
8. Po wciśnięciu Finish, Eclipse poprosi o podanie komentarza do Commita. Podajemy np. „import
projektu Eclipse”.
Ciekawostką jest fakt, że jest to drugi commit, zawartości projektu. Pierwszy został wykonany
automatycznie i polegał na utworzeniu tylko folderu projektu w SVN – najprostszy sposób, aby
wykluczyć istnienie w repozytorium projektu o podanej nazwie.
9. Obecnie projekt jest obecny w repozytorium, oraz lokalnie. Kopia lokalna jest „standardową”
kopią SVN, o czym można się przekonać wykonując dowolne operacje z poziomu TortoiseSVN
na folderze projektu Eclipse.
Oznacza to np. że dodając do projektu pliki z poziomu TortoiseSVN nie ryzykujemy
niespójności repozytorium – Eclipse działa tutaj jak „nakładka” na projekt, podobnie jak
TortoiseSVN jako „nakładka” na system plików.
Ćwiczenie 2.2. Dodawanie plików
1. Z poziomu Windowsa dodajemy do folderu src plik Fibonacci.java.
2. W Eclipse odświeżamy projekt (Refresh w menu kontekstowym projektu).
3. Rozwijając drzewko do poziomu dodanego pliku widzimy obok ikonkę ze znakiem zapytania.
Oznacza ona, że plik jest nieznany z punktu widzenia repozytorium, tzn. został dodany lokalnie,
ale w repozytorium go nie ma.
Zwróćmy też uwagę na symbol > obok projektu. Oznacza on, że w tym projekcie są jakieś
rozbieżności pomiędzy repozytorium a wersją lokalną (najczęściej zmodyfikowane lokalnie
pliki).
4. Na projekcie wybieramy Team/Synchronize with Repository. Perspektywa, która się pokazała
jest podstawową z punktu widzenia operacji na kopii lokalnej i repozytorium.
5. Widzimy, że Eclipse wykonuje automatycznie niektóre operacje, np. oznaczył do dodania plik
Fibonacci.java.
6. Na projekcie wybieramy z menu kontekstowego Commit... i wpisujemy komentarz, np. „dodano
plik Fibonacci.java”.
7. Eclipse informuje nas, że nie ma więcej zmian w stosunku do repozytorium; podobnie w
perspektywie Java, nie widać oznaczań zmian lokalnych na ikonach w drzewku.
Ćwiczenie 2.3. Pobieranie projektu z repozytorium
Teraz spróbujemy pobrać projekt z repozytorium. Żeby było to skuteczne na projekcie wybieramy z
menu kontekstowego Delete i zaznaczamy opcję Also delete contents under '...'.
1. Wybieramy z File/Import... i SVN/Projects from SVN.
2. Wybieramy nasz profil repozytorium z listy.
3. Zaznaczamy na liście folder trunk/test-svn i klikamy Finish.
4. Potwierdzamy checkout zasobu jako osobny projekt.
5. Sprawdzamy, czy „w środku” jest wszystko tak, jak przed rozpoczęciem ćwiczenia.
Ćwiczenie 2.4. Modyfikacja i różnice w plikach
1. Z poziomu Windows podmieniamy zawartość Fibonacci.java (patrz ćwiczenie 1.3., krok 1.).
2. Odświeżamy w Eclipse projekt i przechodzimy do perspektywy Team Synchronizing.
3. Widzimy, że Eclipse wykrył zmianę w pliku: strzałka „w prawo” oznacza chęć Eclipse'a do
wysłania zmian do repozytorium.
4. Aby przekonać się, co się zmieniło, dwukrotnie klikamy na zmieniony plik. W obszarze edytora
otworzy się nowe okno, gdzie zaprezentowane są zmiany pomiędzy wersją lokalną a oryginalną
z repozytorium.
5. Aby wysłać zmiany do repozytorium na projekcie wybieramy Commit.
Ćwiczenie 2.5. Symulowanie konfliktów
Podobnie jak w ćwiczeniu 1.7., do symulacji konfliktu potrzebujemy drugiej, równoległej kopii
lokalnej.
1. Utwórzmy c:\temp\infXXXXX\repo3.
2. Pobierzmy repozytorium tak jak opisano w Ćwiczeniu 1.1.
3. Zmieńmy zawartość c:\temp\infXXXXX\repo3\trunk\testsvn\src\Fibonacci.java zastępując go treścią pliku Fibonacci3a.java. Po tej zmianie
można wykonać TortoiseSVN/Diff, żeby zobaczyć, jakie zmiany wprowadzono w pliku.
4. Zapiszmy nową wersję do repozytorium SVN nadając następujący opis: „poprawka do liczby
liczb w dokumentacji”.
5. Wracamy do pracy w katalogu projektu Eclipse.
6. Znajduje się tam już teraz nieaktualna wersja, o czym jednak nie wie programista nad nią
pracujący.
7. Zmieńmy zawartość pliku Fibonacci.java zastępując ją treścią z pliku Fibonacci3b.java.
Odświeżamy projekt w Eclipse.
Po tej zmianie można podejrzeć (jak w ćwiczeniu 2.4.), jakich dokonano zmian lokalnych na tym
pliku.
8. Przy próbie synchronizacji (przycisk Synchronize SVN w perspektywie Team Synchronizing)
status pliku zmieni się na „konfliktowy” (czerwony kolor strzałek na ikonie).
Ćwiczenie 2.6. Rozwiązywanie konfliktów.
1. Aby zobaczyć konflikty i je rozwiązać, dwukrotnie klikamy na plik Fibonacci.java (ciągle w
perspektywie synchronizacji).
Widzimy, że plik lokalnie zmieniony i najnowsza wersja z repozytorium zostały połączone.
Wszystkie lokalne zmiany są prezentowane tak, jak widzieliśmy to podczas oglądania różnic w
ćwiczeniu 2.4.
Konfliktowe linie zostały zaznaczone na czerwono. Wymagają one podjęcia decyzji, jak ma
wyglądać w tych miejscach nowa wersja pliku lokalnego, którą będzie można „wrzucić” do
repozytorium.
2. Proszę zapoznać się z przyciskami nad panelem różnic, bez obaw klikając:
Show/Hide Ancestor pane – oprócz dwóch plików pokazany zostanie trzeci, który jest
wspólnym „przodkiem” obu zmian,
Select Next/Previous Change – pozwala na nawigowanie pomiędzy zmianami. Podświetlane są
zmiany na poziomie poszczególnych znaków, co jest często dużą pomocą: czasem trudno
stwierdzić „na oko” czym różnią się dwie linie.
3. Ponieważ chcemy wprowadzić w wierszu konfliktowym inny tekst, niż dostępny w obu
wersjach, ustawiamy tam kursor po stronie Local File (lewy panel) i wpisujemy
* Created on listopad 2004
po czym zapisujemy plik (Ctrl+S).
4. Dajemy znać Eclipse'owi, żeby się już nie martwił i że rozwiązaliśmy wszystkie konflikty:
wybieramy Marked as Merged z menu kontekstowego na kłopotliwym pliku.
5. Status pliku zmieni się z „konfliktowego” na zmodyfikowany lokalnie. Możemy więc zapisać
zmiany w repozytorium (ćwiczenie 2.4., kroki od 3.).
Narzędzie 3: Linia poleceń
Historycznie patrząc, jest to pierwszy i referencyjny klient do SVN, rozwijany razem z serwerem.
Większość operacji, które można wykonać z poziomu GUI (Eclipse, TortoiseSVN) można też
wykonać z poziomu linii poleceń, jednak wymaga to większej liczby operacji i „stuknięć klawisze”.
Aby wywołać klienta należy wpisać w konsoli
svn <komenda>
gdzie <komenda> jest operacją, jaką chcemy wykonać. Zależnie od operacji może być wymagane
podanie dodatkowych argumentów. Można się o tym dowiedzieć – co będzie użyteczne w dalszych
ćwiczeniach – z pomocy uzyskanej poleceniem svn help <komenda>.
Ćwiczenie 3.1: Checkout z repozytorium
Polecenie (jedna linia!)
svn checkout
https://ophelia.cs.put.poznan.pl/svn/io2009/infXXXXX/lab03 repo4
pobierze zawartość repozytorium do katalogu repo4.
Ćwiczenie 3.2: Dodawanie plików
Należy przejść do katalogu repo4/trunk.
1. Wykonać komendę SVN status. Nie powinno być żadnego komunikatu, co oznacza, że kopia
lokalna jest „czysta”, bez zmian lokalnych.
2. Należy utworzyć nowy katalog i plik. Ponowna komenda status pokaże obok nowych elementów
znak '?', co oznacza, że nie jest on znany dla SVN.
3. Wykonujemy komendę add. Ponowne sprawdzenie statusu pokazuje obok nowych elementów
znak 'A', co wskazuje na oznaczenie elementów do dodania.
4. Należy zatwierdzić zmiany w repozytorium komendą commit.
5. Status katalogu powinien być „czysty”, jak w punkcie 1.
Ćwiczenie 3.3: Tworzenie gałęzi
W dowolnym miejscu rozwoju kodu możemy podjąć decyzję o utworzeniu gałęzi: alternatywnej
linii rozwoju projektu.
W SVN nie istnieje pojęcie gałęzi jako element architektury. Zamiast tego używa się mechanizmu
„taniej kopii” i umownej struktury repozytorium.
Taką umową są trzy katalogi o specjalnych nazwach, położone obok siebie:
trunk – tutaj umieszczane są „zwykłe” zmiany. Zawartość tego katalogu to najczęściej główna linia
rozwoju projektu;
branches – kiedy uznamy, że potrzebna jest dodatkowa gałąź (np. celem stabilizacji wersji do
wydania na rynek, bez konieczności zwalniania tempa rozwoju trunka), tutaj wykonujemy kopię
trunka;
tags – kiedy uznamy, że jakiś moment (tj. wersja repozytorium) jest godna uwagi (np. stabilizowana
gałąź jest wydawana na rynek), tutaj wykonujemy kopię z gałęzi (najczęściej).
Powyżej sporo pisano o kopiach. Tak jest, ponieważ kopiowanie jest „tanie” w Subversion i jest
często używane. Kopia zasobu w SVN podobna jest do linka w systemie Linux; stanowi ona tylko
oznaczenie, z którego miejsca w której wersji repozytorium pochodzi kopia.
1. Posłuchać co prowadzący może mieć do powiedzenia na temat kopii, gałęzi i tagów.
2. Wykonać kopię najnowszej wersji repozytorium do nowej gałęzi (proszę zauważyć, że
kopiowanie jest tylko w repozytorium, bez udziału kopii lokalnej – jest to dużo wydajniejsze niż
kopiowanie do kopii lokalnej i z powrotem):
svn copy https://ophelia/svn/io2009/infXXXXX/lab03/trunk
https://ophelia/svn/io2009/infXXXXX/lab03/branches/stable-01
3. Pobrać wersję gałęzi do osobnego katalogu, np. repo5 (jedna linia!):
svn checkout
https://ophelia/svn/io2009/infXXXXX/lab03/branches/stable-01
C:\temp\infXXXXX\repo5
4. Wprowadzić zmiany w gałęzi (tj. w repo5) i wrzucić je do repozytorium.
5. Zauważmy, że po aktualizacji kopii roboczej z trunka (tj. w repo4) komendą update nic się nie
zmieniło (bo jest to zupełnie inny podkatalog w repozytorium: kopia wykonana przez copy
zaczyna „żyć własnym życiem”).
6. Czasami jednak chcemy przenieść część zmian z gałęzi do trunka (np. dokonane poprawki
błędów). Służy do tego komenda merge, na której przećwiczenie nie mamy niestety czasu...
Odpowiednia komenda, wykonana w repo4, która przeniesie naszą ostatnią zmianę z brancha
do trunka miałaby postać:
svn merge -r X:Y
https://ophelia/svn/io2009/infXXXXX/lab03/branches/stable-01
gdzie X = Y-1, a Y jest wersją, którą uzyskaliśmy po poprzednim commicie.