Dlaczego mogę kasować oddział, który został usunięty z GitHub?

26

W naszym repozytorium GitHub współpracownik usunął gałąź o nazwie release. Ale kiedy uruchamiam git checkout releaselokalnie, zawsze otrzymuję usuniętą gałąź release. To samo, nawet gdy sprawdziłem inną gałąź, usunąłem releasegałąź git branch -D releasei uruchomiłem ponownie git checkout release.

Czy jest coś do naprawienia w repozytorium GitHub, czy powinienem naprawić coś lokalnie?

Tim
źródło
1
Co git branch --remotegeneruje po uruchomieniu git fetch? Konieczne może być przycięcie, git fetch -paby zapomnieć o usuniętych zdalnych gałęziach.
Stephen Kitt
2
Jeśli gałąź ta została kiedykolwiek przekazana do GitHub, a następnie została wyciągnięta, masz również kopię gałęzi. Każde repozytorium git jest kompletne samo w sobie, chyba że użyłeś płytkiego klonu lub czegoś takiego.
muru
@StephenKitt: Dzięki. git branch --remotewyjście origin/release. Czy chcesz uruchomić git fetch -pbez dodatkowych argumentów i czy spowoduje to przycięcie wszystkich usuniętych zdalnych gałęzi?
Tim
1
Tak, git fetch -pbez dodatkowych argumentów przycina wszystkie usunięte zdalne gałęzie.
Stephen Kitt
1
Witamy w świecie rozproszonej kontroli wersji!
Chrylis

Odpowiedzi:

24

Po usunięciu gałęzi po stronie zdalnej możesz nadal zobaczyć lokalnie wcześniej pobraną gałąź lokalną, patrz:

$ git branch -a
[...]
release
remotes/origin/release
[...]

Usunąłeś tylko „wydanie”, ale nie „piloty / pochodzenie / wydanie”. Usuń to w ten sposób:

$ git branch -rd origin/release

Lub usuń wszystkie pobrane gałęzie, które już nie istnieją po drugiej stronie:

$ git remote prune origin 
rudimeier
źródło
Dzięki. W git branch -rd origin/releaseto, co robi -rśrednią? Czy to -dznaczy tak samo jak -D? Można git branch -rd origin/releasezastąpić git branch -d remotes/origin/release?
Tim
@Tim: Z instrukcji; -R List or delete (if used with -d) the remote-tracking branches.; -D:Shortcut for --delete --force.
looper
Dzięki. Można git branch -rd origin/releasezastąpić git branch -d remotes/origin/release?
Tim
@Tim nie -rodnosi się do zdalnych oddziałów, jest potrzebny. Lokalne i zdalne oddziały są przechowywane w różnych katalogach, porównują ls -l .git/refs/headsi ls -l .git/refs/remotes. Możesz także mieć lokalny oddział o nazwie, bez remotes/origin/releasektórego można by usunąć -r. To może wydawać się mylące, ale możesz po prostu bawić się, tworzyć gałęzie o dziwnych nazwach i patrzeć, jak to wygląda .git/.
rudimeier
15

Gdy oddziały są usuwane zdalnie, musisz przyciąć swoje lokalne repozytorium - najłatwiej to zrobić

git fetch -p

Spowoduje to zaktualizowanie lokalnego repozytorium ze wszystkimi zmianami wprowadzonymi w zdalnym repozytorium, ale bez aktualizacji żadnego z lokalnych oddziałów. Po uruchomieniu tego

git branch --remote

nie będzie już wyświetlać usuniętej zdalnej gałęzi.

repozytoria git są kompletne, zarówno w twoim systemie, jak i na serwerze. Kiedy więc po raz pierwszy sklonujesz repozytorium, otrzymasz pełną kopię, a lokalny git „wie” o wszystkich zdalnych gałęziach, a także o lokalnych oddziałach. Informacje te nie są synchronizowane automatycznie, więc kiedy twój kolega usunął releasegałąź na serwerze, lokalne repozytorium git nie straciło pojęcia zdalnego releaseoddziału. Synchronizacja z git fetchaktualizacjami powoduje, że wszystkie lokalne informacje w zdalnych oddziałach są zgodne ze stanem na serwerze (ściśle mówiąc, zdalne repozytorium, gdziekolwiek to jest), ale bez usuwania jakichkolwiek lokalnych informacji w zdalnych oddziałach. Przycinanie za pomocą git fetch -p(lub git fetch --prunelub git remote prune) usuwa lokalne informacje ze zdalnych gałęzi, które zostały usunięte.

