Niezbędnik Juniora: Git — kontrola wersji

By 2 January 2016 February 6th, 2017 Niezbędnik Juniora

Dzisi­aj nauczysz się korzys­tać z Gita — sys­te­mu kon­troli wer­sji, który stał się de fac­to stan­dar­d­em na rynku.Git to rozpros­zony sys­tem kon­troli wer­sji (co to dokład­nie znaczy, powiemy sobie za moment), u którego pod­staw leżą bard­zo proste założe­nia. To jest jed­nak jego potęgą — elasty­czność oraz kil­ka spry­t­nych pomysłów spowodowała że pow­stało narzędzie proste w uży­ciu, pasu­jące zarówno do prostych pro­jek­tów jak i ogrom­nych przed­sięwz­ięć (jak np. jądro sys­te­mu lin­ux).

Git jest prak­ty­cznie wyma­ganą kom­pe­tencją w wielu fir­ma­ch i od tego momen­tu rozwiąza­nia naszych lekcji oraz dodatkowe mate­ri­ały będziemy pub­likować właśnie w ten sposób.

Podstawowe pojęcia

Zan­im prze­jdziemy do mer­i­tum, wyjaśni­jmy pod­sta­wowe poję­cia i skró­ty, których będziemy używać.

  • SCM — to akro­n­im od Source Code Man­age­ment, czyli dosłown­ie kon­tro­la kodu (w języku pol­skim funkcjonu­je określe­nie sys­tem kon­troli wer­sji); jest to sys­tem który pozwala na archi­wiz­owanie i śledze­nie zmi­an w kodzie, dzię­ki czemu może­my cofać się w his­torii lub pode­jrzeć, kto był autorem konkret­nej zmiany
  • Repozy­to­ri­um — ‘kon­tener’ na określony zbiór kodu, najczęś­ciej jeden pro­jekt; repozy­to­ri­um pozwala grupować kod i zmi­any, dzię­ki czemu może­my przeglą­dać wszys­tkie zmi­any wyko­nane w ramach jed­nego repozy­to­ri­um, przyz­nawać uprawnienia do repozy­toriów oraz pobier­ać / kopi­ować je
  • Com­mit (lub rewiz­ja) — jest to pro­ces ‘wysła­nia’ na repozy­to­ri­um określonych zmi­an w kodzie — jeśli pobierasz kod z repozy­to­ri­um, następ­nie dokonu­jesz mody­fikacji i wysyłasz te zmi­any z powrotem do repozy­to­ri­um, pro­ces ten nosi nazwę com­mi­towa­nia, a same zmi­any wysłane razem nazy­wamy com­mitem lub rewizją
  • pull / push — odpowied­nio pobranie i wysłanie zmi­an (jed­nego lub wielu com­mitów) z/do innego repozytorium
  • diff — (ang. różni­ca) — jest to różni­ca pomiędzy różny­mi rewiz­ja­mi — dzię­ki temu może­my zobaczyć, które frag­men­ty uległy zmi­an­ie oraz w jaki sposób; pozwala to także zop­ty­mal­i­zować trans­fer danych pomiędzy repozytoriami
  • fork — kopia repozy­to­ri­um; szczegól­nie pop­u­larne w przy­pad­ku pro­jek­tów open-source, dzię­ki czemu może­my sko­pi­ować cały pro­jekt i rozwi­jać go nieza­leżnie (np. dopa­sowu­jąc do naszych potrzeb)
  • branch — odgałęzie­nie, wer­s­ja wewnątrz repozy­to­ri­um; branche pozwala­ją na prace wielu osobom równocześnie, bez ciągłego wchodzenia sobie w drogę i nad­pisy­wa­nia zmi­an — każdy może pra­cow­ać na swoim branchu, dopiero po zakończe­niu pra­cy łącząc zmi­any z inny­mi i rozwiązu­jąc problemy
  • merge — połącze­nie wielu zmi­an z różnych źródeł, które może skutkować niekom­paty­bil­ny­mi zmi­ana­mi wyma­ga­ją­cy­mi ręcznych mody­fikacji; merge pozwala łączyć prace wykony­wane w różnych obszarach, które mogą się zazębi­ać, w jed­ną całość w sposób kon­trolowany i świadomy

Tyle definicji — na ten moment mogą one brzmieć abstrak­cyjnie, ale już za chwile wytłu­maczymy sobie o co dokład­nie chodzi.

Klient Git

Pod­czas tego tuto­ri­alu będziemy korzys­tać z graficznego klien­ta Git o nazwie Smart Git — jest on bezpłat­ny do użytku pry­wat­nego, i spośród przetestowanych przez nas rozwiązań spisał się najlepiej. Obo­je uży­wamy go w pra­cy i pry­wat­nie :) Oczy­wiś­cie Gita moż­na uży­wać także z kon­soli lub za pomocą bib­liotek takich jak JGit — na początek pole­camy jed­nak coś prostszego ;)

Dlaczego Smart­Git? Z kilku powodów, przede wszys­tkim nigdy nas nie zaw­iódł (niedzi­ała­ją­ca funkcjon­al­ność, reklamy, blokowane funkc­je, brak aktu­al­iza­cji itp). Jego inter­fe­js jest prze­jrzysty, etyki­ety przy­cisków naw­iązu­ją do pole­ceń git, które wykonu­ją (co jest bard­zo pomoc­ne, jeśli szukasz jak zro­bić coś w gicie ogól­nie — możesz to łat­wo prze­nieść do klien­ta), a graficzne kon­trol­ki (np. his­to­ria, czy różnice pomiędzy wer­s­ja­mi) są czytelne, jasne i przy­jazne. Dodatkowo dzi­ała na każdym sys­temie, z którego musimy lub chce­my korzys­tać. Wady to oczy­wiś­cie konieczność kupi­enia licencji, aby uży­wać w wer­sji komer­cyjnej — z drugiej strony cena zde­cy­dowanie nie jest wygórowana i w naszej opinii pro­dukt wart jest swo­jej ceny. Licenc­ja jest też dla devel­opera, a nie insta­lacji — dzię­ki temu jed­nej licencji możesz uży­wać w pra­cy i w domu. Pro­gram ten inte­gru­je się także z GitHub’em, co także będzie pomocne.

