Come verificare se esiste un ramo remoto su un dato repository remoto?


106

Devo fare un'unione di sottostruttura per un ramo specifico, se esiste su un dato repository remoto. Il problema è che il repository remoto non viene estratto localmente, quindi non posso usarlo git branch -r. Tutto quello che ho è un indirizzo remoto, qualcosa del genere https://github.com/project-name/project-name.git. C'è un modo per elencare i rami remoti solo tramite un indirizzo remoto? Non sono riuscito a trovare nulla di utile :(

Risposte:


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

Nel caso in cui branch-namevenga trovato, otterrai il seguente output:

b523c9000c4df1afbd8371324083fef218669108        refs/heads/branch-name

Altrimenti non verrà inviato alcun output.

Quindi convogliarlo wcti darà 1o 0:

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

In alternativa è possibile impostare un --exit-codeflag su git ls-remotecui restituirà il codice di uscita 2nel caso in cui non vengano trovati riferimenti corrispondenti. Questa è la soluzione più idiomatica. Il risultato può essere verificato direttamente in un test di shell o controllando la variabile di stato $?.

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

7
Ho usato git ls-remote --heads ${REPO} ${BRANCH} | grep ${BRANCH} >/dev/nullseguito daif [ "$?" == "1" ] ; then echo "Branch doesn't exist"; exit; fi
sibaz

1
Stavo cercando questa risposta chiara e precisa per alcune ore, brillante.
medik

È necessario specificare il nome del ramo come /refs/heads/branch-name. Altrimenti, il ramo foo/branch-nameverrebbe restituito anche quando non ci sono branch-name.
FuzzY

Congratulazioni per il tuo badge d'oro "Ottima risposta". :)
jmort253

4
Nota: se non si desidera specificare l'URL del repository, è possibile specificare invece il nome remoto del repository, ad esempio: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

Non sapevo nemmeno di ls-remote. Grazie!
Keen

7
Avevo bisogno di fare un test in uno script bash e quindi ero veramente interessato solo al codice di uscita, quindi ho fatto quanto segue in un clone locale: git ls-remote --exit-code . origin/branch-name &> /dev/nullpoi usato $?come operando di test
Darren Bishop

5
@ Darren, semplicemente usando il comando direttamente in un condizionale, come con if git ls-remote ...; then ...; fi, è meno soggetto a errori rispetto al controllo $?(che può essere modificato registrando istruzioni, trap, ecc.).
Charles Duffy

Perché il --heads?
Steve

@JohnLinux --headselenca solo i rami. utilizzare --tagsper elencare solo i tag.
rymo

19

Un altro modo che puoi usare nella cartella corrente se si tratta di un repository git da eseguire

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

2
Usa le virgolette doppie:git branch -a | egrep "remotes/origin/${YOUR_BRANCH_NAME}$"
Ivan

3
Questo non è ottimale perché restituirà true anche se hai trovato solo una parte del nome di un ramo esistente, ma non corrispondeva esattamente al ramo di destinazione. Quindi questo non può essere utilizzato in modo sicuro in uno script per verificare se il ramo esiste prima di verificarlo. Grazie per la condivisione comunque, poiché l'ho trovato utile. Può essere risolto in questo modo:git branch -a | grep "\b${BRANCH}$"
EntangledLoops

2
git fetchè necessario se si utilizza in git branch -amodo che tutti i ref dei telecomandi vengano recuperati per primi. Altrimenti utilizzare git ls-remotecome indicato da altri.
hIpPy

git branch -a --list '<pattern>'è anche un'opzione. Invia pipe a grep se hai bisogno di un codice di ritorno per il tuo script.
LOAS

17

Puoi anche usare questo:

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

restituisce l'ultimo commit e il valore di $? è 0 altrimenti restituisce "fatal: bad sha1 reference remotes / origin / <>" e il valore di $? è 128


Questo non estrarrà i rami dal telecomando prima del controllo, quindi non otterrai lo stato remoto più recente.
siemanko

11

Puoi fare qualcosa di simile nel terminale Bash. Sostituisci semplicemente gli echi con i comandi che vuoi eseguire.

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

Spero che sia d'aiuto.


1
Mi piace. altre risposte hanno anche ls-remote, quello che mi piace è il "se".
Stony

11

Quindi non è necessario passare manualmente il nome del repository ogni volta.

git ls-remote origin <branch>

Invece di

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

Esempio :

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

O

git ls-remote origin uat_21dec

Entrambi daranno lo stesso output:

inserisci qui la descrizione dell'immagine

Altro su Origin : Git ha il concetto di "telecomandi", che sono semplicemente URL di altre copie del tuo repository. Quando cloni un altro repository, Git crea automaticamente un nome remoto "origin" e punta ad esso. Puoi visualizzare ulteriori informazioni sul telecomando digitando git remote show origin.


11

Tutte le risposte qui sono specifiche della shell di Linux, il che non aiuta molto se ti trovi in ​​un ambiente che non supporta questo tipo di operazioni, ad esempio il prompt dei comandi di Windows.

Fortunatamente git ls-remoteaccetta un --exit-codeargomento che restituisce 0 o 2 a seconda che il ramo esista o meno, rispettivamente. Così:

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

restituirà 0 e

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

tornerà 2.

Per PowerShell, puoi semplicemente usare la semantica di gestione della verità incorporata:

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

produce $true, mentre:

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

rendimenti $false.


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

funziona la maggior parte del tempo.

Ma non funzionerà se il ramo corrisponde parzialmente come sotto,

$ git branch -a
creative/dev
qa/dev

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

Uso

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

se vuoi un modo affidabile.

Se si desidera utilizzare in script e non si desidera assumere origincome remoto predefinito, allora

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

dovrebbe funzionare.

Nota che git branch -a | grep ...non è affidabile in quanto potrebbe essere necessario un po 'di tempo dall'ultima fetchesecuzione.


Per me, questa è la risposta accettata, combinata con quella di Amitesh (nome breve remoto), combinata con quella di James Cache ( grep -x "$branch"è identica a grep ^"$branch"$). Anche se negli script Io preferisco il long-form interruttori: --line-regexp. Inoltre, non è necessario farlo wc -l. Mettere un output vuoto in un Bash viene if [ -z ] effettivamente valutato come vero, quindi significa che il ramo non esiste. Questo ti fa risparmiare pochi millisecondi.
Amedee Van Gasse,

1

Puoi aggiungere il repository che hai come telecomando usando git remote add something https://github.com/project-name/project-name.gite quindi fare a git remote show somethingper ottenere tutte le informazioni sul telecomando. Ciò richiede una connessione di rete ed è utile per l'uso umano.

In alternativa, fai un file git fetch something. Questo recupererà tutti i rami sul telecomando chiamato somethinge li manterrà nel tuo repository locale. Puoi quindi unirli nella tua filiale locale come preferisci. Vi consiglio questo percorso in quanto, se finalmente si decide che si deve a fusione, questo è ciò che devi fare.

OT: Il tuo uso di "verificato localmente" indica che ti stai avvicinando a questo da un punto di vista del sistema di controllo delle versioni centralizzato. Di solito è un vicolo cieco quando hai a che fare con git. Utilizza parole come "checkout" ecc. Diversamente da come facevano i vecchi sistemi.


Grazie per le spiegazioni. Non mi sono ancora abituato a git e richiede un modo di pensare diverso.
Keen

1

Puoi provare

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

Qui si @{u}riferisce a remoto / upstream e si @{0}riferisce all'attuale HEAD locale (con la versione più recente di git, @{0}può essere abbreviato come @). Se il telecomando non esiste, viene visualizzato un errore.

Con git 2.16.2 (non sono sicuro di quale versione sia la prima ad avere questa funzionalità, ad esempio git 1.7.1 non ce l'ha), puoi farlo

git checkout

Se esiste un ramo remoto, ci sarà un output, come

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

Altrimenti non c'è uscita.


1

Restituirà tutti i rami (remoti o locali) che contengono la query nel nome.

git branch --all | grep <query>


0

Se i nomi dei tuoi rami sono molto specifici, potresti non aver bisogno di usare grep per la semplice corrispondenza dei nomi dei rami:

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

che funziona per

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

Usiamo un ID problema univoco come nomi di ramo e funziona bene.


0

Ho appena provato questo:

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

Questo restituirà 1 se viene trovato il ramo "tuo-ramo" e 0 altrimenti.


0

Sto combinando alcune delle risposte sopra in uno script:

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

Questo script otterrà 4 rami da un bitbucket remoto e li invierà a un github remoto, quindi invierà tutti i tag a gitHub. Lo sto usando in un lavoro Jenkins, ecco perché non vedi alcun git fetcho git pull, che è già fatto nella configurazione del repository di lavoro Jenkins.

Di solito preferisco le opzioni di lunga durata negli script. Avrei potuto combinare git branche git checkoutusando git checkout -B.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.