Blog JSystems - uwalniamy wiedzę!
Blog JSystems - uwalniamy wiedzę!
Znasz to uczucie, gdy w folderze z projektem lądują pliki oferta.docx, oferta_final.docx, oferta_final_POPRAWIONA.docx i oferta_final_naprawde_ostatnia.docx? A potem nikt już nie wie, która wersja jest aktualna i co dokładnie zmieniło się między nimi? Git rozwiązuje ten problem raz na zawsze. To narzędzie, które zapamiętuje każdą wersję Twojego projektu i pozwala wrócić do dowolnego momentu w jego historii, porównać zmiany i bezpiecznie pracować nad kilkoma pomysłami równolegle.
Git jest dziś standardem w pracy programistów, ale korzystają z niego też administratorzy, analitycy danych, autorzy dokumentacji i wszyscy, którzy chcą mieć porządek w plikach tekstowych. W tym przewodniku przeprowadzimy Cię od zera: zainstalujesz Gita, założysz pierwsze repozytorium, nauczysz się zapisywać zmiany, cofać błędy, pracować na gałęziach i wysyłać kod na GitHub. Każdy krok pokażemy na prawdziwych zrzutach z terminala, dokładnie tych, które zobaczysz u siebie.
init, add, commit),status, diff, log),restore, reset, revert),push, pull, clone).Zanim cokolwiek zainstalujemy, uporządkujmy dwa pojęcia, które początkującym często się mylą. Git i GitHub to nie to samo.
Git to program, który instalujesz na swoim komputerze. To on jest systemem kontroli wersji, czyli mechanizmem zapisującym kolejne wersje plików i pozwalającym wracać do wcześniejszych. Git działa w całości lokalnie: nie potrzebuje internetu ani żadnego konta, żeby śledzić historię Twojego projektu. Cała ta historia leży u Ciebie na dysku, w ukrytym folderze o nazwie .git.
GitHub (a także GitLab czy Bitbucket) to z kolei serwis internetowy, na którym możesz trzymać kopię swojego repozytorium. Służy do współpracy w zespole, do backupu i do dzielenia się kodem. Git potrafi wysłać Twoją historię na taki serwer i pobrać z niego zmiany innych osób, ale sam w sobie świetnie działa nawet bez niego.
Najprostsza analogia: Git jest jak edytor tekstu z historią zmian, a GitHub jak dysk w chmurze, na który tę historię wrzucasz. W tym przewodniku najpierw opanujemy samego Gita (części 2 do 8), a dopiero na końcu połączymy się z GitHubem.
Git instaluje się inaczej w zależności od systemu. Na Windowsie pobierz instalator ze strony git-scm.com i przeklikaj kreator, zostawiając domyślne ustawienia. Razem z Gitem dostaniesz program Git Bash, czyli terminal, w którym będziemy pracować (wszystkie zrzuty w tym przewodniku pochodzą właśnie z niego). Na macOS najłatwiej wpisać w terminalu brew install git (jeśli masz menedżer Homebrew), a na Linuksie skorzystać z menedżera pakietów, na przykład sudo apt install git na Ubuntu i Debianie.
Po instalacji sprawdź, czy wszystko się udało. Otwórz terminal (na Windowsie Git Bash) i wpisz polecenie sprawdzające wersję:
git --versionJeśli w odpowiedzi zobaczysz numer wersji, Git jest gotowy do pracy.
Została jedna rzecz, którą robi się tylko raz po instalacji: przedstawienie się Gitowi. Przy każdym zapisie zmiany (commicie) Git podpisuje ją Twoim imieniem i adresem e-mail, żeby w historii było widać, kto co zrobił. Ustawiamy to poleceniami git config z opcją --global, która oznacza, że dane zapamiętane zostaną dla wszystkich Twoich projektów na tym komputerze. Wpisz swoje dane (podmień na własne):
git config --global user.name "Jan Kowalski"
git config --global user.email "jan.kowalski@example.pl"Możesz od razu sprawdzić, czy dane zapisały się poprawnie. Polecenie git config --get odczytuje ustawioną wartość:
To wszystko. Od tej pory Git wie, kim jesteś, i nie będziemy już musieli tego powtarzać przy kolejnych projektach.
Zanim zaczniemy zapisywać zmiany, warto zrozumieć jeden pomysł, na którym opiera się cały Git. To on odróżnia Gita od zwykłego zapisywania plików i na początku bywa mylący, ale gdy raz go zrozumiesz, reszta stanie się prosta. W Gicie każdy plik przechodzi przez trzy stany.
Po pierwsze, katalog roboczy (working directory) to zwykły folder z Twoimi plikami, ten, który widzisz w eksploratorze. Gdy edytujesz plik, zmiana najpierw pojawia się właśnie tutaj. Git widzi, że plik się różni od ostatnio zapisanej wersji, ale jeszcze nic z tym nie robi.
Po drugie, poczekalnia (nazywana też staging area albo index) to lista zmian, które chcesz zapisać w najbliższym commicie. Poleceniem git add mówisz Gitowi: tę konkretną zmianę chcę utrwalić. Poczekalnia pozwala zapisywać zmiany porcjami. Możesz zmienić pięć plików, ale do jednego commita dołożyć tylko dwa, a resztę zostawić na później.
Po trzecie, repozytorium (folder .git) to trwała historia. Gdy wykonasz git commit, zawartość poczekalni zostaje zapisana jako nowy punkt w historii, do którego zawsze możesz wrócić. Ten punkt nazywamy commitem.
Całą pracę z Gitem można streścić jako ciągłe przesuwanie zmian przez te trzy obszary: edytujesz plik, dodajesz go do poczekalni przez git add, a potem zapisujesz w historii przez git commit. Zobaczmy to na żywo.
Załóżmy projekt: prostą stronę WWW o nazwie moja-strona. Utwórz gdziekolwiek pusty folder, wejdź do niego w terminalu, a następnie zamień go w repozytorium Gita jednym poleceniem:
git initPolecenie git init tworzy w folderze ukryty podfolder .git, w którym Git będzie trzymał całą historię. Od tej chwili Twój zwykły folder stał się repozytorium. W odpowiedzi Git wypisze Initialized empty Git repository (zainicjowano puste repozytorium). Zaraz potem sprawdźmy stan poleceniem git status, które będzie Twoim najczęściej używanym poleceniem: pokazuje, co się dzieje w repozytorium.
Git informuje No commits yet (brak commitów) oraz nothing to commit (nie ma czego zapisać), bo folder jest pusty. Dodajmy więc pierwsze pliki, na przykład index.html i README.md, i ponownie sprawdźmy status:
Pliki pojawiły się w sekcji Untracked files (pliki nieśledzone), zaznaczone na czerwono. Czerwony kolor w Gicie zawsze oznacza: ta zmiana nie jest jeszcze w poczekalni. Git widzi te pliki, ale świadomie ich nie pilnuje, dopóki mu nie powiesz. Zróbmy to poleceniem git add. Możesz wymienić pliki po nazwie albo użyć kropki (git add .), która dodaje wszystkie zmiany naraz:
Teraz te same pliki są w sekcji Changes to be committed (zmiany do zatwierdzenia) i świecą na zielono. Zielony kolor oznacza: ta zmiana czeka w poczekalni na zapis. Zostało utrwalić ją w historii. Robimy to poleceniem git commit. Opcja -m pozwala od razu dopisać krótki opis (message), czyli notatkę, co ten commit wprowadza:
git commit -m "Pierwsza wersja strony"Git odpowiada linią w rodzaju [main (root-commit) 134902f] i podsumowaniem, ile plików i linii się zmieniło. Ten pierwszy commit nazywany jest root-commit, bo rozpoczyna historię. Ciąg znaków 134902f to skrócony identyfikator commita, unikalny odcisk palca, po którym Git rozpoznaje ten konkretny punkt w historii. Sprawdźmy tę historię poleceniem git log:
Gratulacje, właśnie zapisałeś pierwszą wersję projektu. W git log widać pełny identyfikator commita, jego autora (dane, które ustawiłeś w części drugiej), datę oraz opis. Ta historia będzie teraz rosnąć z każdym kolejnym commitem.
Prawdziwa siła Gita ujawnia się, gdy projekt się rozwija. Dodajmy plik ze stylami style.css i wprowadźmy drobną zmianę w index.html. Zanim cokolwiek zapiszemy, warto zobaczyć dokładnie, co się zmieniło. Do porównania stanu bieżącego z ostatnim commitem służy polecenie git diff:
To jeden z najważniejszych zrzutów w tym przewodniku, więc przyjrzyjmy mu się dokładnie. git status pokazuje na górze, że index.html został zmodyfikowany (modified), a style.css jest nowym, nieśledzonym plikiem. Poniżej git diff pokazuje szczegóły: linie zaczynające się od plusa i podświetlone na zielono to linie dodane, a te z minusem na czerwono byłyby liniami usuniętymi. Widać jak na dłoni, że dołożyliśmy odwołanie do arkusza stylów i jeden akapit. Dzięki git diff nigdy nie zapisujesz zmian w ciemno.
Gdy zmiany wyglądają dobrze, zapisujemy je znaną już parą poleceń: git add . odkłada wszystko do poczekalni, a git commit utrwala. Potem obejrzyjmy skróconą historię poleceniem git log --oneline, które pokazuje każdy commit w jednej linii:
Opcja --oneline to najwygodniejszy sposób na szybki przegląd historii: każdy commit zajmuje jedną linię z jego skróconym identyfikatorem i opisem. Gdy chcesz wiedzieć nie tylko co, ale i ile się zmieniło, dodaj opcję --stat, która pokazuje liczbę zmienionych linii w każdym pliku:
Te trzy polecenia, git status, git diff i git log, to Twoje oczy w projekcie. Pierwsze mówi, co się dzieje teraz, drugie pokazuje dokładne różnice, a trzecie odtwarza całą przeszłość projektu.
Każdy popełnia błędy, a Git jest w tym wybaczający, pod warunkiem że wiesz, którego polecenia użyć. To najważniejsza praktyczna część przewodnika, bo strach przed zepsuciem czegoś jest tym, co najczęściej blokuje początkujących. Rozłóżmy cofanie na trzy sytuacje.
Wyobraź sobie, że eksperymentowałeś w pliku style.css, popsułeś go i chcesz po prostu wrócić do ostatniej zapisanej wersji. Polecenie git restore przywraca plik do stanu z ostatniego commita, kasując wszystkie niezapisane zmiany:
git restore style.css
Po git restore polecenie git status pokazuje working tree clean (katalog roboczy czysty), czyli że nie ma już żadnych niezapisanych zmian. Uwaga: to działanie kasuje Twoje zmiany bezpowrotnie, więc używaj go tylko wtedy, gdy naprawdę chcesz je porzucić.
Inna sytuacja: dodałeś plik do poczekalni przez git add, ale rozmyśliłeś się i nie chcesz go jeszcze zapisywać. Opcja --staged cofa plik z poczekalni z powrotem do katalogu roboczego, nie ruszając samej treści:
git restore --staged README.md
Najciekawiej robi się, gdy chcesz cofnąć cały commit. Załóżmy, że przez pomyłkę zapisałeś commit z plikiem, którego nie powinno tam być. Polecenie git reset --soft HEAD~1 cofa ostatni commit, ale zachowuje jego zmiany w poczekalni (HEAD~1 oznacza jeden commit wstecz):
git reset --soft HEAD~1
Po reset --soft commit zniknął z historii, ale jego zawartość wróciła do poczekalni. Możesz teraz coś poprawić i zapisać na nowo. Ważne: git reset przepisuje historię, więc używaj go tylko na commitach, których jeszcze nikomu nie wysłałeś. Jeśli commit trafił już na GitHub i pobrali go inni, sięgnij po bezpieczniejsze git revert. Zamiast wymazywać commit, tworzy ono nowy commit, który odwraca jego zmiany:
git revert --no-edit HEAD
Zauważ różnicę w historii: po revert stary commit dalej tam jest, a nad nim pojawił się nowy commit Revert..., który cofa jego skutki. Nic nie znika, więc nikomu, kto pracuje na tej samej historii, nic się nie rozjedzie. To złota zasada Gita: na własnych, niewysłanych zmianach możesz przepisywać historię, na wspólnych, wysłanych, tylko ją dopisujesz.
Do tej pory pracowaliśmy na jednej linii historii. Ale co, jeśli chcesz wypróbować nowy pomysł, nie psując tego, co działa? Do tego służą gałęzie (branches). Gałąź to niezależna linia pracy: możesz na niej eksperymentować, zapisywać commity i dopiero gdy wszystko jest gotowe, dołączyć ją do głównej wersji projektu. Główna gałąź nazywa się zwykle main.
Zobaczmy to w praktyce. Poleceniem git branch sprawdzamy listę gałęzi (gwiazdka pokazuje, na której jesteśmy), a git switch -c tworzy nową gałąź i od razu na nią przechodzi. Litera c pochodzi od create (utwórz):
git branch
git switch -c oferta
Jesteśmy teraz na gałęzi oferta. Wszystko, co tu zapiszemy, nie dotknie gałęzi main. Dodajmy nowy plik i zróbmy commit, a potem wróćmy na main poleceniem git switch main i dołączmy naszą pracę poleceniem git merge:
Polecenie git merge oferta dołączyło commity z gałęzi oferta do main. Git nazwał to scalanie fast-forward, bo main nie miał w międzyczasie własnych nowych commitów, więc wystarczyło przesunąć go do przodu. Na końcu użyliśmy git log --graph --oneline --all, które rysuje historię wszystkich gałęzi w formie grafu. Gdy gałąź jest już scalona, możesz ją usunąć poleceniem git branch -d oferta, bo jej praca żyje teraz w main.
Fast-forward z poprzedniej części był łatwy, bo tylko jedna gałąź coś zmieniła. Ale co, jeśli dwie gałęzie zmienią tę samą linię w tym samym pliku? Git nie zgadnie, która wersja jest właściwa, i poprosi Cię o decyzję. To jest konflikt scalania i choć brzmi groźnie, jest zupełnie normalną częścią pracy zespołowej.
Odtwórzmy go świadomie. Na jednej gałęzi zmienimy nagłówek strony na jeden tekst, a na main na inny, po czym spróbujemy je scalić:
Git wypisuje CONFLICT (content): Merge conflict in index.html oraz Automatic merge failed (automatyczne scalanie nie powiodło się). Polecenie git status pokazuje plik jako both modified (zmieniony po obu stronach). Nic złego się nie stało, Git po prostu potrzebuje Twojej decyzji. Gdy otworzysz plik, zobaczysz w nim specjalne znaczniki:
Te znaczniki wyglądają na skomplikowane, ale mają prostą logikę, którą pokazuje poniższa grafika:
Między <<<<<<< HEAD a ======= znajduje się Twoja wersja (z gałęzi, na której jesteś), a między ======= a >>>>>>> wersja z drugiej gałęzi. Twoim zadaniem jest zostawić w pliku właściwą treść i skasować wszystkie trzy linie ze znacznikami. Gdy to zrobisz, kończysz scalanie tak samo jak zwykły zapis: dodajesz plik do poczekalni i robisz commit:
I gotowe. Konflikt rozwiązany, gałęzie scalone. Warto zapamiętać, że konflikty pojawiają się tylko wtedy, gdy dwie osoby ruszą dokładnie tę samą linię. W praktyce zdarza się to rzadziej, niż się obawiasz, a gdy już się zdarzy, wiesz teraz dokładnie, co robić.
Czas połączyć się ze światem. Do tej pory cała historia leżała na Twoim dysku. Teraz wyślemy ją na GitHub, żeby mieć kopię w chmurze i móc współpracować z innymi. Załóż darmowe konto na github.com i utwórz tam nowe, puste repozytorium (przyciskiem New). GitHub pokaże Ci jego adres, na przykład https://github.com/twoj-login/moja-strona.git.
Zdalne repozytorium podłączamy poleceniem git remote add origin, gdzie origin to przyjęta nazwa głównego zdalnego repozytorium. Możesz sprawdzić, że repozytorium podłączyło się poprawnie, poleceniem git remote -v - wypisze ono adresy zdalnego repo (fetch i push). Potem wysyłamy całą historię poleceniem git push. Opcja -u origin main przy pierwszym wysłaniu łączy Twoją lokalną gałąź main z tą na serwerze, żeby przy kolejnych razach wystarczyło samo git push:
git remote add origin https://github.com/twoj-login/moja-strona.git
git remote -v
git push -u origin main
Git wypisuje kolejne etapy wysyłki (liczenie i kompresowanie obiektów, zapis) i na końcu [new branch] main -> main, co oznacza, że gałąź pojawiła się na serwerze. Od teraz Twój projekt ma bezpieczną kopię w chmurze.
Gdy dołączasz do istniejącego projektu albo chcesz go pobrać na drugi komputer, używasz git clone. To polecenie ściąga całe repozytorium wraz z pełną historią do nowego folderu:
git clone https://github.com/twoj-login/moja-strona.git
W klonie robimy zmianę i wysyłamy ją na GitHub poleceniem git push. Teraz wyobraź sobie, że to kolega wysłał zmianę, a Ty chcesz ją pobrać do siebie. Najpierw git fetch sprawdza, co nowego pojawiło się na serwerze (ale niczego jeszcze nie zmienia u Ciebie), a git status pokazuje wtedy, że Twoja gałąź jest behind, czyli w tyle za serwerem:
Na koniec git pull pobiera zmiany i od razu scala je z Twoją wersją. Możesz myśleć o tym tak: git pull to git fetch (sprawdź, co nowego) plus git merge (dołącz to do mnie) w jednym poleceniu. W codziennej pracy zespołowej wygląda to zwykle tak: rano robisz git pull, żeby pobrać zmiany innych, pracujesz, robisz commity, a na koniec dnia git push, żeby podzielić się swoimi.
Na koniec dwie rzeczy, które oddzielają porządne repozytorium od bałaganu. Pierwsza to plik .gitignore. Nie wszystko z folderu projektu powinno trafić do Gita: pliki tymczasowe, hasła, foldery z zależnościami (jak node_modules) czy pliki konfiguracyjne edytora tylko zaśmieciłyby historię. Tworzysz wtedy w głównym folderze plik o nazwie .gitignore i wypisujesz w nim wzorce nazw, które Git ma ignorować:
# pliki i foldery, które Git ma pomijać
node_modules/
*.log
.env
.vscode/
Thumbs.dbOd tej pory Git nie będzie pokazywał tych plików w git status ani ich nie zapisze. Regułą, którą warto wpoić sobie od początku, jest nigdy nie zapisuj w repozytorium haseł ani kluczy. Plik .env z danymi dostępowymi zawsze dopisz do .gitignore.
Druga rzecz to dobre opisy commitów. Opis poprawki nic nie mówi za pół roku. Dobry opis w kilku słowach wyjaśnia, co commit wnosi, na przykład Dodaj formularz kontaktowy albo Popraw literówkę w nagłówku. Przyjęło się pisać je w trybie rozkazującym, tak jakby zdanie zaczynało się od słowa ten commit ma.... Dobre commity to prezent dla Ciebie z przyszłości i dla całego zespołu.
Przeszliśmy razem długą drogę: od pustego folderu, przez pierwszy commit, gałęzie i konflikty, aż po współpracę na GitHubie. Na start nie musisz pamiętać wszystkiego. W codziennej pracy wraca kilkanaście poleceń, a resztę znajdziesz, gdy będzie potrzebna. Oto ściąga, którą warto mieć pod ręką:
Najlepszym sposobem na naukę Gita jest po prostu używanie go. Załóż repozytorium dla dowolnego swojego projektu, choćby notatek albo małej strony, i rób commity za każdą sensowną zmianę. Po tygodniu polecenia wejdą Ci w krew, a po miesiącu nie wyobrazisz sobie pracy bez Gita. A gdy poczujesz, że chcesz opanować Gita naprawdę solidnie, razem z pracą zespołową, strategiami gałęzi i integracją z narzędziami, na których stoi nowoczesne wytwarzanie oprogramowania, warto zrobić to pod okiem trenera.
Git to pierwszy klocek większej układanki. Jeśli myślisz o karierze w DevOps albo chcesz uporządkować sposób, w jaki Twój zespół wytwarza oprogramowanie, zobacz nasze praktyczne szkolenia prowadzone na żywo z trenerem.
Jeśli chcesz ogarnąć cały warsztat DevOps od podstaw, zacznij od naszego Kompleksowego wprowadzenia do DevOps w formie warsztatowej. To najszersza ścieżka: od Gita, przez Bash i Ansible, po Dockera, Kubernetes, potoki CI/CD i monitoring. W kilka dni układamy Ci w głowie cały nowoczesny sposób wytwarzania i wdrażania oprogramowania, ćwicząc na żywo z trenerem praktykiem. Szkolenie ma terminy gwarantowane, czyli takie, które odbywają się niezależnie od liczby zapisanych osób.
Kompleksowe wprowadzenie do DevOps -->
Kompleksowe szkolenie DevOps z GitHub Actions, Jenkins, Terraform, AWS i Ansible prowadzi Cię od kontroli wersji, przez automatyzację budowania i wdrażania, aż po zarządzanie infrastrukturą w chmurze. Pięć dni intensywnej praktyki, po których samodzielnie zbudujesz pełny potok CI/CD. Szkolenie ma terminy gwarantowane, czyli takie, które odbywają się niezależnie od liczby zapisanych osób.
Szkolenie DevOps z GitHub Actions, Jenkins, Terraform, AWS i Ansible -->
Wolisz najpierw solidnie opanować sam fundament? Szkolenie GIT - kontrola wersji oprogramowania to praktyczny kurs, na którym przejdziesz od podstaw do pewnej pracy zespołowej: gałęzie, scalanie, rozwiązywanie konfliktów, praca ze zdalnym repozytorium i dobre praktyki, których używa się w prawdziwych projektach. Zajęcia prowadzimy na żywo z trenerem praktykiem.
Komentarze (0)
Brak komentarzy...