git branch, fork, fetch, merge, rebase i clone, jakie są różnice?

Czy ktoś może mi pomóc zrozumieć różnicę między gałęzią, widelcem i klonem w Git?

Podobnie, co to znaczy, gdy robię git fetch w przeciwieństwie do git pull?

Co oznacza rebase w porównaniu do merge?

Jak mogę zgnieść poszczególne zobowiązania razem?

Jak są używane, dlaczego są używane i co reprezentują?

Jak działa GitHub?

Author: IlyaK, 2010-07-25

5 answers

Klon jest po prostu kopią repozytorium. Na pozór, jego wynik jest równoważny svn checkout, gdzie pobiera się kod źródłowy z innego repozytorium. Różnica między scentralizowanymi VC, takimi jak Subversion, a DVCSs, takimi jak Git, polega na tym, że w Git, podczas klonowania, kopiujesz całe repozytorium źródłowe, w tym całą historię i gałęzie. Masz teraz nowe repozytorium na swoim komputerze i wszelkie commity, które wykonasz, trafiają do tego repozytorium. Nikt nie zobaczy żadnych zmian, dopóki ty nie wypychaj zmiany do innego repozytorium (lub oryginalnego) lub dopóki ktoś nie wyciągnie zmian z twojego repozytorium, jeśli jest ono publicznie dostępne.

Gałąź jest czymś, co znajduje się w repozytorium. Koncepcyjnie reprezentuje nić rozwoju. Zazwyczaj masz gałąź master, ale możesz również mieć gałąź, w której pracujesz nad jakąś funkcją xyz, i inną, która naprawia abc błędu. Gdy sprawdzisz gałąź, wszelkie commity, które wykonasz, pozostaną w tej gałęzi i nie będą współdzielone z innymi gałęziami, dopóki nie połączysz ich z nimi lub nie przerobisz ich na daną gałąź. Oczywiście, Git wydaje się trochę dziwny, jeśli chodzi o gałęzie, dopóki nie przyjrzysz się bazowemu modelowi implementacji gałęzi. Zamiast wyjaśniać to sam (już powiedziałem za dużo, myślę), podam link do" informatycznego " wyjaśnienia jak Git modeluje gałęzie i commity, zaczerpnięte z Gita strona internetowa:

Http://eagain.net/articles/git-for-computer-scientists/

Widelec nie jest koncepcją Gita, jest raczej ideą polityczno-społeczną. Oznacza to, że jeśli niektórzy ludzie nie są zadowoleni ze sposobu działania projektu, mogą wziąć kod źródłowy i pracować nad nim samodzielnie, niezależnie od oryginalnych programistów. To byłby widelec. Git ułatwia rozwidlanie, ponieważ każdy ma już swoją "master" kopię kodu źródłowego, więc jest to tak proste, jak cięcie więzi z oryginalnymi deweloperami projektu i nie wymaga eksportowania historii ze współdzielonego repozytorium, jak może mieć to związek z SVN.

EDIT: ponieważ nie byłem świadomy współczesnej definicji "widelca", używanej przez strony takie jak GitHub, proszę spojrzeć na komentarze, a także odpowiedź Michaela Durranta poniżej mojej, aby uzyskać więcej informacji.

 355
Author: siride,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:20

Git

moja odpowiedź obejmuje github, jak wielu ludzi pytało o to zbyt.

Lokalne Repozytoria

Git (lokalnie) posiada katalog (.git), do którego zatwierdzasz swoje pliki i jest to Twoje "lokalne repozytorium". Różni się to od systemów takich jak svn, w których natychmiast dodajesz i zatwierdzasz do zdalnego repozytorium.

Git przechowuje każdą wersję pliku, która zmienia się przez zapisanie całego pliku. Różni się również od svn w pod tym względem można przejść do dowolnej wersji bez "odtworzenia" jej poprzez zmiany delty.

