Podczas pracy z git w zespole używającym gałęzi funkcji często trudno mi zrozumieć strukturę gałęzi w historii.
Przykład:
Powiedzmy, że istniała funkcja gałęzi / make-coffee , a usuwanie błędów było kontynuowane na master równolegle do gałęzi funkcji.
Historia może wyglądać następująco:
* merge feature/make-coffee
|\
| * small bugfix
| |
* | fix bug #1234
| |
| * add milk and sugar
| |
* | improve comments
| |
* | fix bug #9434
| |
| * make coffe (without milk or sugar)
| |
* | improve comments
|/
*
Problem
Na pierwszy rzut oka trudno mi stwierdzić, po której stronie jest gałąź funkcji. Zwykle muszę przejrzeć kilka komentarzy po obu stronach, aby dowiedzieć się, który jest który. Staje się to bardziej skomplikowane, jeśli istnieje wiele gałęzi elementów równolegle (szczególnie jeśli dotyczą one blisko powiązanych elementów) lub jeśli nastąpiło scalenie w obu kierunkach między gałęzią elementów a wzorcem.
Dla kontrastu w Subversion jest to znacznie łatwiejsze, ponieważ nazwa gałęzi jest częścią historii - więc mogę od razu powiedzieć, że zatwierdzenie zostało pierwotnie dokonane na „feature / make-coffee”.
Git mógłby to ułatwić, włączając nazwę bieżącego oddziału do metadanych zatwierdzenia podczas tworzenia zatwierdzenia (wraz z autorem, datą itp.). Jednak git tego nie robi.
Czy istnieje jakiś fundamentalny powód, dla którego tak się nie dzieje? A może po prostu nikt nie chciał tej funkcji? Jeśli to drugie, czy istnieją inne sposoby zrozumienia celu historycznych gałęzi bez poznania nazwy?
Odpowiedzi:
Prawdopodobnie dlatego, że nazwy oddziałów mają znaczenie tylko w jednym repozytorium. Jeśli jestem w
make-coffee
zespole i prześlę wszystkie moje zmiany za pośrednictwem strażnika, mojamaster
gałąź może zostać przyciągnięta domake-coffee-gui
gałęzi strażnika , który połączy się ze swojąmake-coffee-backend
gałęzią, zanim przejdzie domake-coffee
gałęzi, która zostanie scalona zmaster
gałęzią centralną .Nawet w obrębie jednego repozytorium nazwy oddziałów mogą się zmieniać w miarę ewolucji przepływu pracy.
master
może się później zmienićdevelopment
na przykład w celu wywołaniaJak wspomniał CodeGnome, git ma silną filozofię projektowania polegającą na tym, że nie zapisuje czegoś w danych, jeśli nie jest to potrzebne. Oczekuje się, że użytkownicy skorzystają z opcji
git log
igit diff
wyprowadzą dane według własnych upodobań. Zalecam wypróbowanie go, dopóki nie znajdziesz formatu, który będzie dla Ciebie lepszy.git log --first-parent
, na przykład, nie pokaże zatwierdzeń z łączonego oddziału.źródło
Śledź historię oddziału za pomocą
--no-ff
W Git, zatwierdzenie ma przodków, ale „gałąź” jest tak naprawdę tylko obecnym szefem jakiejś linii rozwoju. Innymi słowy, zatwierdzenie jest migawką działającego drzewa w pewnym momencie i może należeć do dowolnej liczby gałęzi jednocześnie. Jest to część tego, co sprawia, że rozgałęzienia Git są tak lekkie w porównaniu do innych DVCS.
Zatwierdzenia Git nie niosą informacji o oddziale, ponieważ nie są one niezbędne do historii Git. Jednak połączenia, które nie są szybkie, mogą z pewnością zawierać dodatkowe informacje o tym, który oddział został scalony. Możesz upewnić się, że twoja historia zawiera te informacje, zawsze przekazując
--no-ff
flagę do twoich połączeń. git-merge (1) mówi:Generalnie spowoduje to utworzenie wiadomości scalającej podobnej do
Merge branch 'foo'
, dzięki czemu zwykle można znaleźć informacje o „gałęziach przodków” w linii podobnej do następującej:źródło
git log --merges
.Najprostsza odpowiedź jest taka, że nazwy gałęzi są ulotne. Co by było, gdyby, powiedzmy, zmienić nazwę oddziału (
git branch -m <oldname> <newname>
)? Co stałoby się ze wszystkimi zobowiązaniami wobec tego oddziału? A jeśli dwie osoby mają oddziały o tej samej nazwie w różnych lokalnych repozytoriach?Jedyną rzeczą, która ma znaczenie w git, jest suma kontrolna samego zatwierdzenia. Jest to podstawowa jednostka śledzenia.
Informacja jest tam, po prostu jej nie pytasz i nie jest dokładnie tam.
Git przechowuje sumę kontrolną głowy każdego oddziału w
.git/refs/heads
. Na przykład:(tak, spycham sumy kontrolne git, to nie jest specjalne, ale są to prywatne repozytoria, na które patrzę w tej chwili, w których nie trzeba mieć przypadkowego wycieku).
Patrząc na to i śledząc wstecz wszystkie zatwierdzenia, które mają to jako rodzic, rodzic-rodzic lub rodzic-rodzic ... możesz dowiedzieć się, w jakich gałęziach znajduje się dane zatwierdzenie. To tylko duży wykres do renderowania.
Przechowywanie tam, gdzie konkretnie jest nazwa gałęzi (która może ulec zmianie, jak wspomniano powyżej), zatwierdzenie znajduje się w samym zatwierdzeniu, jest dodatkowym narzutem na zatwierdzeniu, które mu nie pomaga. Przechowuj elementy nadrzędne zatwierdzenia i jego dobra.
Możesz zobaczyć gałęzie, uruchamiając polecenie git log z odpowiednią flagą.
Istnieje wiele różnych sposobów wybierania tego, co chcesz - spójrz do dokumentacji dziennika git -
-all
sekcji i kilku poniższych opcji.„Test”, „test1” i „test2” są gałęziami, do których zostały zobowiązane.
Zauważ, że dokumentacja dziennika git jest ogromna i całkiem możliwe jest uzyskanie z niej prawie wszystkiego, co chcesz.
źródło
Dlaczego polecenia git nie zawierają nazwy gałęzi, w której zostały utworzone?
Tylko decyzja projektowa. Jeśli potrzebujesz tych informacji, możesz dodać haczyk przygotuj-zatwierdzenie-msg lub zatwierdzenie-msg, aby wymusić to w pojedynczym repozytorium.
Po katastrofie BitKeepera Linus Torvalds opracował git, aby pasował do procesu rozwoju jądra Linuksa. Tam, dopóki łatka nie zostanie zaakceptowana, jest ona kilkakrotnie poprawiana, edytowana, polerowana (przez pocztę), podpisywana (= edycja zatwierdzenia), wybierana przez wiarę, wędrowanie do oddziałów porucznika może być często zmieniane, więcej edycji, wiśnia - wybiera i tak dalej, aż w końcu zostaną połączone przez Linusa.
W takim przepływie pracy może nie istnieć określone pochodzenie zatwierdzenia, a często zatwierdzenie jest właśnie tworzone w jakiejś tymczasowej gałęzi debugowania w jakimś nieistotnym prywatnym repozytorium losowym ze śmiesznymi nazwami gałęzi, gdy git jest dystrybuowany.
Być może ta decyzja projektowa wydarzyła się przypadkowo, ale dokładnie pasuje do procesu rozwoju jądra Linux.
źródło
Ponieważ w Git zatwierdzenia, takie jak „zaparz kawę”, są uważane za część obu gałęzi, gdy gałąź funkcji jest scalona. Istnieje nawet polecenie, aby to sprawdzić:
Ponadto gałęzie są tanie, lokalne i eteryczne; można je łatwo dodawać, usuwać, zmieniać nazwy, wypychać i usuwać z serwera.
Git działa zgodnie z zasadą, że wszystko można zrobić, dlatego możesz łatwo usunąć gałąź ze zdalnego serwera i łatwo przepisać historię.
Powiedzmy, że byłem w gałęzi „master” i dokonałem dwóch zatwierdzeń: „zrób kawę” i „dodaj mleko i cukier”, a następnie zdecydowałem się użyć do tego nowej gałęzi, więc resetuję „master” z powrotem do „pochodzenia” /mistrz'. Nie ma problemu, cała historia jest wciąż czysta: „rób kawę” i „dodaj mleko i cukier” nie są częścią master, tylko funkcja / robienie kawy.
Mercurial jest przeciwieństwem; nie chce niczego zmieniać. Gałęzie są stałe, historia pisania nie jest mile widziana, nie można po prostu usunąć gałęzi z serwera.
W skrócie: Git pozwala ci robić wszystko, Mercurial chce ułatwić ci wszystko (i naprawdę utrudnia ci robienie tego, co chcesz).
źródło