Jak sprawdzić, czy zdalna gałąź istnieje w danym zdalnym repozytorium?


106

Muszę wykonać scalenie poddrzewa dla określonej gałęzi, jeśli istnieje w danym zdalnym repozytorium. Problem polega na tym, że repozytorium zdalne nie jest pobierane lokalnie, więc nie mogę go użyć git branch -r. Mam tylko zdalny adres, coś takiego https://github.com/project-name/project-name.git. Czy istnieje sposób na wyświetlenie zdalnych oddziałów tylko przez zdalny adres? Nie znalazłem nic przydatnego :(

Odpowiedzi:


124
$ git ls-remote --heads git@github.com:user/repo.git branch-name

W przypadku branch-nameznalezienia otrzymasz następujące dane wyjściowe:

b523c9000c4df1afbd8371324083fef218669108        refs/heads/branch-name

W przeciwnym razie żadne wyjście nie zostanie wysłane.

Więc podłączenie go do wcda ci 1lub 0:

$ git ls-remote --heads git@github.com:user/repo.git branch-name | wc -l

Alternatywnie możesz ustawić --exit-codeflagę, git ls-remotektóra zwróci kod zakończenia, 2jeśli nie zostaną znalezione żadne pasujące referencje. To najbardziej idiomatyczne rozwiązanie. Wynik można sprawdzić bezpośrednio w teście powłoki lub sprawdzając zmienną statusu $?.

$ git ls-remote --exit-code --heads  git@github.com:user/repo.git branch-name

7
Użyłem, git ls-remote --heads ${REPO} ${BRANCH} | grep ${BRANCH} >/dev/nulla następnieif [ "$?" == "1" ] ; then echo "Branch doesn't exist"; exit; fi
sibaz

1
Szukałem tej zgrabnej i precyzyjnej odpowiedzi przez kilka godzin, genialne.
medik

Musisz określić nazwę oddziału jako /refs/heads/branch-name. W przeciwnym razie gałąź foo/branch-namezostanie zwrócona, nawet jeśli nie ma branch-name.
FuzzY

Gratulacje za złotą odznakę „Świetna odpowiedź”. :)
jmort253

4
Uwaga: jeśli nie chcesz określać adresu URL repozytorium, możesz zamiast tego podać nazwę zdalnego repozytorium, np .:git ls-remote --heads origin branch-name
daveruinseverything

50
git ls-remote --heads https://github.com/rails/rails.git
5b3f7563ae1b4a7160fda7fe34240d40c5777dcd    refs/heads/1-2-stable
81d828a14c82b882e31612431a56f830bdc1076f    refs/heads/2-0-stable
b5d759fd2848146f7ee7a4c1b1a4be39e2f1a2bc    refs/heads/2-1-stable
c6cb5a5ab00ac9e857e5b2757d2bce6a5ad14b32    refs/heads/2-2-stable
e0774e47302a907319ed974ccf59b8b54d32bbde    refs/heads/2-3-stable
13ad87971cc16ebc5c286b484821e2cb0fc3e3b1    refs/heads/3-0-stable
3df6c73f9edb3a99f0d51d827ef13a439f31743a    refs/heads/3-1-stable
f4db3d72ea564c77d5a689b850751ce510500585    refs/heads/compressor
c5a809e29e9213102351def7e791c3a8a67d7371    refs/heads/deps_refactor
821e15e5f2d9ef2aa43918a16cbd00f40c221e95    refs/heads/encoding
8f57bf207ff4f28fa8da4544ebc573007b65439d    refs/heads/master
c796d695909c8632b4074b7af69a1ef46c68289a    refs/heads/sass-cleanup
afd7140b66e7cb32e1be58d9e44489e6bcbde0dc    refs/heads/serializers

Nie wiedziałem też o ls-remote. Dziękuję Ci!
Keen

7
Musiałem zrobić test w skrypcie basha, więc byłem naprawdę zainteresowany tylko kodem wyjścia, więc zrobiłem następujące w lokalnym klonie: git ls-remote --exit-code . origin/branch-name &> /dev/nullnastępnie użyłem $?jako operandu testowego
Darren Bishop

5
@Darren, samo użycie polecenia bezpośrednio w warunku, tak jak w przypadku if git ls-remote ...; then ...; fi, jest mniej podatne na błędy niż sprawdzanie $?(co można zmienić, logując instrukcje, pułapki itp.).
Charles Duffy

Dlaczego --heads?
Steve

@JohnLinux --headswyświetla tylko gałęzie. użyj tylko --tagsdo wyświetlenia tagów.
rymo

19

Innym sposobem, którego możesz użyć w bieżącym folderze, jeśli jest to repozytorium git do uruchomienia

git branch -a | egrep 'remotes/origin/${YOUR_BRANCH_NAME}$'

