Étant donné un identifiant de commit, comment déterminer si la branche actuelle contient le commit?

156

Ce que j'essaie de faire, c'est une vérification de version. Je veux m'assurer que le code reste au-dessus d'une version minimale. J'ai donc besoin d'un moyen de savoir si la branche actuelle contient un commit spécifié.

TieDad
la source
10
Voir le doublon proposé pour savoir comment trouver toutes les branches qui contiennent un commit spécifié. Pour savoir si la branche courante contient le commit C , utilisez la commande "plumbing" git merge-base --is-ancestor. La branche courante contient C si C est un ancêtre de HEAD, donc: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
Bonjour, veuillez soumettre ceci comme réponse afin qu'elle puisse être sélectionnée comme réponse correcte =)
Ben
1
@Ben - Je l'ai ajouté en tant que réponse wiki de la communauté.
Zitrax
1
@Remover: dans les scripts shell, zéro est vrai, différent de zéro est faux: l'inverse de la convention C. /bin/truea été initialement implémenté au fur exit 0et à /bin/falsemesure exit 1. (Des coquilles modernes ont ensuite été intégrées.)
torek

Réponses:

220

Il existe plusieurs façons d'atteindre ce résultat. La première option naïve est d'utiliser git loget de rechercher un commit spécifique en utilisant grep, mais ce n'est pas toujours précis

git log | grep <commit_id>

Il vaut mieux utiliser git branchdirectement pour trouver toutes les branches contenant des données en COMMIT_IDutilisant

git branch --contains $COMMIT_ID

L'étape suivante consiste à découvrir la branche actuelle qui peut être effectuée depuis l' git 1.8.1utilisation

git symbolic-ref --short HEAD

Et combinés ensemble comme

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

Mais la commande ci-dessus ne renvoie ni vrai ni faux et il existe une version plus courte qui renvoie le code de sortie 0 si la validation est dans la branche actuelle OU le code de sortie 1 sinon

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

Le code de sortie est sympa, mais comme vous voulez une chaîne trueou falsecomme réponse, vous devez en ajouter un peu plus, puis combiner avec iffrom bash, vous obtenez

if [ 0 -eq $(git merge-base --is-ancestor $COMMIT_ID HEAD) ]; then echo "true"; else echo "false"; fi
JiriS
la source
9
Ce n'est pas correct; le greppourrait entraîner des faux positifs si les git logmentions du commettras SHA pour d' autres raisons, par exemple , il est mentionné dans un message de validation à la suite d'un port d' une autre branche.
Adam Spiers
1
Corrigé (ou plutôt ajouté une autre option).
JiriS
3
Veuillez voir le commentaire sur la question, qui utilise le jeu d'outils intégré git. stackoverflow.com/questions/43535132/…
Ben
2
J'aime la première option, mais pour écarter l'objection d'Adam, j'ajouterais l'option --format=format:%Hà git log.
PJSCopeland
71

Obtenez une liste de branche (s) contenant le commit spécifique.

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

Vérifiez si une branche a le commit spécifique.

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

Recherchez la branche (par exemple feature) avec une correspondance exacte .

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

par exemple , si vous avez 3 branches locales appelées feature, feature1, feature2puis

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

# output
feature
feature1
feature2

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

# output
feature     

Vous pouvez également rechercher dans les deux branches localet remote(utilisation -a) ou uniquement dans les remotebranches (utilisation -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$'
Sajib Khan
la source
1
L' grepici pourrait également entraîner des faux positifs s'il existe d'autres branches contenant le commit dont les noms contiennent également en <branch-name>tant que sous-chaîne.
Adam Spiers
1
Oui @AdamSpiers, a mis à jour la réponse avec une correspondance exacte avec le nom de la succursale pargrep -E '(^|\s)branchname$'
Sajib Khan
1
Selon ce commentaire sur la question associée, il peut être utile d'ajouter l' option -r("remote") ou -a("all") git branchpour rechercher les branches qui ne peuvent pas être répliquées dans le clone du dépôt local.
sxc731
Cela n'a pas fonctionné pour moi, j'avais besoin git branch --all --contains <commit-id>
Arthur Tacca
7

Commentaire extrait par @torek comme réponse:

Voir le duplicata proposé pour savoir comment trouver toutes les branches qui contiennent un commit spécifié.

Pour savoir si la branche courante contient le commit C, utilisez la commande "plumbing" git merge-base --is-ancestor. La branche courante contient C si C est un ancêtre de HEAD, donc:

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

(Note latérale: dans les scripts shell, une commande qui sort de zéro est "vraie" tandis que celle qui sort de zéro est "fausse".)

torek
la source
4

Pour lister les branches locales contenant commit:

git branch --contains <commit-id>

et pour lister toutes les branches, y compris distantes uniquement, contenant commit:

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

De même pour vérifier si le commit est dans une branche particulière:

git log <branch> | grep <commit_id>

et si la branche n'existe pas localement, préfixez le nom de la branche avec origin/

hgrey
la source
Voté pour la remarque sur -a. Merci pour ce conseil!
Thorkil Værge
3

Ouais une autre alternative:

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

Cela fonctionne mieux pour moi car cela fonctionnerait également sur des branches distantes mises en cache localement telles que remotes/origin/master, sur lesquelles git branch --containsne fonctionnera pas.

Cela couvre plus que la question d'OP sur la "branche actuelle", mais je trouve idiot de poser une version "toute branche" de cette question, alors je décide de poster quand même ici.

logique ou
la source
1
git branch --contains <commit-id> --points-at <target branch name>

Il renverra le nom de la branche cible si l'ID de validation existe dans cette branche. Sinon, la commande échouera.

DreamUth
la source
nope ...error: malformed object name 'branch-name'
bbodenmiller
1
Vous pouvez obtenir cette erreur dans 2 cas 1. Lorsque le <nom de la branche> donné ne contient pas le <commit id> donné 2. Le contrôle <nom de la branche> n'est pas le <nom de la branche> donné
DreamUth
0

Puisque cette question a de belles réponses scripty, j'ajoute mes favoris.

Celui-ci vous montrera, pour les derniers $ncommits dans $brquelles branches contient chacun:

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

Celui-ci est similaire mais fait de même pour une liste de branches:

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
Bruno Bronosky
la source