Pobierz Smart Git

Inne aplikacje

Oczy­wiś­cie ist­nieje mnóst­wo innych, mniej lub bardziej rozbu­dowanych klien­tów GIT. Pomi­mo, że ten mini-kurs opiera się o Smart­Git, praw­ie wszys­tkie pro­gramy ofer­u­ją tą samą funkcjon­al­ność — układ okien może być inny, nazwa funkcji w menu, ale możli­woś­ci pozosta­ją te same. Podob­nie jak ze środowiskiem IDE — jedyny słuszny wybór to taki, który jest dla Ciebie wygod­ny i przy­jem­ny w uży­ciu.  Na ofic­jal­nej stron­ie Git’a zna­jdziesz lin­ki do różnych klien­tów — komer­cyjnych oraz nie. Wybier­a­jąc klien­ta pomyśl też o swo­jej pra­cy — o ile nie wykupisz licencji komer­cyjnej lub licenc­ja bezpośred­nio na to nie zezwala, najpraw­dopodob­niej pro­gra­mu nie będziesz mogła uży­wać w fir­mie. To ważne pod kątem przyzwycza­ja­nia się do narzędzia i ‘intu­icyjnej’ obsługi.

Miej też na uwadze, że zarówno Eclipse jak i Intel­liJ IDEA posi­a­da funkcjon­al­noś­ci związane z obsługą Git — niek­tórzy devel­op­erzy korzys­ta­ją tylko z nich, dla nas zewnętrza aplikac­ja okaza­ła się wygod­niejsza w uży­ciu i obo­je korzys­tamy z klien­tów graficznych poza IDE.

Hosting repozytorium Git

W tym wypad­ku sko­rzys­tamy z plat­formy GitHub — jed­nej z pier­wszych i zde­cy­dowanie najpop­u­larniejszej. Moż­na w niej bezpłat­nie założyć kon­to oraz — o ile nie chce­my ukryć naszego repozy­to­ri­um — moż­na także bezpłat­nie prze­chowywać tam swo­je projekty.

Pamię­taj tylko, że Twój pro­fil na GitHub to także Two­ja wiz­ytówka jako pro­gramisty — o ile nie ukry­jesz repozy­to­ri­um, każdy może je znaleźć i obe­jrzeć. Jest to jed­na z lep­szych form wery­fikacji kom­pe­tencji przez potenc­jal­nych pra­co­daw­ców — dlat­ego pamię­taj aby utrzymy­wać tam porządek i wysyłać kod, którego się nie pow­sty­dzisz :) Oczy­wiś­cie wszys­tko moż­na później popraw­ić, o ile się o tym pamięta ;)

Inne opcje

Na rynku ist­nieje masa alter­natyw, zarówno bezpłat­nych jak i płat­nych, ale to GitHub jest plat­for­mą częs­to wybier­aną przez firmy, oraz do tej pory najsta­bil­niejszą. Pon­ad­to nie próbu­je być ‘plat­for­mą do wszys­tkiego’ dzię­ki czemu inter­fe­js jest prze­jrzysty i nie gubi. Szczegól­nie pod­czas nau­ki jest to ważne, aby narzędzia poma­gały ćwiczyć zdobytą wiedzę, a nie stanow­iły łamigłówek do rozwiązy­wa­nia za każdym razem.

Jeśli jesteś ciekawa innych plat­form, sprawdź np. bitbucket.org czy gitlab.com

Zanim zaczniemy

Przed rozpoczę­ciem pra­cy upewnij się, że masz zain­stalowanego klien­ta Git (np. wspom­ni­any wyżej Smart Git) oraz masz założone kon­to w repozy­to­ri­um, np. GitHub (choć nie jest to stricte konieczne, zale­camy abyś posi­adała kon­to w celu przetestowa­nia wszys­t­kich pod­sta­wowych opcji).

Jeśli obie rzeczy masz gotowe, to zaczynamy!

Tworzenie nowego repozytorium

Tą lekc­je zaczniemy od utworzenia nowego repozy­to­ri­um. Repozy­to­ri­um to miejsce, w którym będzie prze­chowywany Twój kod.

Git jako narzędzie jest zde­cen­tral­i­zowany, co oznacza że nie ma ‘cen­tral­nego’ repozy­to­ri­um z definicji, a jedynie pow­iązane ze sobą, ale zarządzane odd­ziel­nie repozy­to­ria. Oznacza to tyle, że na Twoim kom­put­erze także będzie pełno­prawne repozy­to­ri­um Git (które ktoś może w teorii uży­wać tak jak Ty uży­jesz GitHub’a), ale będzie ono zaw­ier­ało infor­ma­cję o tzw. upstream repos­i­to­ry — czyli repozy­to­ri­um ‘nadrzęd­nym’, w naszym przy­pad­ku będzie to po pros­tu utwor­zone na GitHu­bie. O ile Git pozwala tego nie wyma­ga, więk­szość devel­op­erów pracu­je z nim tak, jak­by był to sys­tem cen­tral­ny — jed­no repozy­to­ri­um w ser­wisie GitHub czy podob­nym służy za wspólne miejsce dla wszys­t­kich pro­gramistów, z którego pobier­a­ją zmi­any innych i wysyła­ją swo­je zmiany.

