piątek, 22 maja 2015

[GIT] Klonowanie repozytorium, zdalne repozytoria i klucze SSH

TRUE
7463796078999611238
Prawdziwą magią Gita jest możliwość współdzielenia kodu i praca zespołowa. W poprzedniej części nauczyliśmy się tworzyć własne repozytorium na lokalnym komputerze i pracy z nim, a teraz nauczymy się aspektów pracy z repozytoriami udostępnianymi przez innych programistów. Nauczymy się także w jaki sposób pracować na zdalnym repozytorium, hostowanym np. w serwisie GitHUB. Dowiemy się również na czym polega uwierzytelnianie i w jaki sposób tworzyć i korzystać z kluczy RSA, które będą wymagane np. do pracy z GitHUB-em.

Wiele projektów/aplikacji udostępnianych na licencji Open Source udostępnia swój kod w serwisach takich jak GitHUB (GIT), czy Google Code (SVN).
Wiele z takich projektów jest również w taki sposób rozwijanych, gdzie każdy chętny może dodawać swoje własne funkcjonalności, czy poprawki do czyjegoś kodu. Na czym polega sklonowanie repozytorium? W skrócie polega ono na sklonowaniu go ;) A dokładniej - na naszym dysku tworzona jest LOKALNA KOPIA repozytorium, na której możemy dowolnie pracować, a po skończonej pracy możemy wrzucić wszystkie stworzone lokalnie zmiany do oryginalnego, głównego repozytorium na serwerze, z którego dokonaliśmy sklonowania - jeśli oczywiście posiadamy takie uprawnienia.

Co jeśli takich uprawnień nie mamy? Bo przecież zapewne domyślamy się już, iż żaden programista nie pozwoli nam na dowolną modyfikację jego kodu bez jego zgody. Jak więc to wygląda w praktyce? Otóż - jeśli pracujemy na nie swoim repozytorium, to wszelkie zmiany, które dokonamy w kodzie lokalnie możemy osobie zarządzającej wysłać i zasugerować. Właściciel repozytorium, lub osoba uprawniona dostaje wtedy informację z żadaniem/prośbą dołączenia naszego kodu, np. z poprawkami do głównej gałęzi repozytorium. Może taką prośbę zignorować, albo zaakceptować zmiany jakie wprowadziliśmy i dołączyć naszą proponowaną gałąź do gałęzi głównej projektu.

A co jeśli pracujemy na swoim repozytorium, tyle że hostowanym na zdalnym serwerze, jak np. GitHUB?
Otóż w tym przypadku jako osoby uprawnione do pracy nad repozytorium (w końcu jest to nasze repozytorium) możemy pracować na nim dowolnie. Jak jednak wygląda sprawa "powiedzenia Gitowi", że mamy do danego repozytorium pełny dostęp? Otóż polega na zasadzie wymiany kluczy kryptograficznych. Rzecz polega na wygenerowaniu pary dwóch kluczy: klucza publicznego i klucza prywatnego. Klucz publiczny wysyłamy na serwer, na którym trzymamy nasze repozytorium np. na GitHUB-a, natomiast klucz prywatny trzymamy na swoim roboczym komputerze i pilnujemy ;) Następnie, w momencie połączenia przez SSH, pary kluczy są porównywane i na tej zasadzie określane jest, czy mamy dostęp do danego zasobu.
Kluczy oczywiście można dodać kilka - dla kilku osób, które będą miały uprawnienia do danego repo (jeśli pracujemy np. w teamie). O kluczach przeczytamy więcej kilka akapitów dalej.

Uwierzytelnianie może polegać też na zwykłym HTTPS, nie tylko za pomocą SSH.

1) git clone - czyli klonowanie repozytorium

Sklonujmy sobie testowe repozytorium.
Zapewne spotkaliśmy się już z terminem sklonuj repozytorium. Jeśli nie, to zaraz się spotkamy ;)
GitHUB udostępnia testowe repozytorium, które jest stworzone właśnie w celach demonstracyjnych i do nauki. Znajduje się ono pod adresem: https://github.com/octocat/Spoon-Knife
Jak widzimy zawiera ono 3 pliki:

  • README.md
  • index.html
  • styles.css




