Dato un ID commit, come determinare se il ramo corrente contiene il commit?


156

Quello che sto cercando di fare è un controllo della versione. Voglio assicurarmi che il codice rimanga aggiornato su una versione minima. Quindi ho bisogno di un modo per sapere se il ramo corrente contiene un commit specificato.



10
Vedi il duplicato proposto per come trovare tutti i rami che contengono un commit specificato. Per scoprire se il ramo corrente contiene commit C , usa il comando "idraulico" git merge-base --is-ancestor. L'attuale ramo contiene C se C è un antenato di HEAD, quindi:if git merge-base --is-ancestor $hash HEAD; then echo I contain commit $hash; else echo I do not contain commit $hash; fi
torek

1
Ciao, si prega di inviare questo come una risposta in modo che possa essere selezionato come la risposta corretta =)
Ben

1
@Ben - L'ho aggiunto come risposta wiki della community.
Zitrax,

1
@Remover: negli script di shell, zero è vero, diverso da zero è falso: il contrario della convenzione C. /bin/trueè stato originariamente implementato come exit 0e /bin/falsecome exit 1. (Le conchiglie moderne sono state integrate.)
Torek,

Risposte:


220

Esistono diversi modi per ottenere questo risultato. La prima opzione ingenua è usare git loge cercare un commit specifico usando grep, ma ciò non è sempre preciso

git log | grep <commit_id>

È meglio usare git branchdirettamente per trovare tutti i rami che contengono dato COMMIT_IDusando

git branch --contains $COMMIT_ID

Il prossimo passo è scoprire l'attuale ramo che può essere fatto git 1.8.1dall'uso

git symbolic-ref --short HEAD

E combinati insieme come

git branch $(git symbolic-ref --short HEAD) --contains $COMMIT_ID

Ma il comando sopra non restituisce true o false e esiste una versione più breve che restituisce il codice di uscita 0 se commit è nel ramo corrente O il codice di uscita 1 in caso contrario

git merge-base --is-ancestor $COMMIT_ID HEAD

Il codice di uscita è carino, ma come vuoi stringa trueo falsecome risposta devi aggiungere un po 'di più e poi combinato con ifda bash ottieni

if [ 0 -eq $(git merge-base --is-ancestor $COMMIT_ID HEAD) ]; then echo "true"; else echo "false"; fi

9
Non è corretto; ciò greppotrebbe comportare falsi positivi se git logmenziona il commit SHA per altri motivi, ad esempio è menzionato in un messaggio di commit come risultato di una porta di un altro ramo.
Adam Spires,

1
Corretto (o meglio aggiunto un'altra opzione).
JiriS,

3
Si prega di vedere il commento sulla domanda, che utilizza il set di strumenti git incorporato. stackoverflow.com/questions/43535132/…
Ben

2
Mi piace la prima opzione, ma per escludere l'obiezione di Adam, aggiungerei l'opzione --format=format:%Ha git log.
PJSCopeland,

71

Ottieni un elenco di filiali che contengono il commit specifico.

# get all the branches where the commit exists
$ git branch --contains <commit-id>

Controlla se un ramo ha il commit specifico.

# output the branch-name if the commit exists in that branch
$ git branch --contains <commit-id> | grep <branch-name>

Cerca nel ramo (diciamo, feature) con la corrispondenza esatta .

$ git branch --contains <commit-id> | grep -E '(^|\s)feature$'

ad esempio, se si dispone di 3 sedi locali chiamati feature, feature1, feature2poi

$ git branch --contains <commit-id> | grep 'feature'

# output
feature
feature1
feature2

$ git branch --contains <commit-id> | grep -E '(^|\s)feature$'

# output
feature     

È anche possibile cercare sia locale remoterami (uso -a), o solo in remoterami (uso -r).

# search in both 'local' & 'remote' branches  
$ git branch -a --contains <commit-id> | grep -E '(^|\s)feature$'

# search in 'remote' branches  
$ git branch -r --contains <commit-id> | grep -E '(^|\s)feature$'

1
Il grepqui potrebbe anche provocare falsi positivi se ci sono altri rami contenenti il ​​commit i cui nomi contengono anche <branch-name>come sottostringa.
Adam Spires,

1
Sì @AdamSpiers, aggiornata la risposta con la corrispondenza esatta del nome della succursale digrep -E '(^|\s)branchname$'
Sajib Khan,

1
Per questo commento sulla domanda correlata può essere utile aggiungere l' opzione -r("remote") o -a("all") git branchper cercare rami che potrebbero non essere replicati nel clone del repository locale.
sxc731,

Non ha funzionato per me, avevo bisogno git branch --all --contains <commit-id>
Arthur Tacca il

7

Commento estratto da @torek come risposta:

Vedi il duplicato proposto per come trovare tutti i rami che contengono un commit specificato.

Per scoprire se il ramo corrente contiene commit C, usa il comando "idraulico" git merge-base --is-ancestor. L'attuale ramo contiene C se C è un antenato di HEAD, quindi:

if git merge-base --is-ancestor $hash HEAD; then
    echo I contain commit $hash
else
    echo I do not contain commit $hash
fi

(Nota a margine: negli script di shell, un comando che esce da zero è "vero" mentre uno che esce da zero è "falso".)


4

Per elencare le filiali locali contenenti commit:

git branch --contains <commit-id>

e per elencare tutti i rami, incluso solo il telecomando, contenenti commit:

git branch -a --contains <commit-id>

Allo stesso modo per verificare se il commit è in un determinato ramo:

git log <branch> | grep <commit_id>

e se il ramo non esiste localmente prefisso il nome del ramo con origin/


Votato per l'osservazione su -a. Grazie per quel consiglio!
Thorkil Værge

3

Sì un'altra alternativa:

git rev-list <branch name> | grep `git rev-parse <commit>`

Questo funziona meglio per me poiché funzionerebbe anche su filiali remote memorizzate nella cache locale come remotes/origin/master, su cui git branch --containsnon funzionerà.

Questo riguarda più della domanda di OP relativa al solo "ramo corrente", ma trovo stupido porre una versione "qualunque ramo" di questa domanda, quindi decido di pubblicare qui comunque.


1
git branch --contains <commit-id> --points-at <target branch name>

Restituirà il nome del ramo di destinazione se l'ID commit esiste in quel ramo. Altrimenti il ​​comando fallirà.


error: malformed object name 'branch-name'
no

1
È possibile che si verifichi questo errore in 2 casi 1. Quando il <nome ramo> specificato non contiene il <ID commit> 2. Il checkout <nome ramo> non è il <nome ramo> specificato
DreamUth

0

Dal momento che questa domanda ha delle belle risposte scripty, sto aggiungendo i miei preferiti.

Questo ti mostrerà, per gli ultimi $ncommit in $brcui le filiali contengono ciascuna:

br=mybranch
n=10
git log --oneline -n$n $br | awk '{print; system("git branch --contains "$1)}'

Questo è simile ma fa lo stesso per un elenco di rami:

br="mybranch yourbranch herbranch"
n=4
for br in $brs; do git log --oneline -n$n $br | awk '{print; system("git branch --contains "$1)}'; done
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.