W sytu­acji kiedy mamy repozy­to­ri­um nadrzędne, pier­wszym krok­iem jest utworze­nie nowego repozy­to­ri­um nadrzęd­nego, na ser­w­er­ach zdalnych.

Tworzenie repozytorium w serwisie GitHub

Po zal­o­gowa­niu w ser­wisie GitHub.com przy­cis­ki u góry pozwala­ją łat­wo prze­jść do opisu istot­nych ele­men­tów aplikacji. Zachę­camy do zapoz­na­nia się z tymi mate­ri­ała­mi, zna­jdziesz tam wiele ciekawych wskazówek i porad jak korzys­tać w sposób efektywny.

Aby utworzyć repozy­to­ri­um, w prawym górnym rogu wybier­amy opcję ‘New repos­i­to­ry’ z menu rozwijanego.

screen_1

Tworze­nie nowego repozy­to­ri­um w ser­wisie GitHub.com

Pojawi się okno, w którym musimy wybrać nazwę naszego repozy­to­ri­um oraz może­my określić kil­ka dodatkowych para­metrów. W tym kur­sie wpisal­iśmy wartoś­ci jak na poniższym ekranie:

Ekran tworzenia nowego repozytorium

Ekran tworzenia nowego repozytorium

Tutaj zatrzy­mamy się na chwilę nad opc­ja­mi w dol­nej częś­ci for­mu­la­rza. Są one specy­ficzne dla plat­formy GitHub.com i (praw­ie) nie są związane bezpośred­nio z Gitem jako narzędziem, ale warto o nich wiedzieć.

Pier­wsza z nich to ‘Ini­tial­ize this repos­i­to­ry with a README’ — w momen­cie utworzenia repozy­to­ri­um utwor­zony zostanie plik readme z przykład­owym opisem stworzym z uży­ciem skład­ni mark­down. GitHub automaty­cznie wyświelta ten plik na stron­ie przeglą­da­nia repozy­to­ri­um, co jest niezwyk­le wygodne w przy­pad­ku bib­liotek i pro­jek­tów Open Source — pozwala zamieś­cić tam najważniejsze infor­ma­c­je, odniesienia do doku­men­tacji, przykłady itp. Dodatkowo GitHub nieco rozsz­erza skład­nię mark­down o własne ele­men­ty.

Dru­ga opc­ja to plik .git­ig­nore — plik ten jest stan­dar­d­owym ele­mentem Git’a i służy do ignorowa­nia określonych plików (a dokład­niej ścieżek) — dzię­ki temu pli­ki, które pasu­ją do zapisanych tam wzor­ców, nie pokazu­ją się w klien­cie jako zmi­any, nie są także wysyłane na ser­w­er. To bard­zo poręcz­na funkc­ja, a GitHub dodatkowo ją ułatwia — może­my wybrać pre­defin­iowany plik .git­ig­nore dla narzędzia/języka, którego uży­wamy (np. Maven ignoru­je wszys­tko w kat­a­lo­gach /target, a Eclipse pli­ki specy­ficzne dla Eclipse).

Ostat­nia z opcji to wybór licencji — pozwala na dołącze­nie do repozy­to­ri­um wybranej licencji, dzię­ki czemu nie musimy się martwić szukaniem jej treś­ci, wkle­janiem itp. Bard­zo proste i funkcjon­alne narzędzie. PS. Jeśli chcesz wybrać licencję do swo­jego pro­jek­tu, ale przytłacza Cię ich ilość, drob­ne różnice itp, pole­camy ser­wis tldrlegal.com — zna­jdziesz tam zwięzłe pod­sumowanie każdej pop­u­larnej licencji (co moż­na, czego nie moż­na, co jest wyma­gane), co poz­woli uniknąć Ci bólu głowy naw­igu­jąc po różnych prawnych tek­stach i zawiłościach.

W tym momen­cie repozy­to­ri­um zostanie utwor­zone, a Ty zosta­niesz prze­nie­siona na jego główną stronę — przeglą­darkę zawartości.

Korzystamy z GitHub.com

W tym miejs­cu powiemy sobie parę słów o inter­fe­jsie github.com oraz funkcjon­al­noś­ci­ach, jakie tam zna­jdziemy. Główny ekran naszego repozy­to­ri­um wyglą­da następująco:

Główna strona repozytorium GitHub

Głów­na strona repozy­to­ri­um GitHub

Okno to ma kil­ka sekcji:

  1. Narzędzia repozy­to­ri­um — tutaj zna­jdziemy opc­je repozy­to­ri­um (gdzie może­my zmienić nazwę, dodać uprawnienia itp) ale także wiki i ‘issues’ — proste mod­uły do prowadzenia doku­men­tacji i obsłu­gi zgłoszeń (może­my je wyłączyć z poziomu opcji) oraz odnośni­ki do pod­sumowań takich jak pulse (zdarzenia związane z naszym repozy­to­ri­um), graphs (podob­nie do pulse, tylko w postaci graficznej) oraz pull requests (to sposób, w jaki każdy może ‘zapro­ponować’ dodanie czegoś do repozy­to­ri­um, nawet jeśli nie posi­a­da do niego uprawnień; jest to także sposób na code review za pomocą GitHub’a)
  2. Statysty­ki — krótkie pod­sumowanie iloś­ci branchy, com­mitów, wydań oraz osób mają­cych uprawnienia do wysyła­nia kodu do repozy­to­ri­um (każ­da z opcji jest klikalna, co przenosi nas na odpowied­nią stronę ze szczegółami)
  3. Szczegóły repozy­to­ri­um — tutaj zna­jdziemy m.in. opcję zmi­any bran­cha, wyszuki­wa­nia, jak i pobiera­nia danego bran­cha w postaci pacz­ki ZIP oraz link do pobra­nia go na swój kom­put­er (o tym powiemy sobie za moment)
  4. Pli­ki i kat­a­lo­gi — dzię­ki temu może­my naw­igować po repozy­to­ri­um prze­chodząc wgłąb kat­a­logów czy podglą­da­jąc pli­ki; w górnej częś­ci jest też skró­cona infor­ma­c­ja o ostat­nim com­mi­cie, kiedy nastąpił oraz kto był jego autorem
  5. Readme — jeśli bieżą­cy kat­a­log zaw­iera plik README.md, tutaj będzie wyświ­et­lona jego zawartość w postaci ‘uład­nionej’