Git w ogóle nie blokuje plików i w ten sposób unika 'wyłącznej blokady' dla edycji (przychodzą na myśl starsze systemy, takie jak PVC), więc wszystkie pliki mogą być zawsze edytowane, nawet gdy są wyłączone. To naprawdę robi niesamowite zadanie scalania zmian plików (w tym samym pliku!) razem podczas ściągania lub pobierania / wypychania do zdalnego repozytorium, takiego jak github. The only time you need to do zmiany ręczne (w rzeczywistości edytowanie pliku) są wtedy, gdy dwie zmiany dotyczą tej samej linii kodu.


Gałęzie

Gałęzie pozwalają zachować główny kod (gałąź 'master'), wykonać kopię (nową gałąź), a następnie pracować w tej nowej gałęzi. Jeśli praca zajmuje trochę czasu lub master otrzymuje wiele aktualizacji od czasu utworzenia gałęzi, należy wykonać scalanie lub rebasing (często preferowane dla lepszej historii i łatwiejszego rozwiązywania konfliktów) przeciwko gałęzi master. Kiedy po zakończeniu scalasz zmiany wprowadzone w gałęzi z powrotem do głównego repozytorium. Wiele organizacji używa gałęzi dla każdego elementu pracy, niezależnie od tego, czy jest to funkcja, błąd czy element obowiązkowy. Inne organizacje używają oddziałów tylko do dużych zmian, takich jak uaktualnienia wersji. Fork: za pomocą gałęzi kontrolujesz i zarządzasz gałęzią, podczas gdy za pomocą forka ktoś inny kontroluje przyjmowanie kodu z powrotem.
Ogólnie rzecz biorąc, istnieją dwa główne podejścia do robienia branż. Pierwszym jest utrzymanie większość zmian w gałęzi głównej, używa tylko gałęzi dla większych i dłużej działających rzeczy, takich jak zmiany wersji, w których chcesz mieć dwie gałęzie dostępne dla różnych potrzeb. Drugi polega na tym, że zasadniczo tworzysz gałąź dla każdego żądania funkcji, naprawy błędów lub obowiązków, a następnie ręcznie decydujesz, kiedy faktycznie połączyć te gałęzie w główną gałąź master. Chociaż brzmi to żmudnie, jest to wspólne podejście i jest to, które obecnie używam i polecam, ponieważ utrzymuje master branch cleaner i jest to master, który promujemy do produkcji, więc chcemy tylko ukończonego, przetestowanego kodu, poprzez rebasing i łączenie gałęzi.

Standardowym sposobem wprowadzenia gałęzi "w" do mistrza jest wykonanie merge. Gałęzie mogą być również rebase d, aby "wyczyścić" historię. Nie wpływa na obecny stan i ma na celu nadanie "czystszej" historii. Zasadniczo chodzi o to, że rozgałęziasz się z pewnego punktu (zwykle od mistrza). Skoro sam "Mistrz" się poruszył naprzód. Byłoby więc czystsze, gdyby wszystkie zmiany, które zrobiliście w gałęzi, były rozgrywane przeciwko najnowszemu mistrzowi ze wszystkimi jego zmianami. Tak więc proces jest następujący: Zapisz zmiany; uzyskaj" nowy " master, a następnie ponownie zastosuj zmiany ponownie przeciwko temu. Pamiętaj, że rebase, podobnie jak merge, może powodować konflikty, które musisz ręcznie rozwiązać (edytować).

Jedna 'wskazówka' do zapamiętania: tylko rebase, jeśli gałąź jest lokalna i nie przesunąłeś jej jeszcze do zdalnego! to jest głównie dlatego, że rebasing może zmienić historię, którą widzą inni ludzie, która może zawierać własne commity.

Oddziały śledzenia

Są to gałęzie o nazwie origin/branch_name (w przeciwieństwie do samej nazwy gałęzi). Kiedy wciskasz i ciągniesz kod do / z repozytoriów zdalnych, jest to mechanizm, za pomocą którego tak się dzieje. Na przykład, gdy git push jest gałąź o nazwie 'building_groups', twoja gałąź przechodzi najpierw do origin / building_groups, a następnie idzie do zdalnego repozytorium (faktycznie to przesadne uproszczenie, ale na razie wystarczająco dobre). Podobnie jeśli wykonasz git fetch building_groups pobrany plik zostanie umieszczony w gałęzi origin / building_groups. Następnie możesz połączyć tę gałąź z lokalną kopią. Nasza praktyka polega na tym, aby zawsze wykonywać git fetch i Manual merge, a nie tylko git pull (który wykonuje oba powyższe kroki w jednym kroku).

