git-svn – pracuj lokalnie z git, synchronizuj się z SVN

Wszystkie projekty w mojej pracy są wersjonowane mocno na SVN. Ten system kontroli wersji ma już swoje lata i już dawno temu zaczął być wypierany przez gita. Niestety, u nas perspektyw na migrację nie ma w najbliższej przyszłości, więc od kilku lat korzystałem bezpośrednio z SVN.

Na początku niezbyt mi to przeszkadzało – najpierw się wdrażałem, potem zmieniłem zespół, potem zmiany wprowadzałem liniowo i nie było zapotrzebowania na “skakanie” pomiędzy zagadnieniami. Jedynie czasem trzeba było wybrać część zmian z wielu innych w tych samych plikach, ale mniej więcej w tym czasie odkryłem możliwości pary diff + patch, przez co wybrane zmiany można było łatwo scommitować gdzieś na boku bez zbędnego komentowania zmian, które wejść nie powinny.

Sytuacja zmieniła się radykalnie wraz ze zmianami w szeregach naszego biznesu. Coraz częściej wykonywaliśmy po kilka zagadnień “jednocześnie”, przestała mieć też znaczenie kolejność wykonywania zmian – czasem zagadnienia skończone jednego dnia musiały wejść na produkcję jeszcze w tym samym dniu, inne zaś musiały czekać tygodniami, a czasem nawet zostawały zaorane.

Miało to co najmniej trzy poważne konsekwencje:

  • wiecznie zapchane working copy: po roku takiej pracy miałem zawsze kilkadziesiąt zmienionych plików i efektywne przejrzenie diffa przed commitem było praktycznie niemożliwe, przez co często zdarzało się zapomnieć o jakimś pliku; nie muszę też pisać, że codzienny widok niewdrożonych zmian sprzed np. kilku tygodni ma katastrofalny wpływ na motywację,
  • utrudnione testy: zmiany bardzo często dotyczyły tych samych plików, codziennością było kilka zagadnień w tym samym module, co powodowało, że testowanie niektórych zmian było bezcelowe w oderwaniu od innych, zaś czasem sztucznie wstrzymywałem pracę nad dalszymi zmianami w oczekiwaniu na testy ze strony biznesu,
  • wieczny ból dupy przed wdrożeniami: po pewnym czasie nakładających się na siebie zmian było tyle, że diff i patch na boku musiał być używany hurtowo; ręczna edycja diffów bywa czasem utrudniona, co w połączeniu z wybieraniem zmian z kilkudziesięciu plików było szalenie czasochłonne; przygotowania do wdrożenia zaczęły być pasmem kombinowania.

Mniej więcej w tym samym czasie zacząłem podchodzić dużo poważniej do kwestii testowania oprogramowania, co wcale nie ułatwiało sytuacji. SVN był w takich sytuacjach po prostu bezbronny – jego branche w tak szybkim i zmiennym procesie rozwoju oprogramowania nie mają prawa bytu i są strasznie ciężkie. Zacząłem czytać coraz więcej o gicie.

Gita znałem jeszcze z czasów swojej freelancerki, jednak z racji tego, że pracowałem sam, to tak naprawdę go nie znałem. Nie korzystałem nawet aktywnie z branchów – wszystkie moje projekty z tamtego czasu to jedynie master, służący jako kopia zapasowa i archiwum zmian. Wiedziałem jednak, że możliwości są dużo większe, aż w końcu trafiłem na sposób pogodzenia SVN i git – projekt git-svn.

Po przejściu przez kilka tutoriali wiedziałem, że to będzie to. Git-svn pozwala stworzyć gitowe repozytorium na podstawie brancha z SVN, który będzie synchronizowany w dwie strony.

Użyłem więc git-svn do clone’a z SVN. Po kilkudziesięciu minutach mielenia (nasz projekt miał wtedy ponad 2,5k commitów) miałem już gotowe repo, które spatchowałem niescommitowanymi zmianami z kopii roboczej SVN, której dotąd używałem.

Zacząłem ostrożnie – dalej miałem mnóstwo niescommitowanych zmian, dalej nie używałem branchy, jednak git add –patch i selektywne dodawanie zmian do scommitowania w obrębie jednego pliku zrobił furorę – to był ten moment, w którym przestałem zaprzątać sobie głowę myśleniem o wtórnych problemach: czyli “jak tym razem scommitować zmiany wymieszane pomiędzy zagadnieniami?”.

Po miesiącu takiej pracy okazało się, że w zasadzie nie występują większe problemy. Dlaczego więc nie pójść o krok dalej? Tym krokiem było oczywiście przeniesienie zmian do osobnych gałęzi zgodnie z git flow. Dzięki temu rozwiązałem raz na zawsze problem zapchanego working copy (czy – w przypadku gita – indeksu).

Podaję materiały, które mogą się przydać każdemu znajdującemu się w sytuacji podobnej do mojej, a z których sam korzystałem:

8.1 Git and Other Systems – Git and Subversion

Effectively Using Git With Subversion

Na koniec moje protipy:

  • unikaj rebase na synchronizowanym z SVN branchu (przeważnie master), przepisanie historii commitów powoduje czasem zaburzenie liniowości historii, przez co synchronizacja się nie udaje; sam rozwiązuję to w ten sposób, że feature branche merge’uję do mastera z przełącznikiem –no-ff,
  • pamiętaj, że korzystając z git-svn wszelkie zmiany w lokalnych branchach nie są wypychane tak, jak przy “tradycyjnym” repozytorium gita, posiadasz więc prawdopodobnie jedyną kopię tych zmian – pamiętaj o wykonywaniu kopii zapasowych, w przypadku uszkodzenia lokalnego repozytorium możesz stracić wszystkie efekty swojej pracy.

Muszę też ostrzec potencjalnych użytkowników – spotkałem się z wieloma opiniami mówiącymi o tym, że git-svn tak bardzo usprawnia pracę, że jest pierwszym krokiem do całkowitego przejścia na gita w pracy. Sprawdziło się to i u mnie – narzędziem tym zaraziłem kolegę z zespołu. Czas na resztę. 😉