Informacje o commicie

W górnej częś­ci okna widz­imy ostat­ni com­mit w danym kat­a­logu — może­my kliknąć w niego, aby zobaczyć jego szczegóły. Moż­na także kliknąć przy­cisk ‚com­mits’, aby prze­jrzeć pełną his­torię com­mitów, klika­jąc na dowol­ny z nich prze­chodz­imy do jego podsumowania.

Pod­sumowanie com­mi­ta zaw­iera najważniejsze infor­ma­c­je — kto i kiedy go dokon­ał, wiado­mość do niego dołąc­zoną oraz pod­sumowanie zmi­an — tzw. diff. Pod­sumowanie to po lewej stron­ie pokazu­je jak ‚było’, a po prawej wprowad­zone zmi­any. Całość jest kolorowana aby ułatwić naw­igację — kolor czer­wony oznacza usunięte ele­men­ty, zielony dodane, a żół­ty zmi­any. Na widoku tym może­my też wybrać com­mit, z którym porównu­je­my — może­my więc obe­jrzeć zmi­any kilku com­mitów razem, co znacznie ułatwia ‚oga­r­nię­cie’ co zostało zmienione w serii commitów.

Widok commita w serwisie github.com

Widok com­mi­ta w ser­wisie github.com

Blame’ czyli lekcja historii

Kole­jną bard­zo przy­dat­ną funkcją jest tzw. blame — funkcjon­al­ność pozwala­ją­ca ‚odszukać’ kto był autorem ostat­nich zmi­an w wybranym pliku / lin­i­jce. Jest to funkcjon­al­ność dostęp­na zarówno poprzez inter­fe­js Smart­Git jak i GitHub

Przeglą­da­jąc pli­ki w repozy­to­ri­um może­my przełączyć się na widok ‘blame’. Wtedy po lewej stron­ie zna­jdziemy pasek z listą com­mitów i różny­mi odcieni­a­mi pokazu­ją­cy, z którego com­mi­ta pochodzi konkret­na linia. Odcień także ma znacze­nie — im jaśniejszy, tym ‚nowsza’ zmi­ana — dzię­ki temu może­my się szy­bko zori­en­tować czy intere­su­ją­cy nas frag­ment był niedawno mody­fikowany, bez czy­ta­nia szczegółów commitów.

Widok 'blame' pliku na github.com

Widok ‘blame’ pliku na github.com

Forkowanie repozytorium

Cza­sem zdarza się, że chce­my pobrać czy­jeś repozy­to­ri­um, sko­pi­ować je w całoś­ci, a następ­nie pra­cow­ać nieza­leżnie od niego. To bard­zo częs­ta prak­ty­ka w przy­pad­ku pro­jek­tów open source, ale także bard­zo dużych pro­jek­tów. Oper­ac­ja ta nosi nazwę fork — od ang­iel­skiego słowa oznacza­jącego ‚roz­gałęzie­nie’ lub ‚roz­gałęzi­ać’.

W ser­wisie GitHub oper­ac­ja ta jest banal­na, i sprowadza się do jed­nego kliknię­cia — nad repozy­to­ri­um do którego mamy dostęp, wystar­czy kliknąć przy­cisk ‚fork’. Dzię­ki temu uzyskamy kopię repozy­to­ri­um całkowicie pod naszą kontrolą.

Forkowanie repozytorium w GitHub

Forkowanie repozy­to­ri­um w GitHub

Kopia doty­czy całoś­ci repozy­to­ri­um — tzn kopi­owana jest także his­to­ria zmi­an i wszys­tkie branche (o bran­chach powiemy sobie nieco więcej w dal­szej częś­ci). Oczy­wiś­cie może­my je usunąć tak jak usuwal­ibyśmy we włas­nym repozytorium.

Co ważne, wszelkie zmi­any wprowad­zone w naszej kopii repozy­to­ri­um nie są widoczne w ‚ory­gi­nale’, podob­nie jak w drugą stronę — od tej pory są to dwa nieza­leżne repozy­to­ria. Może­my jed­nak świadomie ‚przesyłać’ zmi­any pomiędzy nimi, co także jest widoczne jako pull requesty.

Inne funkcje

GitHub ofer­u­je wiele innych dodatkowych narzędzi, o których możn­a­by napisać naprawdę dłu­gi wpis. Omówiliśmy te najważniejsze, a zain­tere­sowanych odsyłamy do pomo­cy GitHub, która jest naprawdę dobrze napisana.

Korzystamy z repozytorium zdalnego

W tym momen­cie mamy już repozy­turi­um utwor­zone na ser­w­erze, GitHub sam umieś­cił w nim kil­ka plików, czas pobrać je na nasz kom­put­er oraz dokon­ać jakichś zmi­an! Na początku pokaże­my drogę ‘domyśl­ną’, w przy­pad­ku GitHub’a oraz Smart­Git’a jest też dro­ga ‘na skró­ty’, o której krótko będzie poniżej.