Fetching nowe oddziały.

[[40]}zdobywanie nowych gałęzi: w początkowym punkcie klon będziesz miał wszystkie gałęzie. Jeśli jednak inni programiści dodają gałęzie i wypchną je do pilota, musi istnieć sposób, aby "wiedzieć" o tych gałęziach i ich nazwach, aby móc je ściągać lokalnie. Odbywa się to za pomocą git fetch, który pobierze wszystkie nowe i zmienione gałęzie do lokalnego repozytorium za pomocą gałęzi śledzących (np. origin/). Po fetched, można git branch --remote wymienić gałęzie śledzenia i git checkout [branch] faktycznie przełączyć się na dowolny jeden.

Scalanie

Scalanie jest procesem łączenia zmian kodu z różnych gałęzi lub z różnych wersji tej samej gałęzi (na przykład gdy lokalna gałąź i zdalna nie są zsynchronizowane.). Jeśli ktoś rozwinął pracę w gałęzi i praca jest kompletna, gotowa i przetestowana, to można ją połączyć w gałąź master. Jest to wykonywane przez git checkout master, aby przełączyć się do gałęzi master, a następnie git merge your_branch. Połączenie spowoduje wprowadzenie wszystkich różnych plików i nawet różnych zmian do tych samych plików razem. Oznacza to, że faktycznie zmieni kod wewnątrz plików, aby scalić wszystkie zmiany. Podczas wykonywania checkout z master zaleca się również wykonanie git pull origin master, aby uzyskać najnowszą wersję zdalnego wzorca połączoną z lokalnym wzorcem. Jeśli zdalny master się zmienił, tj. moved forward, zobaczysz informacje, które odzwierciedlają to podczas git pull. W takim przypadku (master changed) zaleca się git checkout your_branch, a następnie rebase to master, aby twoje zmiany w rzeczywistości uzyskać "powtórkę" na szczycie "nowego" mistrza. Następnie kontynuujesz pobieranie master-to-date, jak pokazano w następnym akapicie.

Jeśli nie ma konfliktów, master będzie miał dodane nowe zmiany. Jeśli występują konflikty, oznacza to, że te same pliki mają zmiany wokół podobnych linii kodu, których nie można automatycznie scalić. W tym przypadku git merge new_branch zgłosi, że istnieje konflikt(y) do rozwiązania. "Rozwiązujesz" je edytując pliki (które będą miały zarówno zmiany w nich), wybierając zmiany, które chcesz, dosłownie usuwając wiersze zmian, których nie chcesz, a następnie zapisując plik. Zmiany są oznaczone separatorami, takimi jak ======== i <<<<<<<<

Gdy już rozwiążesz wszelkie konflikty, będziesz ponownie git add i git commit te zmiany, aby kontynuować scalanie (podczas tego procesu otrzymasz informacje zwrotne od Gita, które Cię poprowadzą). Gdy proces nie działa dobrze, przekonasz się, że git merge --abort jest bardzo przydatny do resetowania rzeczy.

Interaktywny rebasing i zgniatanie / Zmiana kolejności / usuwanie commitów