Nad listą plików znajduje się rozwijana lista z dostępnymi gałęziami (branches).
Jak widzimy przeglądamy domyślnie gałąź główną - master.
Pod listą plików znajduje się treść pliku README.md, który o ile istnieje w repozytorium, to jest tutaj zawsze wyświetlany.

Po prawej natomiast mamy to co nas interesuje, czyli link do repozytorium, umożliwiający nam jego sklonowanie.
Tuż pod nim znajdują się jeszcze 2 opcje:

  • Clone in Desktop (służacy do sklonowania przez aplikację GitHUB-a, o ile taką posiadamy)
  • Download ZIP (zwykłe pobranie repozytorium w postaci archiwum zip)

Nas interesuje link do sklonowania, zaznaczmy go i skopiujmy do schowka.
Ma on postać: https://github.com/octocat/Spoon-Knife.git

Tutaj mała uwaga: każdy taki link do repozytorium GIT-a będzie się kończył końcówką .git.
Nie oznacza to jednak, że to co będziemy pobierać będzie plikiem Spoon-Knife.git.
Jest to jedynie umowne nazewnictwo prowadzące tak naprawdę do całego repozytorium, w którym znajduje się o wiele więcej plików.

Utwórzmy teraz testowy folder, do którego sklonujemy sobie to repozytorium, niech będzie to np. C:/cloned_repo, następnie wejdżmy do niego:
[code]$ mkdir C:/cloned_repo
$ cd C:/cloned_repo[/code]
i sklonujmy tutaj repozytorium za pomocą polecenia git clone:
[code]$ git clone https://github.com/octocat/Spoon-Knife.git[/code]

Jak widzimy, repozytorium sklonowało się do naszego folderu:
[code]C:/cloned_repo/Spoon-Knife[/code]
Wejdźmy w nie i wylistujmy pliki, jak widać wszystko odbyło się poprawnie i mamy swoją własną lokalną kopię repozytorium:

Jak tez widać, domyślną gałęzią na jakiej w tej chwili pracujemy jest master. Wpiszmy teraz:
[code]$ git checkout[/code]
Pojawi nam się komunikat:
Your branch is up-to-date with 'origin/master'.



Wymaga to małego wytłumaczenia:
Informacja ta mówi nam, że gałąź jaką tu mamy jest aktualna z tą, która znajduje się w repozytorium na serwerze. Załóżmy jednak, że jutro ktoś dokona tam zmian - nasza lokalna kopia będzie zatem nieaktualna, gdyż w oryginalnym repozytorium nastąpiły jakieś zmiany. Musimy więc ręcznie pobrać najnowszą, aktualną wersję repozytorium, a robimy to poleceniem:
[code]$ git fetch origin master[/code]
Polecenie takie pobiera nam aktualną wersję gałęzi master z repozytorium origin.
Skąd jednak wzięło się tutaj to origin i co ono oznacza?
Otóż origin to nazwa repozytorium źródłowego - tego z którego klonowaliśmy.
Wygląda więc to tak: nasza lokalna główna gałąź to master, natomiast główna, źródłowa gałąź na serwerze zawsze będzie to origin/master.

Jedziemy dalej.
Pobraliśmy aktualną wersję z gałęzi origin/master, natomiast musimy dokonać jeszcze jednego manewru: musimy pobraną gałąź scalić z naszą lokalną gałęzią master. Robimy to komendą:
[code]$ git merge origin master[/code]
Od tej chwili mamy aktualną lokalną kopię repozytorium.

git pull

Po co jednak dwa poprzednie polecenia wykonywać oddzielnie?
Istnieje komenda, która jednocześnie pobiera i scala najnowszą wersję repozytorium z naszą lokalną wersją:
[code]$ git pull origin master[/code]