2
Użyj cudzysłowów:git branch -a | egrep "remotes/origin/${YOUR_BRANCH_NAME}$"
Ivan

3
Nie jest to optymalne, ponieważ zwróci wartość true, nawet jeśli dopasowałeś tylko część istniejącej nazwy gałęzi, ale nie pasowałeś dokładnie do gałęzi docelowej. Dlatego nie można tego bezpiecznie użyć w skrypcie do sprawdzenia, czy gałąź istnieje przed jej sprawdzeniem. Mimo wszystko dziękuję za udostępnienie, ponieważ uznałem to za przydatne. Można to naprawić w ten sposób:git branch -a | grep "\b${BRANCH}$"
EntangledLoops

2
git fetchjest wymagane, jeśli używasz, git branch -awięc wszystkie referencje pilota są pobierane jako pierwsze. W przeciwnym razie użyj, git ls-remotejak wskazali inni.
hIpPy

git branch -a --list '<pattern>'jest również opcją. Potwierdź do grep, jeśli potrzebujesz kodu powrotu dla swojego skryptu.
LOAS

17

Możesz również użyć tego:

git show-branch remotes/origin/<<remote-branch-name>>

zwraca ostatnie zatwierdzenie i wartość $? czy 0 w przeciwnym razie zwraca „fatal: bad sha1 reference remotes / origin / <>” i wartość $? jest 128


Nie spowoduje to ściągnięcia gałęzi ze zdalnego przed sprawdzeniem, więc nie otrzymasz najnowszego stanu zdalnego.
siemanko

11

Możesz zrobić coś takiego w terminalu Bash. Po prostu zastąp echa poleceniami, które chcesz wykonać.

if git ls-remote https://username:password@github.com/project-name/project-name.git | grep -sw "remote_branch_name" 2>&1>/dev/null; then echo "IT EXISTS..START MERGE" ; else echo "NOT FOUND" ; fi

Mam nadzieję, że to pomoże.


1
Lubię to. inne odpowiedzi też mają ls-remote, to co mi się podoba to "if".
Stony

11

Dzięki temu nie ma potrzeby ręcznego przekazywania nazwy repozytorium za każdym razem.

git ls-remote origin <branch>

Zamiast

git ls-remote <full repo url> <branch>

Przykład:

git ls-remote git@bitbucket.org:landmarkgroupme/in-store-application.git  uat_21dec

LUB

git ls-remote origin uat_21dec

Oba dadzą ten sam wynik:

wprowadź opis obrazu tutaj

Więcej o Origin : Git wykorzystuje koncepcję „pilotów”, które są po prostu adresami URL do innych kopii Twojego repozytorium. Kiedy klonujesz inne repozytorium, Git automatycznie tworzy zdalne źródło o nazwie „pochodzenie” i wskazuje na nie. Możesz zobaczyć więcej informacji o pilocie, wpisując git remote show origin.


11

Wszystkie odpowiedzi są specyficzne dla powłoki Linuksa, co nie pomaga zbytnio, jeśli jesteś w środowisku, które nie obsługuje tego rodzaju operacji - na przykład wiersz polecenia systemu Windows.

Na szczęście git ls-remoteakceptuje --exit-codeargument, który zwraca 0 lub 2 w zależności od tego, czy gałąź istnieje, czy nie. Więc:

git ls-remote --exit-code --heads origin <branch-that-exists-in-origin>

zwróci 0, a

git ls-remote --exit-code --heads origin <branch-that-only-exists-locally>

zwróci 2.

W przypadku programu PowerShell można po prostu użyć wbudowanej semantyki obsługi prawdziwości:

if (git ls-remote --heads origin <branch-that-exists-in-origin>) { $true } else { $false }

plony $true, podczas gdy:

if (git ls-remote --heads origin <branch-that-only-exists-locally>) { $true } else { $false }

plony $false.


6
$ git ls-remote --heads origin <branch> | wc -l

działa przez większość czasu.

Ale nie zadziała, jeśli gałąź pasuje częściowo, jak poniżej,

$ git branch -a
creative/dev
qa/dev

$ git ls-remote --heads origin dev | wc -l
2

Posługiwać się

git ls-remote --heads origin <branch> | \
    cut -d$'\t' -f2 | \
    sed 's,refs/heads/,,' | \
    grep ^<branch>$ | wc -l

jeśli chcesz niezawodny sposób.

Jeśli chcesz użyć w skrypcie i nie chcesz zakładać originjako domyślnego pilota, to

git ls-remote --heads $(git remote | head -1) "$branch" | \
    cut -d$'\t' -f2 | \
    sed 's,refs/heads/,,' | \
    grep ^"$branch"$ | wc -l

powinno działać.

Zauważ, że git branch -a | grep ...nie jest to niezawodne, ponieważ może upłynąć trochę czasu od ostatniego fetchuruchomienia.