Jeśli wykonałeś pracę w wielu małych krokach, np. zatwierdzasz kod jako 'work-in-progress' każdego dnia, możesz chcieć "zmiażdżyć" te wiele małych commitów w kilka większych commitów. Może to być szczególnie przydatne, gdy chcesz robić recenzje kodu ze współpracownikami. Nie chcesz odtworzyć wszystkich 'kroków', które wykonałeś (poprzez commity), chcesz tylko powiedzieć, że oto efekt końcowy (diff) wszystkich moich zmiany dla tej pracy w jednym commicie. Kluczowym czynnikiem do oceny przy rozważaniu, czy to zrobić, jest to, czy wiele commitów dotyczy tego samego pliku lub Plików więcej niż jeden raz (lepiej w takim przypadku usunąć commity). Odbywa się to za pomocą interaktywnego narzędzia rebasing. To narzędzie pozwala na squash commity, delete commity, reword messages, itp. Na przykład git rebase -i HEAD~10 zauważ, że jest to ~ a nie -
interaktywny rebasing w Git Bądź jednak ostrożny i używaj tego narzędzia "ostrożnie". Wykonaj jeden squash/delete/reorder na raz, wyjdź i zapisz ten commit, a następnie ponownie uruchom narzędzie. Jeśli commity nie są sąsiadujące ze sobą, możesz zmienić ich kolejność (a następnie squash w razie potrzeby). Możesz również tutaj usunąć commity, ale naprawdę musisz mieć pewność, co robisz, gdy to robisz!

Widły

Istnieją dwa główne podejścia do współpracy w repozytoriach git. Pierwszy, opisany powyżej, jest bezpośrednio przez gałęzie, które ludzie ciągną i pchają Z / do. Współpracownicy ci mają ich klucze SSH zarejestrowane w zdalnym repozytorium. To pozwoli im przejść bezpośrednio do tego repozytorium. Minusem jest to, że musisz utrzymywać listę użytkowników. Inne podejście-forking-pozwala każdemu na "rozwidlenie" repozytorium, zasadniczo tworząc lokalną kopię na swoim własnym koncie repozytorium git. Następnie mogą wprowadzać zmiany i po zakończeniu wysyłać "pull request" (tak naprawdę jest to bardziej "push" od nich i "pull" dla rzeczywistego opiekuna repozytorium), aby uzyskać kod akceptuję.
Ta druga metoda, używająca forków, nie wymaga od kogoś prowadzenia listy użytkowników dla repozytorium.


Github

Github (zdalne repozytorium) jest zdalnym źródłem, do którego normalnie push i pull te wprowadzone zmiany, jeśli masz (lub są dodawane) takie repozytorium, więc lokalne i zdalne są w rzeczywistości całkiem różne. Innym sposobem myślenia o zdalnym repozytorium jest to, że jest to .struktura katalogów git, która żyje na zdalny serwer.

Kiedy 'fork' - w gui przeglądarki github możesz kliknąć na Tutaj wpisz opis obrazka - tworzysz kopię ('klon') kodu w na swoim koncie github. Może to być trochę subtelne za pierwszym razem, więc upewnij się, że przyjrzysz się, pod czyim repozytorium znajduje się baza kodu - albo oryginalnemu właścicielowi, albo "oddzieliłeś" i tobie, np. {108]} {56]} Gdy masz lokalną kopię, możesz wprowadzać zmiany według własnego uznania (ciągnąc je i popychając do lokalnej maszyny). Kiedy skończysz, wysyłasz "pull request" do oryginalnego właściciela repozytorium/administratora (brzmi to fantazyjnie, ale w rzeczywistości po prostu klikasz na to:- Tutaj wpisz opis obrazka)i oni "wciągają" go.
Bardziej powszechne dla zespołu pracującego razem nad kodem jest "sklonowanie" repozytorium (kliknij ikonę "Kopiuj" na głównym ekranie repozytorium). Następnie wpisz lokalnie git clone [paste] to ustawi Cię lokalnie i możesz również wypchnąć i pociągnąć do (współdzielonej) lokalizacji github.

Klony

Jak wskazano w sekcja na GitHubie, klon jest kopią repozytorium. Gdy masz zdalne repozytorium, wydajesz polecenie git clone na jego adres URL, a następnie kończysz z lokalną kopią lub klonem repozytorium. Ten klon zawiera wszystko , pliki, gałąź master, pozostałe gałęzie, wszystkie istniejące commity, cały shebang. To właśnie z tym klonem robisz swoje adds and commits przeciwko, a następnie samo zdalne repozytorium jest tym, do czego pchasz te commity. To jest to lokalna / zdalna koncepcja, która sprawia, że git (i podobne do niego systemy, takie jak Mercurial) jest systemem DVCS (Distributed Version Control System) w przeciwieństwie do bardziej tradycyjnych systemów CVs (Code Versioning Systems), takich jak SVN, PVCS, CVs, itp. gdzie commit bezpośrednio do zdalnego repozytorium.