i takiej właśnie komendy polecam używać.

To wszystko.
Mamy gotowe do dalszej pracy repozytorium, z którym robić możemy co tylko zapragniemy - tworzyć gałęzie, modyfikować pliki, dodawać nowe - wszystko dokładnie tak jak podczas pracy z repozytorium utworzonym za pomocą git init.
Dokonajmy zatem jakiś modyfikacji.
Dodajmy np. nowy plik o nazwie new_feature.php i dodajmy go do repozytorium:
Plik możemy utworzyć w konsoli za pomocą polecenia touch nazwa_pliku, zawartość katalogu listujemy komendą ls.
[code]$ touch "new_feature.php"
$ ls
$ git add "new_feature.php"
$ git commit -a -m "added new feature for test"[/code]


Stworzyliśmy właśnie nową rewizję, jak teraz wysłać zmiany do oryginalnego repozytorium?
Zrobimy to komendą push:

git push

[code]$ git push origin master[/code]
Komenda wysyła nasze zmiany w gałęzi master do repozytorium origin.
Co się jednak dzieje?


Zostajemy poproszeni o nazwę użytkownika i hasło, takowych jednak nie posiadamy.
Tak jak wspomniałem na początku - nie posiadamy tutaj uprawnień do tego repozytorium, posiada je użytkownik GitHUBA o nazwie octocat. Możemy oczywiście napisać do octocata z prośbą o udostępnienie nam hasła do swojego konta, co jednak raczej skwintuje on głębokim śmiechem ;)
Co więc teraz zrobić? Otóż - wykorzystamy mechanizm pull request dostępny na GitHUB-ie, który pozwoli nam na wysłanie prośby o dołączenie naszej gałęzi do źródłowego repozytorium. Zrobimy to jednak później, gdyż wymaga to założenia darmowego konta w serwisie GitHUB, a póki co chcemy przetestować wysyłanie zmian do zdalnego repozytorium.

2) GitHUB

Nieuniknionym jest założenie darmowego konta na GitHUB-ie, aby przejść dalej.
To tylko chwila, a pomoże nam przetestować pracę ze zdalnym repozytorium i kilka innych ciekawych możliwości.

Wchodzimy więc w adres: https://github.com/join i rejestrujemy nowe konto.
Po utworzeniu konta dodamy sobie na GitHUBie swoje włąsne repozytorium.
Gdy już jesteśmy zaogowani do GitHUB-a, wchodzimy w adres: https://github.com/new

Wpisujemy nazwę naszego testowego repozytorium, np. myTestRepo,
zaznaczamy opcję Initialize this repository with a README i klikamy na Create repository.



Mamy już swoje pierwsze repozytorium.
Skopiujmy teraz jego link do sklonowania i sklonujmy je lokalnie:
[code]
$ cd c:/cloned_repo
$ git clone https://github.com/NAZWA_KONTA/myTestRepo.git
$ cd myTestRepo
$ ls[/code]



Jak widać, mamy już kopię lokalną swojego repozytorium z GitHUB-a.
Póki co mamy w nim jedynie plik README.md - jest to główny plik z opisem, który GitHUB wyświetla na stronie podczas wejścia w repozytorium. To zwykły plik tekstowy, tyle tylko, że z rozszerzeniem .md. To też akurat dobra okazja, aby przetestować działanie polecenia pull, które jak pamiętamy, aktualizuje nam lokalne repozytorium do aktualnej wersji.

Na początek otwórzmy plik README.md (z lokalnej kopii, nie na github.com) w dowolnym edytorze tekstowym, zobaczymy coś w stylu:
[code]# myTestRepo
test[/code]



A teraz zmodyfikujmy ten plik w repozytorium na stronie GitHUB-a.
Kliknijmy na nim na liście, a następnie na ikonce edycji:


I wpiszmy tam cokolwiek, np.:



