Dlaczego „stan git” pokazuje, że jestem w gałęzi głównej, a „gałąź git” nie znajduje się w nowo utworzonym repozytorium?

83

Próbuję zautomatyzować proces i wydam git branchpolecenie, aby dowiedzieć się, w której gałęzi jestem. Wszystko działa dobrze, z wyjątkiem nowo zainicjowanego repozytorium, w którym git branchnic nie zwraca. Biorąc pod uwagę, że nic nie zrobiłem z repozytorium, nawet początkowe zatwierdzenie, mogę zaakceptować odpowiedź. Jeśli jednak uruchomię, git statusto powie mi, że jestem na mastergałęzi, jak widać tutaj:

$ mkdir todelete
$ cd todelete
$ git init
Initialized empty Git repository in /u/u70021a/todelete/.git
$ git status
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)
$ git branch
$

czy robię coś źle? Czy jest jakieś ustawienie, którego nie ustawiłem poprawnie?

Mam też kilka nowych osób do Gita i nie mogę im wyjaśnić, dlaczego polecenie pokazujące, w której gałęzi się znajdują, nic nie pokazuje, ale polecenie statusu tak.

GOVarney
źródło

Odpowiedzi:

94

Głosowałem za dwiema innymi odpowiedziami, ale myślę, że sposób myślenia o tym jest prosty: możesz być na gałęzi, która nie istnieje. Jest to również normalne w nowym, pustym repozytorium, ponieważ aby istniała nazwa gałęzi, musi ona istnieć identyfikować identyfikator skrótu istniejącego, prawidłowego zatwierdzenia. Nowe puste repozytorium nie ma zatwierdzeń, więc żadne nazwy gałęzi nie mogą jeszcze istnieć.

Niemniej jednak początkowo jesteś w jakiejś branży. Gałąź, na której się znajdujesz, to ta, której nazwa jest zapisana w specjalnej nazwie HEAD. W nowym, pustym repozytorium, Git przechowuje nazwę master(a dokładniej refs/heads/master- pełną nazwę gałęzi) w HEAD, więc jesteś włączony master, a masternie istnieje.

Możesz zmienić nieistniejącą gałąź, której używasz git checkout -b:

$ git init
Initialized empty Git repository in [path]
$ git checkout -b asdf
Switched to a new branch 'asdf'
$ git checkout -b hello
Switched to a new branch 'hello'

Kiedykolwiek jesteś na gałęzi, która nie istnieje, następne zatwierdzenie, które tworzysz, tworzy gałąź. Tak też git checkout --orphandziała.

torek
źródło
6
Dzięki. Chociaż nie zgadzam się z tym, co wyświetla git. Przynajmniej rozumiem dlaczego. Twój przykład kasy jest interesujący. Zgodnie z dokumentacją dla "git checkout" -b oznacza: Utwórz nową gałąź o nazwie <new_branch>, co nie jest do końca prawdą. W twoim przykładzie ani gałąź asdf, ani hello nie zostały utworzone. Ale tak się stanie, jeśli zostanie wykonane zatwierdzenie. Osobiście uważam, że komunikat „On branch master” powinien zostać zmieniony na „Next Commit to branch master”, ponieważ dopóki nie zostanie wykonane zatwierdzenie, master branch nie istnieje.
GOVarney,
2
Nie jestem pewien, czy jest to istotne dla twojego przypadku, czy nie, ale chcę zaznaczyć, że w przypadku Git możliwe jest, aby w ogóle nie być w żadnej gałęzi.
sklott
Git wewnętrznie używa, cat .git/HEADaby zobaczyć, w której gałęzi się znajduje, ustalenie, że gałąź istnieje, zużywa więcej procesora i czasu dysku, więc prawdopodobnie dlatego tego nie zrobili
Ferrybig
Należy wspomnieć o tym, że w ogóle nie należy używać git branchw zautomatyzowanym procesie, ponieważ nie jest on przeznaczony do tego przypadku użycia. Byłoby interesujące zobaczyć, co pokazują tutaj polecenia inne niż porcelanowe, czy git symbolic-ref --short HEADmają takie samo zachowanie?
Voo
@Voo: git symbolic-refpokazuje nazwę zawartą w HEAD(stąd odniesienie do gałęzi osieroconej / nienarodzonej), pod warunkiem, że HEADnie jest ona odłączona. W nowym pustym repozytorium HEAD nie można odłączyć, ponieważ odłączony HEAD musi zawierać identyfikator skrótu istniejącego, prawidłowego zatwierdzenia. (W niepusty repozytorium z wolnostojącym PRZEWODNICZACEGO, git symbolic-refpowoduje błąd.)
torek
23