Wizualizacja

Wizualizację podstawowych pojęć można zobaczyć na
http://marklodato.github.com/visual-git-guide/index-en.html oraz
http://ndpsoftware.com/git-cheatsheet.html#loc=index

Jeśli chcesz zobaczyć, jak działają zmiany, nie możesz pokonać narzędzia wizualnego gitg (gitx for mac) z gui, które nazywam "mapą metra" (esp. London Underground), świetne do pokazania, kto co zrobił, jak rzeczy się zmieniają, rozchodzą się i łączą itp.

Można go również używać do dodawania, zatwierdzania i zarządzania zmianami !

interfejs gitg/gitx

Chociaż gitg / gitx jest dość minimalny, w w ciągu ostatnich 2-3 lat (2009-2012) liczba narzędzi gui nadal rośnie. Wiele użytkowników komputerów Mac korzysta z widelca gitx, a dla Linuksa świetną opcją jest smart-git z intuicyjnym, ale potężnym interfejsem: {]}

smart-git GUI

Zauważ, że nawet z narzędziem gui, prawdopodobnie wykonasz wiele poleceń w wierszu poleceń.
Do tego mam następujące aliasy w moim~/.plik bash_aliases (który jest wywoływany z mojego ~/.plik bashrc dla każdego terminala sesja:

# git
alias gst='git status' # Warning: gst conflicts with gnu-smalltalk (when used).
alias gb='git branch'
alias gco='git checkout'
alias gcob='git checkout -b '
alias ga='git add '
alias gc='git commit'
alias gg='git grep ' #  A great very FAST search option, easier then `find`

Wreszcie, 6 kluczowych ratowników:

1) psujesz lokalny oddział i po prostu chcesz wrócić do tego, co miałeś ostatnim razem, gdy zrobiłeś git pull:

git reset --hard origin/master  # You will need to be comfortable doing this!

2) zaczynasz wprowadzać zmiany lokalnie, edytujesz pół tuzina plików, a potem, o cholera, nadal jesteś w gałęzi master (lub innej):

git checkout -b new_branch_name  # just create a new branch
git add .                      # add the changes files
git commit -m"your message"    # and commit them

3) psujesz jeden konkretny plik w bieżącej gałęzi i chcesz w zasadzie "zresetować" ten plik (stracić zmiany) do tego, jak był ostatnio wyciągnąłeś go ze zdalnego repozytorium: git checkout your/directories/filename to rzeczywiście resetuje plik (podobnie jak wiele komend Gita, nie jest on dobrze nazwany dla tego, co tutaj robi).

4) dokonujesz pewnych zmian lokalnie, chcesz mieć pewność, że ich nie stracisz podczas resetowania lub rebase ' u Gita: często robię ręczną kopię całego projektu (cp -r ../my_project ~/), kiedy nie jestem pewien, czy mogę zepsuć w git lub stracić ważne zmiany.

5) rebasingujesz, ale sprawy się popsuły:

git rebase --abort # To abandon interactive rebase and merge issues