Następnie kliknijmy na Commit changes. Plik w źródłowym repozytorium (origin) zostanie zmodyfikowany. Zajrzyjmy jeszcze raz do jego lokalnej kopii w naszym sklonowanym repozytorium - jak widać, wciąż posiadamy jego poprzednią wersję. Wykonajmy zatem teraz:
[code]$ git pull origin master[/code]
I ponownie zajrzyjmy do naszego lokalnego README.md:



Jak widać, pobraliśmy najnowszą aktualną wersję :)

Teraz w drugą stronę - zmodyfikujmy plik README.md w naszej lokalnej kopii, wpisując mu np. taką zawartość:


Zapiszmy i zacommitujmy zmieniony plik:
[code]$ git commit -a -m "modified on local copy"[/code]
Stworzyliśmy nową rewizję (commita), ale narazie tylko w naszej lokalnej kopii.
W naszym źródłowym, oryginalnym repozytorium na GitHUB-ie wszystko póki co pozostaje bez zmian. Musimy teraz nasze zmiany wysłać na serwer.
Wpiszmy zatem w konsoli:
[code]$ git push origin master[/code]
Zostaniemy poproszeni o nazwę naszego konta i hasło.
Podajmy więc dane na jakie założyliśmy konto w GitHUB-ie i odczekajmy chwilę.


Jeśli wszystko zrobiliśmy poprawnie to nasze repozytorium na GitHUB-ie powinno zostać właśnie zaktualizowane:



3) FORK

Cofnijmy się teraz o kilka akapitów wstecz i wróćmy do problemu z repozytorium niejakiego octopusa ;)
Jak pamiętamy, wprowadziliśmy tam kilka zmian, lecz nie udało nam się ich wysłać do repozytorium źródłowego z powodu braku uprawnień.
Mając już konto na GitHUBie możemy się teraz tym problemem zająć.

Czym jest FORK?
Możemy sobie to przysłowiowo przetłumaczyć jako "wzięcie czegoś na widelec".
W naszym przypadku kilka akapitów wyżej wzięliśmy na widelec repozytorium Spoon-Knife, lecz nie mieliśmy wtedy jeszcze konta na GitHUB-ie.
Tym razem zrobimy to samo, ale za pomocą opcji FORK.
Wejdźmy ponownie na: https://github.com/octocat/Spoon-Knife

i kliknijmy na opcję Fork w prawym, górnym rogu.
Opcja ta doda do naszego konta na GitHUBie lokalną kopię repozytorium Spoon-Knife.



Jak widzimy, od teraz lokalna kopia pojawiła się pod adresem:
[code]https://github.com/NASZE_KONTO/Spoon-Knife[/code]
Możemy teraz sklonować to repozytorium za pomocą git clone.
Zróbmy więc to, przy okazji stwórzmy nowy podfolder, gdyż mamy już jedną kopię Spoon-Knife:
[code]$ cd C:/cloned_repo
$ mkdir github
$ cd github
$ git clone https://github.com/NASZE_KONTO/Spoon-Knife.git
$ cd Spoon-Knife
$ ls[/code]



Mamy sklonowane repozytorium, ale tym razem to repozytorium jest "forkowane" dla naszego konta na GitHUBie.
Dodajmy teraz jakąś zmianę, umieśćmy np. nowy plik: in_fork.txt i spróbujmy teraz wysłać zmiany do origin:
[code]$ touch in_fork.txt
$ git add in_fork.txt
$ git commit -a -m "added in_fork.txt"
$ git push origin master[/code]


Voila! Tym razem się udało!
Powróćmy teraz na: https://github.com/NASZE_KONTO/Spoon-Knife i zobaczmy co się zmieniło.
Jak widać nasze zmiany zostały zatwierdzone w repozytorium.
Pamiętajmy jednak, że jest to jedynie nasza lokalna kopia oryginalnego repozytorium Spoon-Knife.
Jak więc teraz połączyć je z oryginałem?

Musimy wykonać tzw. Pull Request, czyli wysłać prośbę do zarządcy oryginalnym repozytorium o załączenie naszej zmienionej gałęzi do źródłowego kodu.