Dla mnie jest to akceptowana odpowiedź, w połączeniu z tą od Amitesh (krótka zdalna nazwa), w połączeniu z tą od Jamesa Cache ( grep -x "$branch"jest identyczna grep ^"$branch"$). Chociaż w skryptach Wolę długo postać przełącza: --line-regexp. Nie ma też takiej potrzeby wc -l. Umieszczenie pustego wyjścia w Bash if [ -z ] efektywnie ocenia jako prawdę, więc oznacza, że ​​gałąź nie istnieje. To oszczędza kilka milisekund.
Amedee Van Gasse

1

Możesz dodać repozytorium, które masz jako zdalne, używając, git remote add something https://github.com/project-name/project-name.gita następnie zrobić, git remote show somethingaby uzyskać wszystkie informacje o pilocie. Wymaga to połączenia sieciowego i jest przydatne do użytku przez ludzi.

Alternatywnie zrób plik git fetch something. Spowoduje to pobranie wszystkich gałęzi na zdalnym wywołaniu somethingi przechowywanie ich w lokalnym repozytorium. Następnie możesz scalić je w swoim lokalnym oddziale według własnego uznania. Polecam tę drogę, ponieważ jeśli w końcu zdecydować, że mają do seryjnej, to co trzeba zrobić.

OT: Twoje użycie „wyewidencjonowany lokalnie” wskazuje, że podchodzisz do tego z punktu widzenia scentralizowanego systemu kontroli wersji. To zwykle ślepy zaułek, gdy masz do czynienia z gitem. Używa słów takich jak „do kasy” itp. Inaczej niż w starszych systemach.


Dzięki za wyjaśnienia. Nie przyzwyczaiłem się jeszcze do gita, a to wymaga innego sposobu myślenia.
Keen

1

Możesz spróbować

git diff --quiet @{u} @{0}

Tutaj @{u}odnosi się do remote / upstream i @{0}odnosi się do aktualnego lokalnego HEAD (w nowszej wersji gita @{0}można skrócić jako @). Jeśli pilot nie istnieje, wyświetla błąd.

Z git 2.16.2 (nie jestem pewien, która wersja ma tę funkcjonalność jako pierwsza, na przykład git 1.7.1 jej nie ma), możesz

git checkout

Jeśli istnieje zdalna gałąź, pojawi się jakiś wynik, na przykład

Your branch is up to date with 'origin/master'

W przeciwnym razie nie ma wyjścia.


1

Zwróci wszystkie gałęzie (zdalne lub lokalne), które zawierają zapytanie w nazwie.

git branch --all | grep <query>


0

Jeśli nazwy twoich gałęzi są bardzo szczegółowe, może nie być konieczne używanie grep do prostego dopasowywania nazw gałęzi:

git ls-remote --heads $(git remote | head -1) "*${BRANCH_NAME}*" | \
    cut -d$'\t' -f2 | \
    sed 's,refs/heads/,,' | \
    wc -l

który działa dla

BRANCH=master
BRANCH=mas
BRANCH=NonExistingBranch (returns 0)
BRANCH=ISSUE-123

Używamy unikalnego identyfikatora wydania jako nazw gałęzi i działa dobrze.


0

Właśnie spróbowałem tego:

git ls-remote --heads 2>/dev/null|awk -F 'refs/heads/' '{print $2}'|grep -x "your-branch"|wc -l

Zwróci to 1, jeśli zostanie znaleziona gałąź „twoja-gałąź”, a 0 w przeciwnym razie.


0

Łączę niektóre z powyższych odpowiedzi w skrypcie:

BRANCHES=(develop master 7.0 7.0-master)
ORIGIN=bitbucket
REMOTE=github

for BRANCH in "${BRANCHES[@]}"; do
  BRANCH=$(git ls-remote --heads "${ORIGIN}" "${BRANCH}" \
      | cut --delimiter=$'\t' --fields=2 \
      | sed 's,refs/heads/,,' \
      | grep --line-regexp "${BRANCH}")
  if [ -n "${BRANCH}" ]
  then
    git branch --force "${BRANCH}" "${ORIGIN}"/"${BRANCH}"
    git checkout "${BRANCH}"
    git push "${REMOTE}" "${BRANCH}"
  fi
done

git push github --tags

Ten skrypt pobierze 4 gałęzie ze zdalnego bitbucketu i wypchnie je na zdalny github, a następnie prześle wszystkie tagi do github. Używam tego w zadaniu Jenkinsa, dlatego nie widzisz żadnego git fetchlub git pulljest to już zrobione w konfiguracji repozytorium zadań Jenkinsa.

Zwykle wolę długie opcje w skryptach. Mógłbym połączyć git branchi git checkoutużywając git checkout -B.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.