Uru­chom Smart­Git — powin­naś zobaczyć puste okno z kilko­ma zakład­ka­mi, które może nieco prz­er­ażać. Nie ma się jed­nak czego bać ;)

Okno SmartGit

Główne okno programu SmartGit

Główne okno pro­gra­mu SmartGit

Główne okno podzielone jest na kil­ka ‘sekcji’, z których każ­da ma określone zas­tosowanie. Okien­ka te może­my oczy­wiś­cie otwier­ać / zamykać / przemieszczać wg uzna­nia, powyższy widok jest widok­iem domyślnym.

  • menu rozwi­jane — ofer­u­je dostęp do wszys­t­kich funkcji pro­gra­mu, pozwala także otworzyć sekc­je, które nie są w danej chwili widoczne
  • menu górne — najczęś­ciej uży­wane funkc­je zebrane w postaci dużych przy­cisków, do których zawsze mamy szy­b­ki dostęp
  • repos­i­to­ries — lista repozy­toriów zarządzanych z poziomu Smart­Git’a, pozwala także przełączać się pomiędzy nimi oraz przeglą­dać drze­wo katalogów
  • files — lista plików w wybranym kat­a­logu / repozytorium
  • changes — po wybra­niu pliku, w tej częś­ci może­my pode­jrzeć mody­fikac­je, jakie zostały doko­nane wzglę­dem wer­sji ‘z repozytorium’
  • branch­es — lista branchy w repozy­to­ri­um, z którym obec­nie pracu­je­my, zarówno tych dostęp­nych lokalnie jak i zdalnych
  • out­go­ing — list com­mitów, które nie zostały jeszcze przesłane na serv­er (nie została dla nich wyko­nana oper­ac­ja push — więcej o tym poniżej)
  • out­put — his­to­ria pole­ceń, które wykony­wal­iśmy na repozy­to­ri­um; co ciekawe, pokazane są komendy, jakich moglibyśmy użyć także pracu­jąc z GITem w kon­soli — przy­datne do nau­ki pole­ceń GIT’a lub wery­fikacji, co się tak naprawdę dzieje

Klonowanie repozytorium

Mamy więc już repozy­to­ri­um na ser­w­erze, aby sko­pi­ować je na włas­ny kom­put­er i rozpocząć pracę, musimy wykon­ać oper­ację, która w Git nazy­wa się klonowaniem. W tym celu wybier­amy opcję clone z menu głównego.

Opcja klonowania repozytorium w górnym menu

Opc­ja klonowa­nia repozy­to­ri­um w górnym menu

w kole­jnym kroku musimy podać adres repozy­to­ri­um — zna­jdziemy go na GitHub na głównej stron­ie repozy­to­ri­um, np. https://github.com/kobietydokodupl/kurs-javy.git . Prze­chodząc dalej możesz także zostać popros­zona o hasło, jeśli nie zostało wcześniej zapamiętane.

Wybór repozy­to­ri­um zdalnego

Następ­nie wybier­amy lokaliza­cję na dysku, gdzie chce­my pobrać repozy­to­ri­um. Jeśli wybrany fold­er jest pusty, to pli­ki zostaną pobrane bezpośred­nio do niego. Jeśli nie, zostanie w nim utwor­zony nowy fold­er o nazwie takiej jak repozytorium.

Po chwili repozy­to­ri­um zostało już sko­pi­owane na nasz kom­put­er — może­my pra­cow­ać z nim lokalnie, dokony­wać com­mitów czy też przeglą­dać his­torię zmi­an lokalnie.

Opcja alternatywna: podpięcie konta

Smart­Git umożli­wia pod­pię­cie kon­ta z jed­nego z dostęp­nych sys­temów kon­troli wer­sji, w tym GitHub, i korzys­tanie z niego w kilku miejs­cach. Jest to ułatwie­nie pozwala­jące nam nie wprowadzać hasła wielokrot­nie oraz wybier­ać repozy­to­ri­um z listy dostęp­nych zami­ast kopi­ować jego ścieżkę.

Pier­wszym krok­iem jest kon­fig­u­rac­ja kon­ta — w tym celu otwier­amy pref­er­enc­je a następ­nie wybier­amy z menu opcję host­ing providers.

Ustawienia 'hosting providers' w SmartGit

Ustaw­ienia ‘host­ing providers’ w SmartGit

W tym miejs­cu musimy podać token — najprost­sza opc­ja to wygen­erowanie tokenu za pomocą przy­cisku — w tym celu zostaniemy poproszeni o podanie loginu i hasła. Wygen­erowany zostanie token, który pozwala Smart­Gi­towi korzys­tać z GitHub’a nie uży­wa­jąc bezpośred­nio Two­jego hasła, co jest bez­pieczniejszą opcją. Dostęp ten możesz w każdym momen­cie wyco­fać korzys­ta­jąc z github.com (zakład­ka Appli­ca­tions w ustaw­ieni­ach kon­ta)

Dodawanie konta GitHub

Dodawanie kon­ta GitHub

Po doda­niu kon­ta wybier­a­jąc repozy­to­ri­um, z którego chce­my korzys­tać, mamy możli­wość wybra­nia wszys­t­kich, do których ma dostep nasze kon­to bezpośred­nio z poziomu okna wyboru:

Wybór repozytorium zdalnego - GitHub

Wybór repozy­to­ri­um zdal­nego — GitHub

Modyfikacje, dodawanie i usuwanie plików

Masz już kopię repozy­to­ri­um lokalnie, na swoim dysku. Pra­ca z tymi plika­mi wyglą­da iden­ty­cznie jak z nor­mal­ny­mi plika­mi na dysku — możesz tworzyć pli­ki, usuwać je, mody­fikować, zmieni­ać im nazwy itp. Zmi­any te nie pojaw­ią się jed­nak ‚automaty­cznie’ w repozytorium.