Klikamy tutaj:


Pojawi nam się okno z modyfikacjami jakich dokonaliśmy i klikamy na View Pull Request.
Nasza prośba została wysłana i zostaniemy (lub nie) poinformowani za jakiś czas o ewentualnej decyzji administratora repozytorium źródłowego.

W widoku naszego requesta możemy w każdej chwili podać więcej informacji, służą do tego komentarze w wątku na dole. Oczywiście tutaj nic takiego nie nastąpi, gdyż Spoon-Knife to tylko demonstracyjne repozytorium, przygotowane jedynie do tego typu testów, jednakże cały mechanizm już dzięki temu znamy.

4) ssh-keygen - generowanie pary kluczy SSH

Jak do tej pory łączyliśmy się za pomocą HTTPS, zobaczymy teraz na czym polega sprawa z kluczami.
Tak jak napisałem na początku, z repozytorium możemy łączyć się przy pomocy SSH (tak robi m.in. aplikacja GitHUB-a, czy Tortoise, o których szerzej w następnych odcinkach). Do połączenia takiego wymagane są dwie pary kluczy - publiczny i prywatny, z czego klucz publiczny wysyłamy na serwer, natomiast klucz prywatny pozostaje na naszej maszynie.

Zobaczymy teraz jak wygenerować taki klucz i załączyć go do naszego konta w serwisie GitHUB.
Skorzystamy z komendy ssh-keygen, która powinna się nam zainstalować razem z Gitem (lub z Putty, o ile go posiadamy). Oczywiście na Windowsie, gdyż na Linuxie polecenie to jest standardowo dostępne wraz z pakietem SSH.

Klucze domyślnie zapisywane są w następujących folderach:

  • ~/.ssh  (na linuxach)
  • /Users/nazwa_użytkownika/.ssh (na Windowsach, folder ukryty)


Para kluczy ma postać:

  • klucz (klucz prywatny)
  • klucz.pub (klucz publiczny)

Wygenerujmy sobie więc parę kluczy:
[code]$ ssh-keygen -t rsa -b 4096[/code]
wygeneruje nam to parę kluczy typu (-t) RSA, o długości (-b) 4096 bitów


Zostaniemy poproszeni o nazwę klucza, domyślnie jet to id_rsa.
Nazwę jednak możemy podać dowolną - pamiętajmy, że razem ze ścieżką, inaczej klucz wygeneruje się w folderze, z którego uruchomiliśmy ssh-keygena.
Następnie generator poprosi o utworzenie hasła do naszego klucza, podajmy je dwukrotnie i porządnie zapamiętajmy - nie będzie możliwości skorzystania z klucza w przyszłości, jeśli zapomnimy hasła. Po odczekaniu chwili nasza para kluczy zostanie wygenerowana.
Interesuje nas teraz zawartość klucza publicznego, czyli pliku:
[code]NAZWA_KLUCZA.pub[/code]
Otwieramy go w dowolnym edytorze tekstowym, kopiujemy całą zawartość, która wygląda mniej więcej tak:
[code]ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCplFzgUhfLhBcXWvhYITElVi0QlV9Ehr0CvoQFEoRBRCfQRfVREm7BO9IExt/RjgwEqNXh/njRabiFt8QkXTiifiDzwZkaWNlcwcWp0R1BxtG1Dj4oHpoUQBu/LZCSArxeIEZV/4hj0wSV/00YmuM1zGp091wsTGy1LqUqzqjtUsbMA0H7HGjtLjA6TlP9yv7E4oIvs6Xj4XrqhcEQIhJc1czFSleT66swho3/BhuGAu/HGuWAxAj15iApq1YGWbYFeHCD33f0etIEvr1U+Sv6hxp30/O6ngUtEdrmOVmVFB9UtITDTDtvHk5Rvc8gWmMYP3GjR+NpxNjaJy/TanZHeOZ4uYUoKhSeMqqqnDdwxb87zydyDWybR9AWKYAa/R8vUSTWf2jC8VC25Fgdxex36tovgK/aG/yF4TVtODNLiKD6xeQl7aToNowPMbunrJc6ELxlA8eYcdI7aNvsuXvPJmbI2v3r6QyfAQYmTRASe6Zn43B6NL3r6kwuABlFAmSOWpEzhWtBmuQ0oggKsiMCg/TorzelwUQv6+BlcpKz8XOIS4n3sRxnldQk+z/5SuaBSsnvW9v1rZ92rRbR1jBiws1RNV1JA/8Bb04ngJORG/zdIPXqtaNo7mXEpdZzFuaHDwP2u1WU4o1jI4xJwL3YZ1V9KCK1gEFZM+XndQUzw==szczyglis@LENOVO-PC[/code]
Następnie wchodzimy do ustawień konta na GitHUBie, w zakładkę SSH keys i wklejamy tam nasz klucz:



To wszystko, od tej pory za pomocą aplikacji takich jak GitHUB Desktop, czy TortoiseGit (które zostaną omówione później) będziemy mieli dostęp do swoich repozytoriów po SSH.

4 komentarze:

  1. Dobry poradnik, dzięki, szukałem właśnie czegoś takiego krok po kroku. A mam pytanie: te klucze muszą być w folderze ssh jeśli będę chciał używać Tortoise? Czy tam się jakoś oddzielnie je dodaje? Bo szczerze mówiąc nie wiem, a kazali mi się na to przesiąść. Pozdrawiam. Mario

    OdpowiedzUsuń
  2. Witam, tak. Klucze RSA powinny być w folderze ~/.ssh (na Linuxach), lub w C:/Users/użytkownik/.ssh (na Windowsach - jeśli system jest na "C:" oczywiście. Odnośnie Tortoise Gita nie będzie potrzeby robienia żadnych innych kombinacji jeśli klucze będą w domyśnym folderze. Tak btw niebawem kolejne części poradnika, m.in. też o używaniu Tortoise. Pozdrawiam.

    OdpowiedzUsuń
  3. Witam bardzo fajnie napisany artykuł/tutek.
    Myślałem, rozwiąże to mój problem ale widzę więcej problemów niż robienie tego co chcę na piechotę.
    Ale do rzeczy, może dasz radę coś zasugerować.
    Pracuję sam, mam kilkadziesiąt hostingów, w dużej mierze zawierają ten sam zestaw plików, różnią się configami bo w nich są dostępy itp.
    Raz na jakiś czas wprowadzam w moim głównym koncie ftp jakąś zmianę w jednym pliku, jak teraz wprowadzić w tą zmianę w sposób automatyczny, bez konieczności kopiowania ręcznego. Są na to jakieś proste metody, zmieniam w jednym miejscu a zmiany pojawiają się na pozostałych lokalizacjach.

    Próbowałem nawet include przez url, ale tam z kolei includuję plik php który ma w sobie include pliku z configiem, i jak includuję na inny serwer to config mam includowany ze źródła a nie z lokalnej ścieżki. Będę wdzięczny za wszelkie sugestie.

    OdpowiedzUsuń
  4. Witam mam wygenerowany domyslny klucz C:/Users/użytkownik/.ssh/id_rsa
    na github mam dodany ten klucz jako deploy key w repozytorium
    lokalny git bezproblemowo współpracuje ze zdalnym repo
    ale gdy wygeneruję klucz o innej nazwie np: C:/Users/użytkownik/.ssh/klucz
    i dodam go do repozytorium na github lokalny git próbuje się zalogować za pomocą klucza id_rsa
    jak zmusić git aby używał innego klucza niż id_rsa ?

    OdpowiedzUsuń

Masz sugestię? Znalazłeś błąd? Napisz komentarz! :)

webmaester.pl - profesjonalne projektowanie WWW i webaplikacji
webmaester.pl - profesjonalne projektowanie WWW i webaplikacji