6) Dodaj twoja gałąź git do monitu PS1 (zobacz https://unix.stackexchange.com/a/127800/10043 ), np. Tutaj wpisz opis obrazka
Oddział jest selenium_rspec_conversion

 516
Author: Michael Durrant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-23 20:47:40

Oto obraz Olivera Steele ' a, jak to wszystko do siebie pasuje:

Tutaj wpisz opis obrazka

 140
Author: Contango,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-11 11:58:24

Aby dodać do innych, notkę specyficzną dla forkingu.

Dobrze jest zdać sobie sprawę, że technicznie klonowanie repo i rozwidlanie repo to to samo. Do:
git clone $some_other_repo
I możesz się stuknąć w plecy - - - właśnie rozwidlałeś inne repo. Git, jako VCS, jest w rzeczywistości o klonowanie rozwidlanie. Oprócz "przeglądania" za pomocą zdalnego interfejsu użytkownika, takiego jak cgit, istnieje bardzo niewiele wspólnego z git repo, które nie wymaga rozwidlania klonowania repo w pewnym momencie.

Jednakże

  • Kiedy ktoś mówi ja rozwidlałem repo X, oznacza to, że stworzyli klon repo gdzie indziej z zamiarem ujawnić to innych, na przykład, aby pokazać niektóre eksperymenty, lub zastosować różne mechanizm kontroli dostępu (np. aby umożliwić ludziom bez dostępu do Githuba, ale z wewnętrznym kontem firmy do współpracy).

    Fakty, że: repo jest najprawdopodobniej tworzony za pomocą innego polecenia niż git clone, że najprawdopodobniej jest hostowany gdzieś na serwerze jako w przeciwieństwie do czyjegoś laptopa i najprawdopodobniej ma nieco inny format (jest to "gołe repo", tj. bez drzewa roboczego) są tylko DANE TECHNICZNE.

    Fakt, że najprawdopodobniej będzie zawierać różne zestawy gałęzi, tagi lub commity są najprawdopodobniej powodem, dla którego zrobili to w pierwszym miejsce.

    (Co robi Github po kliknięciu "fork" , to tylko klonowanie z dodanym sugar: klonuje repo dla Ciebie, umieszcza go pod Twoje konto, zapisy "rozwidlony od", dodaje zdalny o nazwie "upstream" , a większość co ważne, odtwarza ładną animację.)

  • Kiedy ktoś mówi sklonowałem repo X , oznacza to, że stworzył klon repo lokalnie na swoim laptopie lub komputerze stacjonarnym z zamiarem Studiuj go, baw się nim, przyczyniaj się do niego lub buduj coś ze źródła kod w nim.

Piękno Gita polega na tym, że to wszystko idealnie do siebie pasuje: wszystkie te repozytoria Udostępnij wspólną część bloku łańcucha zatwierdzeń, aby możliwe było bezpieczne (patrz uwaga poniżej) scalanie zmian tam i z powrotem między wszystkimi tymi repo według własnego uznania.

Uwaga: "bezpiecznie", o ile nie zmienisz wspólnej części łańcucha i o ile zmiany nie będą sprzeczne.

 6
Author: Alois Mahdal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-26 18:02:52

Fork Vs. Clone-dwa słowa, które oba oznaczają copy

Zobacz ten schemat . (oryginalnie z http://www.dataschool.io/content/images/2014/Mar/github1.png).

.-------------------------.     1. Fork     .-------------------------.
| Your GitHub repo        | <-------------- | Joe's GitHub repo       |
| github.com/you/coolgame |                 | github.com/joe/coolgame |
| ----------------------- | 7. Pull Request | ----------------------- |
| master -> c224ff7       | --------------> | master -> c224ff7 (c)   |
| anidea -> 884faa1 (a)   |                 | anidea -> 884faa1 (b)   |
'-------------------------'                 '-------------------------'
    |                 ^
    | 2. Clone        |
    |                 |
    |                 |
    |                 |
    |                 |
    |                 | 6. Push (anidea => origin/anidea)
    v                 |
.-------------------------.
| Your computer           |  3. Create branch 'anidea'
| $HOME/coolgame          |
| ----------------------- |  4. Update a file
| master -> c224ff7       |
| anidea -> 884faa1       |  5. Commit (to 'anidea')
'-------------------------'

(a) - after you have pushed it
(b) - after Joe has accepted it
(c) - eventually Joe might merge 'anidea' (make 'master -> 884faa1')

Widelec

    Jest to jedna z najbardziej rozpoznawalnych postaci w świecie gier komputerowych.]} W tym celu należy wykonać kopię, którą można następnie sklonować do lokalnego repo i F * % $ - up
  • Kiedy skończysz, możesz przesunąć z powrotem do pilota
  • możesz zapytać Joe jeśli chce użyć go w swoim projekcie, klikając pull-request

Klon

    W tym celu należy skontaktować się z Działem obsługi klienta.]}
 5
Author: Timothy L.J. Stewart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-06 18:14:09