Przede wszys­tkim musimy powiedzieć Gitowi które zmi­any chce­my zachować, a które odrzu­cić. Najczęś­ciej chce­my zachować wszys­tkie zmi­any, ale może się także zdarzyć sytu­ac­ja, w której dokon­al­iśmy jakichś zmi­an i chce­my je przy­wró­cić do wer­sji wcześniejszej. Pomoże nam w tym klient Git — w tym wypad­ku Smart­Git. W głównym oknie pro­gra­mu domyśl­nie widz­imy tylko pli­ki, które różnią się od tych zapisanych w pamię­ci Git’a. Klika­jąc w wybraną pozy­cję może­my pode­jrzeć jakie są różnice pomiędzy stanem zapisanym (czyli ostat­nim com­mitem) a bieżącym.

Przykładowa 'różnica' pomiędzy plikami

Przykład­owa ‘różni­ca’ pomiędzy plikami

Smart­Git pozwala ‚dodać’ wybrane zmi­any przed ich zapisaniem (wyko­naniem oper­acji com­mit) — służy do tego przy­cisk ‚Stage’ w górnej belce. Ana­log­icznie przy­cisk ‚Dis­card’ pozwala odrzu­cić zmi­any i przy­wró­cić ostat­nio zapisaną wer­sję (uwa­ga: ta oper­ac­ja jest nieodwracalna!).

Przyciski 'stage' i 'discard' w głównym oknie SmartGit

Przy­cis­ki ‘stage’ i ‘dis­card’ w głównym oknie SmartGit

Mając wybrane zmi­any, które chce­my com­mi­tować, klikamy na przy­cisk Com­mit — tutaj Smart­Git pozwala nam nie tylko uzu­pełnić wiado­mość, jaka będzie pow­iązana z com­mitem, ale także ponown­ie prze­jrzeć, które zmi­any wybral­iśmy, a których nie, i zmienić naszą decyzję w razie potrze­by. Jeśli ostat­nie zmi­any są zapisane tylko lokalne (tzn. nie wysłal­iśmy ich jeszcze na cen­tralne repozy­to­ri­um), mamy opcję pozwala­jącą zmody­fikować ostat­ni com­mit zami­ast tworzyć nowy.

Okno commitowania plików

Okno com­mi­towa­nia plików

W tym momen­cie nasze zmi­any są już gotowe do wysła­nia na ser­w­er — może­my użyć opcji Sync, która jest połącze­niem opcji Pull oraz Push (w tej kole­jnoś­ci). Oper­ac­ja Pull pozwala nam na pobranie ostat­nich zmi­an z repozy­to­ri­um cen­tral­nego, oper­ac­ja push wysyła wszys­tkie com­mi­ty, które są tylko lokalnie, na repozy­to­ri­um centralne.

Com­mit obe­j­mu­je dowolne zmi­any w plikach — nie tylko mody­fikac­je czy dodawanie, ale także zmi­anę nazwy czy ich usuwanie.

Uwa­ga: Git nie prze­chowu­je kat­a­logów, a jedynie pli­ki! Oznacza to, że jeżeli kat­a­log jest pusty, to nie będzie on widoczny w repozy­to­ri­um — kat­a­lo­gi w Git są ‚skutkiem ubocznym’ plików w nich umieszc­zonych (Git mówiąc w uproszcze­niu prze­chowu­je ścież­ki plików wewnątrz repozy­to­ri­um, na tej pod­staw­ie może określić jakie kat­a­lo­gi są ‚widoczne’).

Uwa­ga 2: O ile Git jest w stanie prze­chowywać pli­ki bina­rne (np. grafi­ki, filmy, zdję­cia, doku­men­ty word itp), jego algo­ryt­my i pro­tokół są zop­ty­mal­i­zowane do pra­cy z plika­mi tek­stowy­mi — taki­mi jak np. kody źródłowe. Więk­szość narzędzi jak np. różnice, his­to­ria zmi­an, blame czy rozwiązy­wanie kon­flik­tów traci sens w przy­pad­ku plików bina­rnych z uwa­gi na sposób, w jaki są one twor­zone (np. zmi­ana kilku liter w doku­men­cie word może całkowicie zmienić cały plik docx, w którym ta zmi­ana się zna­j­du­je). Choć ich prze­chowywanie w repozy­to­ri­um Git jest możli­we, Git nie nada­je się do prze­chowywa­nia dużej iloś­ci plików, które nie są tekstem.

Praca z branchami

Bard­zo ważną funkcją sys­temów kon­troli wer­sji są branche — czyli ‚odgałęzienia’ głównej linii kodu, na których moż­na pra­cow­ać nie­jako w ‚izo­lacji’. Jest to bard­zo ważne nie tylko w ogrom­nych pro­jek­tach, gdzie wiele osób pracu­je jed­nocześnie nad wielo­ma rzecza­mi, ale także w mniejszych zespołach. Branche pozwala­ją także na ekspery­men­towanie i wprowadzanie zmi­an bez wpły­wu na główny branch (najczęś­ciej zwany mas­ter), wprowadzanie więk­szych mody­fikacji w sposób przy­ros­towy a także zarządzanie np. dwiema różny­mi wer­s­ja­mi produktu.

Tworzenie nowych branchy

Aby dodać nowy branch wystar­czy w oknie Smart­Git w menu Branch wybrać Cre­at new, a następ­nie podać jego nazwę. Stworzy to nowy branch i przełączy Cię od razu na niego. Branch ten będzie widoczny na ser­w­erze cen­tral­nym po następ­nej oper­acji push.

Dodawanie nowego brancha

Dodawanie nowego brancha

Pobieranie istniejących branchy i ich używanie