Stephen Kitt
źródło
Dzięki. „zaktualizuj lokalne repozytorium o wszystkie zmiany wprowadzone w zdalnym repozytorium, ale bez aktualizacji żadnego z lokalnych oddziałów”. Co to za aktualizacja, biorąc pod uwagę, że nie jest to aktualizacja moich lokalnych oddziałów?
Tim
To wszystkie zdalne aktualizacje. Twoje lokalne repozytorium git odróżnia twoje lokalne gałęzie i zdalne gałęzie, ale zdalne gałęzie nie są magicznie synchronizowane z serwerem - istnieją również lokalnie (jak w, przechowywane w twoim lokalnym repozytorium git). Pobieranie pobiera synchronizuje lokalne repozytorium ze zdalnym repozytorium i aktualizuje stan zdalnych gałęzi; domyślnie usunięte zdalne gałęzie nie są usuwane z lokalnych informacji w zdalnych gałęziach, -p( --prune) wymusza to.
Stephen Kitt
Dzięki. Dlaczego nie usuwając releaseoddział przez git branch -D releaseprzed git checkout releasemake git checkout releasecoraz przystanku releaseoddział?
Tim
1
Ponieważ git checkout releaseautomatycznie utworzy gałąź, jeśli istnieje gałąź zdalna o tej nazwie.
Stephen Kitt
Czy przez „zdalną gałąź” rozumiesz gałąź w moim lokalnym repozytorium lub repozytorium Github? Jeśli poprzedni, git branch -D releasejuż usunął releasegałąź w moim lokalnym repozytorium; Jeśli to drugie, współpracownik usunął releasegałąź na GitHub; Więc nadal nie jestem pewien, dlaczego „automatycznie utworzy gałąź, jeśli istnieje gałąź zdalna o tej nazwie”?
Tim
3

Tim: Git jest dystrybuowany VCS, więc kiedy klonujesz repozytorium ze zdalnego do lokalnego, klonuje wszystko (historię). Kiedy więc sklonowałeś swoje repozytorium, miało ono gałąź zwaną release. Ponieważ Twój kolega zdalnie usunął gałąź wydania, dopóki nie wykonasz przycinania git fetch -plub nie usuniesz tej gałęzi jawnie, lokalny będzie miał tę gałąź.

ManiVI
źródło
3
Czym różni się ta odpowiedź od odpowiedzi już obecnych?
Stephen Rauch
1

Być może nieco styczna, ale perspektywa tej strony może pomóc zrozumieć ogólny temat usuwania gałęzi:

http://railsware.com/blog/2014/08/11/git-housekeeping-tutorial-clean-up-outdated-branches-in-local-and-remote-repositories/

Częściowo pokrywają się z tym, co już tu omówiono, ale nacisk kładziony jest na prowadzenie domu: usuwanie oddziałów, zdalnych i lokalnych, które nie są już potrzebne w środowisku współpracy. W szczególności git branch --mergedpolecenie identyfikuje gałęzie, które można bezpiecznie usunąć z powodu połączenia z linią główną (lub dowolną gałęzią, na której Ci zależy). Jeśli współpracujesz, niektóre bardziej wyrafinowane mini skrypty, takie jak ten, prezentują rzeczy w przyjemnym, łatwym do zrozumienia formacie z datami i autorami.

for branch in `comm -12  <(git branch --merged|awk '{print($1)}') <(git branch -r --merged|awk '{print($1)}'|awk -F \/ '{print($2)}')`; do echo -e `git show --format="%ci %cr %an" $branch | head -n 1` \\t$branch; done | sort -r

(Niestety „miły, strawny” nie dotyczy formatowania samych skryptów).

Warstwa B.
źródło