Przejdź do treści

Blog “Zakasane rękawy”

Jak narobić sobie (i innym) problemów w Git

Data publikacji:
Aktualizacja:

Teoria: w Git trudno jest coś zepsuć

Dzisiejszy temat może się wydać nieco bardziej techniczny od poprzednich, ale git stał się w ostatnich latach właściwie podstawowym narzędziem używanym w IT. Korzystamy z niego zarówno w firmach, jak i w projektach tworzonych “po godzinach”, o czym świadczy np. popularność GitHuba.

W tym artykule zakładam znajomość podstaw tego narzędzia, rozważania wychodzą trochę poza podstawy. Jeśli tak jest, to wiesz już pewnie że praca z gitem daje nam gwarancję, że raz scommitowany kod nie zostanie utracony.

Oczywiście są i tutaj wyjątki. Jeśli się uprzemy, to możemy przepisać historię gita i utracić naszą pracę. Możemy też na współdzielonym repozytorium, jeśli mamy do tego uprawnienia, nadpisać pracę innych osób. Wymaga to jednak nieco zachodu, a także wpisania w poleceniu flagi --force lub odhaczenia w GUI pola wyboru typu "wiem co robię". To powinno dać nam zawsze do myślenia i pozwolić na wycofanie się w porę z niecnego zamiaru.

Jeśli już jednak pracując w zespole zepsujemy coś w ten sposób, prawdopodobnie dowiemy się o tym w przeciągu 24 godzin od innej osoby. Przykładowo, jeśli złośliwie nadpiszemy historię dla gałęzi, to ktoś nie będzie mógł wypchnąć swoich zmian na tę gałąź (ale będzie miał lokalnie kopię całej pracy, więc dane nie zostaną utracone). Jeśli źle rozwiążemy konflikty, to kod się nie zbuduje albo dostrzeżemy to podczas testu po uruchomieniu aplikacji.

Są jednak pułapki, które nas dotykają po czasie

I jest to zły dotyk. Pewnych problemów na pierwszy rzut oka możemy nie zauważyć, ale z czasem mogą stać się kosztowne.

Pewne przyzwyczajenia w zespole mogą powodować że jakość naszego repozytorium z czasem się pogarsza. Oto dwa z nich, które widzę.

1. Commitowanie dużych plików binarnych

Prawdopodobnie większą częśc naszych repozytoriów stanowią rodzaju pliki tekstowe. Przez pliki tekstowe rozumiem takie, które w odróżnieniu od binarnych dają się otworzyć i sensownie edytować w notatniku. Pliki takie składają się z tekstu rozdzielonego znakami nowej linii, łatwo możemy je też automatycznymi narzędziami porównywać i wskazywać fragmenty które się różnią. Pliki binarne natomiast zawierają dane, dla których porównywanie danych "linia po linii" nie ma sensu. Są to na przykład obrazki, pliki wykonywalne, spakowane pliki, ikony.

Jeśli ta definicja wydaje Ci się nieścisła, masz rację. To rozróżnienie jest bardziej umowne. Systemy kontroli wersji używają heurystyk aby ocenić czy coś jest plikiem tekstowym, czy binarnym, bo muszą je traktować inaczej. Możemy im trochę pomóc, np. w git dodając podpowiedzi w pliku .gitattributes. Pewnie wszyscy mamy jednak wyrobioną pewną intuicję na temat tego, co jest plikiem tekstowym, a co binarnym i powinna nam ona na co dzień wystarczyć.

Pliki binarne w praktyce mają też pewną częstą cechę - są duże. Co to znaczy duże? Pomyślmy o przykładowych plikach, które można czasem znaleźć na repozytoriach git:

  • pliki Worda z dokumentacją biznesową,
  • pliki Excela z wymaganiami,
  • obrazki jpeg, png
  • pliki instalacyjne wtyczek Visual Studio potrzebnych do pracy z projektem,
  • programy (exe-ki, dll-ki) będące zależnościami dla naszej aplikacji.

Można by pewnie wymienić jeszcze trochę.

Nie posunąłbym się może do tak rygorystycznego stwierdzenia jak “Don't ever commit binary files to Git”, ale kierowany doświadczeniem zacząłem sam zwracać uwagę, aby ograniczać pliki binarne do minimum.

Pamiętajmy bowiem, że wszystko co commitujemy, zostaje w historii repozytorium już na zawsze. Jeśli więc na starcie projektu webowego dużo sobie prototypujemy i używamy do tego grafik w rozmiarze 4000 x 3000, a do tego często commitujemy zmiany jako "checkpointy" naszej pracy (co jest właściwie dobrą praktyką), to nasze repozytorium będzie szybko puchło.

Każda osoba, która w przyszłości ściągnie repozytorium, będzie musiała ściągnąć również te obrazki, choć w bieżącej wersji kodu może ich od dawna nie być. To nie tylko wolniejsza praca z gitem dla wszystkich członków zespołu, ale też więcej miejsca na dysku zajmowanego przez repozytorium (czasem wiele gigabajtów), oraz np. trudniejszy backup takich danych.

Na koniec, jeśli chcesz, to w ramach krótkiego warsztatu zerknij na folder projektu nad którym pracujesz najdłużej ;) Sprawdź ile miejsca na dysku zajmuje. Możesz potem zestawić tę liczbę z rekomendacją od firmy Atlassian:

Ideally, you should keep your repository size to between 100MB and 300MB. To give you some examples: Git itself is 222MB, Mercurial itself is 64MB, and Apache is 225MB. You can check out these open source repositories here: https://bitbucket.org/mirror/

2. Commitowanie haseł

Fakt, że repozytorium gita "nie zapomina" ma też swoje konsekwencje, jeśli zdarzy nam się wrzucić plik, który zawiera hasło (lub np. connection string do bazy danych).

Jedną z takich historii, zakończoną sporymi stratami finansowymi opisuje Niebezpiecznik.

Bitcoinowi kopacze stale skanują źródła na GitHubie w poszukiwaniu kluczy Amazonu, a kiedy je zdobywają zakładają za ich pomocą potężne instancje, które wykorzystują do kopania wirtualnej waluty na czyjś rachunek.

Jeśli chcesz zobaczyć jak łatwo znaleźć hasło w historii repozytorium, wpisz w wyszukiwarce commitów GitHub frazę "remove password" - to zawsze poprawia humor ;)

Pamiętajmy więc, aby przed commitem zawsze przejrzeć dokładnie wszystko co zmieniliśmy, plik po pliku i linia po linii. Jeśli już "mleko się wylało" i wcisnęliśmy przycisk "Commit", ale nie wypchnęliśmy jeszcze zmian na współdzielone repozytorium, to usuńmy lub zmodyfikujmy zmianę z hasłem, zamiast tworzyć kolejną usuwającą hasło (bo to nic nie da i obie będą dostępne w historii, jak na rys. 3).

Czy to koniec pułapek?

Zapewne nie. Może Ty masz jakieś doświadczenia z gitem, przez które musiałeś lub musiałaś się wstydzić, albo robić nadgodziny? ;-) Jeśli tak, to zachęcam do dzielenia się nimi w komentarzach - w roli przestrogi dla nas wszystkich. Dzięki za odwiedziny!

Komentarze