Domyśl­nie w lewym dol­nym rogu mamy listę branchy, o których Smart­Git ‚wie’ — zarówno tych lokalnych, jak i tych ist­nieją­cych tylko zdalnie.

Lista branchy

Lista branchy

Aby odświeżyć listę zdal­nych branchy może­my kliknąć prawym przy­ciskiem myszy na repozy­to­ri­um, po czym wybrać opcję ‚Fetch’ — dzię­ki temu pobrane zostaną nowe branche, o ile ist­nieją. Przełącze­nie się na lokalny lub zdal­ny branch sprowadza się do dwukrot­nego kliknię­cia na niego. W przy­pad­ku branchy zdal­nych, zostanie on najpierw pobrany lokalnie, a dopiero później nastąpi przełączenie.

Aktu­al­nie wybrany branch, na którym pracu­je­my, wyróżniony jest pogrubieniem.

Operacja stash / unstash

Pracu­jąc z bran­cha­mi mamy dostep­ne także oper­ację zwaną stash — jest to coś w rodza­ju ‚schowka’, na którym może­my umieszczać zmi­any, które chce­my zachować, ale niekoniecznie com­mi­tować. Stash jest tylko lokalny, nie ma możli­woś­ci jego syn­chro­niza­cji z ser­w­erem zdal­nym i jest nieza­leżny od bran­cha. Jest on przy­dat­ny np w sytu­acji kiedy wprowadza­my jakieś zmi­any, po czym musimy przełączyć się na inne zadanie lub chce­my określone zmi­any jed­nak umieś­cić na innym branchu. Stash jest też wyko­rzysty­wany przy pul­lowa­niu zmi­an — każ­da oper­ac­ja pull to tak naprawdę umieszcze­nie zmi­an na stosie, pobranie najnowszej wer­sji, a następ­nie pró­ba przy­wróce­nia tych zmi­an ze stosu.

Aby dodać zmi­any na stos, wystar­czy wybrać opcję Local -> Save stash changes z menu

Zapisz zmiany na stos

Zapisz zmi­any na stos

Podob­nie z ‚przy­wracaniem’ zmi­an — wybier­amy zmi­any, które nas intere­su­ją, po czym są one ‚nakładane’ na bieżącą wer­sję plików. Służy do tego opc­ja w menu Local -> Apply stash

Rozwiązywanie konfliktów

Wspom­ni­ana wcześniej oper­ac­ja pull może prowadz­ić do kon­flik­tów — jeśli wprowadz­iłaś mody­fikac­je w pliku, który zmienił się na repozy­to­ri­um cen­tral­nym od ostat­niego razu, jak robiłaś pull, może to spowodować, że Git nie będzie w stanie samodziel­nie połączyć tych zmi­an. Spowodu­je to tzw. kon­flikt — sytu­ację, która wyma­ga man­u­al­nego rozwiąza­nia. W Smart­Git objaw­ia się to plikiem z czer­woną ikonką.

