git cherry-pick – Izolowanie trwałych lokalnych zmian od głównego brancha

Artykuł opisuje sposoby które działają tylko w Rozproszonych Systemach Kontroli Wersji (np Git).

Opis problemu

Implementujemy funkcję, którą można testować tylko na interfejsie użytkownika. Od uruchomienia aplikacji do pojawienia się w oknie które testujemy mija za każdym razem 2 minuty (które spędzamy klikając w ciągle te same przyciski, czekająć na ciągle te same loadery, etc). Aby sobie ułatwić pracę chcę zrobić w kodzie pewien skrót aby od razu po odpaleniu być w interesującym mnie miejscu. (Może również chodzić o zablokowanie jakiejść synchronizacji trwającej kilka minut.)

Kod i jego optymalizacja (hack)

Skupię się na tym drugim przypadku (czasochłonna synchronizacja). Wydaje mi się prostszy do opisania w kodzie opisać.

Tak wygląda kod produkcyjny:

public class SynchronizationServiceMock
{
    public IEnumerable<string> GetItemsFromFullSynchronization()
    {
        // Check current items
        // Download new and changed items
        // Make some diffs on data
        // etc
        return new[] {"ala", "ma", "kota"};
    }
}

A tak wygląda nasz lokalny hack (a właściwie improvement) dzięki któremu oszczędzamy czas i nerwy:

public class SynchronizationServiceMock
{
    public IEnumerable<string> GetItemsFromFullSynchronization()
    {
        return Enumerable.Empty<string>();

        // Check current items
        // Download new and changed items
        // Make some diffs on data
        // etc
        return new[] {"ala", "ma", "kota"};
    }
}

Różna między tymi commitami wygląda więc tak:
git diff for local improvement

UWAGA: nic nie PUSHujemy, w większości to co pisuję odbywa się w naszym lokalnym repozytorium!

Utworzenie brancha wskazującego na specjalny commit

Zanim zaczniemy implementować konkrety zrobimy sobie brancha (może to też być stash) w tym właśnie miejscu i nazwiemy go without-full-synchronization

git branch without-full-synchronization

Aktualnie nasza historia wygląda tak:
history with only Test synchronization commit

Implementujemy taska, który składa sie z kilku commitów i po wszystkim historia wygląda tak:
Implemnt new feature on top of test synchronization commit

Sprzątamy przed synchronizacją z centralą

Task gotowy jesteśmy zadowoleni. Trzeba teraz wypushować naszą lokalna historie do centralnego repozytorium, tak żeby nie wrzucic naszego TESTowego commita.

Robimy to poprzez funkcjonalność git-rebase-interactive (opisuję jak to zrobić z Source Tree). Po tym kroku historia wyglada:

history without TEST synchronization commit

Teraz możeby PUSHować naszą historie do centralnego repo. Gdy to zrobimy i wracamy do pracy nad następnym taskiem to najpierw wrzucamy nasz ułatwiający pracę commit:

Powrót specjalnego commita do naszego kodu

git cherry-pick without-full-synchronization

Historia wyglądać będzie tak i znowu możemy szybko klepać i odpalać nowy kod:

TEST synchronization commit on top of completed feature

Inne zastosowania

Aktualnie pracuję w środowisku Xamarin. Odpalam kod czasem w Visual Studio, czasem w Xamarin Studio na Windows a czasem w Xamarin Studio na Macu. Niestety żeby otworzyć w Xamarin trzeba zmienić w pewien sposób wszystkie pliki .csproj, a zmiany tej nie chce wrzucać do głownego kodu bo wtedy są problemy z VS. (Może ten problem można rozwiązać inaczej ale o tym nie wiemy jeszcze. Git udostępnia mechanizm dzięki któremu możemy w ten sposób pracować, aż do czasu wymyślenia czegoś lepszego.)

Advertisements
Ten wpis został opublikowany w kategorii Programowanie i oznaczony tagami , , , . Dodaj zakładkę do bezpośredniego odnośnika.