git branchnic nie pokazuje, ponieważ nie ma gałęzi. Ale, jak możesz przeczytać w man git init:

To polecenie tworzy puste repozytorium Git - w zasadzie katalog .git z podkatalogami dla obiektów, refs / heads, refs / tags i plików szablonów. Tworzony jest również początkowy plik HEAD, który odwołuje się do HEAD gałęzi głównej.

Pogrubiłem część, która moim zdaniem jest istotna - wygląda na to, że chociaż nie ma jeszcze gałęzi wzorcowej, odniesienie do niej już istnieje i dlatego jest pokazane w git status. Po zatwierdzeniu zostanie utworzona odpowiednia gałąź.

Stanowczo
źródło
3
Wygląda więc na to, że „stan git” wyświetla po prostu „nazwę gałęzi”, jak widać w .git / HEAD (ref: refs / heads / master), ale nie sprawdza spójności, patrząc w .git / refs / heads, aby zobaczyć, czy to faktycznie istnieje.
GOVarney,
Nie mam pewności, ponieważ nie sprawdzałem kodu gita, ale to, co napisałeś, ma dla mnie sens. Ale nadal wolę odpowiedź Torka od mojej :).
Stanowczo
17

Istniejące odpowiedzi odnoszą się do dosłownego pytania, dlaczego dane wyjściowe są tym, czym są, ale myślę, że w pewnym sensie zamknęły one prawdziwy problem ...

Powiedziałeś, że coś automatyzujesz, więc sugerowałbym, że ani git statusnie git branchjest to najlepsze narzędzie w kontekście skryptowania.

W tej dyskusji można znaleźć kilka alternatyw: Jak programowo określić bieżącą pobraną gałąź Git

Nie znając twoich potrzeb (ani tego, jak chciałbyś, aby zachowywała się nienarodzona gałąź), niekoniecznie zalecam, ale chodzi mi o to, że niektóre polecenia są przeznaczone do interakcji z ludźmi (porcelana), a inne do skryptów ( instalacja wodociągowa)

Mark Adelsberger
źródło
15

Gałąź jeszcze się nie narodziła. Dlatego git branchnie pokazuje tego ( git symbolic-ref HEADwskazuje, że HEAD wskazuje na domyślną gałąź master i że jest nienarodzony, ponieważ git branchtego nie pokazuje, tj. Możesz być na gałęzi, która jeszcze nie istnieje). Jednak popełnienie czegoś spowoduje utworzenie gałęzi.

Dzieje się tak również w przypadku płatności w orphanoddziale.

Przypuszczam, że git statuspokazuje nazwę gałęzi, ponieważ jest to gałąź, która zostanie utworzona.

Aby uzyskać informacje na temat skryptów, zobacz Jak programowo określić bieżącą pobraną gałąź Git

MrTux
źródło
2

W git domyślną gałęzią jest master. Kiedy zatwierdzisz, git "użyje" bieżącej gałęzi, na której jesteś teraz. Ponieważ zainicjowałeś nowe repozytorium, jesteś w "domyślnej" gałęzi i dlatego nie widzisz go na liście swoich gałęzi, pojawi się po zatwierdzeniu zmian.

wprowadź opis obrazu tutaj

wprowadź opis obrazu tutaj

CodeWizard
źródło
2
Rozumiem rozgałęzianie, nie rozumiem, dlaczego „status gita” mówi, że jestem na gałęzi, która nie istnieje.
GOVarney,