Plik w statusi 'konflikt' (na dole widoczne 'adnotacje' Git'a w problematycznym miejscu)

Plik w sta­tusi ‘kon­flikt’ (na dole widoczne ‘adno­tac­je’ Git’a w prob­lematy­cznym miejscu)

Git automaty­cznie tworzy dwa pli­ki tym­cza­sowe — zaw­ier­a­jące sporny plik w wer­sji z repozy­to­ri­um i w wer­sji lokalnej — oraz w rzec­zonym pliku w spornych frag­men­tach doda­je stosowne adno­tac­je. Kon­flik­ty moż­na rozwiązy­wać ręcznie — odpowied­nio mody­fiku­jąc dany plik w wybranym przez nas edy­torze — lub korzys­ta­jąc z opcji ‚Resolve con­flicts’ w Smart­Git. Opc­ja ta pozwala w sposób graficzny, po kolei dla każdej ze zmi­an, które są w kon­flik­cie, wybrać właś­ci­wą zmi­anę lub samodziel­nie zmody­fikować kod tak, aby był praw­idłowy. Po rozwiąza­niu kon­flik­tów ‚infor­mu­je­my’ o tym Git’a poprzez wyko­nanie oper­acji commit.

Rozwiązy­wanie kon­flik­tu — na niebiesko zaz­nac­zone są strza­ł­ki, które pozwala­ją szy­bko wybrać ‘wer­sję’, którą chce­my zachować (możli­wa jest też edy­c­ja ręcz­na, w środ­kowym oknie)

Zasady pracy z Gitem

O ile każ­da orga­ni­za­c­ja czy zespół posi­a­da własne zasady, poniżej przed­staw­iamy kil­ka zasad, które mogą ułatwić wszys­tkim pracę z wspól­nym repozytorium.

Wiadomości commitów

O ile dla Ciebie ‚fix błę­du’ może mieć sens i możesz wiedzieć o co chodzi, za miesiąc nie będziesz już pamię­tała — co to był za błąd, dlaczego trze­ba było go popraw­ić, jak dokład­nie został popraw­iony itp. Dobrą prak­tyką jest dołączanie numeru tick­e­ta do wiado­moś­ci com­mi­ta, o ile taki posi­adamy — dzię­ki temu moż­na w przyszłoś­ci prześledz­ić cała his­torię błę­du w razie potrze­by i uza­sad­nie­nie wprowadzenia określonej zmi­any. Przykład wiado­moś­ci com­mi­ta, która poz­woli w przyszłoś­ci zrozu­mieć cel danej zmiany:

[PROJEKT-123] Zmi­ana kodowa­nia zapy­tań HTTP z UTF‑8 na UTF-16 w celu zgod­noś­ci z sys­te­mem XYZ

Nie bój się też ‚upom­i­nać’ innych osób w zes­pole — na dobrych opisach com­mitów zys­ka ostate­cznie cały zespół.

Branch na każdą funkcjonalność

W prze­ci­wieńst­wie do innych sys­temów kon­troli wer­sji jak np. SVN, stworze­nie bran­cha jest ‚tanie’ — nie ma potrze­by kopi­owa­nia całej zawartoś­ci repozy­to­ri­um, nie wyma­ga to wiele dodatkowego miejs­ca na dysku czy innych zasobów. Dlat­ego dobrą prak­tyką jest tworze­nie nowego bran­cha dla każdej funkcjon­al­noś­ci / zada­nia, nad którym pracu­je­my. Nie tylko ułatwi to innym prze­ję­cie pra­cy po nas w razie potrze­by, ale dodatkowo izolu­je nas od innych zmi­an pod­czas pra­cy nad konkret­nym celem. Oczy­wiś­cie po połącze­niu zmi­an z główną gałęz­ią, branche takie moż­na usunąć lub pozostaw­ić wg pref­er­encji zespołu.

Pewnym uproszcze­niem (choć stworze­nie bran­cha zaj­mu­je naprawdę chwilę) jest tworze­nie bran­cha dla każdego devel­opera — prze­ważnie jed­na oso­ba pracu­je nad jed­ną funkcjon­al­noś­cią w danym momen­cie, więc jest to podob­ne rozwiązanie (choć nieco mniej przejrzyste)

Pushowanie wyłącznie gotowych funkcjonalności

Pracu­jąc nad więk­szą funkcjon­al­noś­cią najpraw­dopodob­niej dokonasz com­mit kilkukrot­nie w trak­cie — zarówno po to, aby zor­ga­ni­zować sobie pracę, ale także być może chcesz wprowadz­ić jakąś zmi­anę, którą możesz chcieć wyco­fać. Pamię­taj jed­nak, żeby nie pushować zmi­an, które nie są ostate­czne — repozy­to­ri­um zdalne jest wspól­nym miejscem pra­cy całego zespołu, i przez niekom­pletne zmi­any możesz np. zep­suć build lub spowodować, że ktoś pobierze niedzi­ała­jącą wer­sję do dal­szej pra­cy. Pamię­taj jed­nak, że nie warto prze­sadzać — jeśli kodowanie nowej funkcjon­al­noś­ci zajmie Ci tydzień, powin­naś rozbić ją na mniejsze ‘pod­funcjon­al­noś­ci’ i w takiej postaci pra­cow­ać nad nimi czy je pushować. Przed wypushowaniem swo­jego com­mi­ta musisz zawsze zadać sobie pytanie, czy “nie pop­su­je on aplikacji” i jeśli nie, to możesz to zrobić.

Oczy­wiś­cie każ­da oso­ba powin­na pra­cow­ać na osob­nym branchu, ale są różne sytu­acje i warto pra­cow­ać z założe­niem, że zmi­any widoczne dla wszys­t­kich na branchu są kom­pletne lub co najm­niej nie psu­ją innych funkcjonalności.

Łączenie wielu commitów przed pushem

Dobrym nawykiem jest com­mi­towanie lokalnie jak najczęś­ciej — dzię­ki czemu mamy pełną his­torię zmi­an, którą może­my przeglą­dać lub wracać do niej i ‚’cofać się’ do dowol­nego punk­tu w cza­sie. Wyglą­dało by to jed­nak nieeste­ty­cznie na repozy­to­ri­um cen­tral­nym, utrud­ni­ało wyszuki­wanie infor­ma­cji, która nas intere­su­je i śledze­nie his­torii zmi­any. Warto przed wyko­naniem oper­acji push połączyć wszys­tkie com­mi­ty związane z jed­ną funkcjon­al­noś­cią / zadaniem w jeden. Służy do tego oper­ac­ja Squash com­mits w menu Local.

Menu z opcją squash commits

Menu z opcją squash commits

Aby oper­ac­ja ta była dostęp­na, musisz wybrać com­mi­ty do połączenia w oknie ‚out­go­ing’. Uwa­ga: nie da się łączyć com­mitów, które zostały już wypushowane! Opc­ja ta dostęp­na jest także po kliknię­ciu prawym przy­ciskiem mysz­ki na zaz­nac­zonych commitach.

commit_squash_submenu

Okienko ‘out­go­ing’ i opc­ja squash commits

Okno pozwala nam wybrać opis zmi­an, który będzie widoczny w logu oraz autor, który zostanie do nich przyp­isany (musi to być jeden z autorów łąc­zonych commitów)

Okno łączenia commitów

Okno łączenia commitów

Podsumowanie

Wytłu­maczyliśmy sobie pod­sta­wowe kon­cepc­je związane z kon­trolą wer­sji oraz jak je stosować w prak­tyce. Mam nadzieję, że przekon­al­iśmy Cię że jest to narzędzie zarówno proste, jak i efek­ty­wne. Mnóst­wo usług czy narzędzi bazu­je na git i ofer­u­je także bezpłat­ny host­ing oraz licenc­je, dzię­ki czemu moż­na go stosować także do swoich pry­wat­nych pro­jek­tów bez ponoszenia kosztów. O ile Git ma znacznie więcej możli­woś­ci i funkcji, te pod­sta­wowe wystar­czą Ci do usprawnienia codzi­en­nej pra­cy i zabez­pieczenia swoich danych :)

Także od tej pory wszys­tkie rozwiąza­nia do lekcji, mate­ri­ały oraz mini-kursy będziemy umieszczać w naszych repozy­to­ri­ach na GitHub. Dzię­ki temu każdy będzie mógł w prosty sposób mieć do nich dostęp, przeglą­dać czy kopi­ować i mody­fikować we włas­nym zakre­sie. Link poniżej!