Disons que j'ai le référentiel local suivant avec une arborescence de validation comme celle-ci:
master --> a
\
\
develop c --> d
\
\
feature f --> g --> h
master
est mon c'est le dernier code de version stable , develop
est mon ceci est le «prochain» code de version , et feature
est une nouvelle fonctionnalité en cours de préparationdevelop
.
Ce que je veux pouvoir faire sur mon référentiel distant en utilisant des hooks, c'est que les poussées feature
soient refusées à moins que commit ne f
soit un descendant direct de develop
HEAD. c'est-à-dire que l'arborescence de validation ressemble à ceci parce que la fonctionnalité a été git rebase
activée d
.
master --> a
\
\
develop c --> d
\
\
feature f --> g --> h
Est-il donc possible de:
- Identifiez la branche parente de
feature
? - Identifiez le commit dans la branche parent qui
f
est un descendant de?
À partir de là, je vérifierais ce qu'est le HEAD de la branche parent et je verrais si le f
prédécesseur correspond au HEAD de la branche parent, pour déterminer si la fonctionnalité doit être rebasée.
Réponses:
En supposant que le référentiel distant possède une copie du développement branche de (votre description initiale la décrit dans un référentiel local, mais il semble qu'elle existe également dans la télécommande), vous devriez être en mesure de réaliser ce que je pense que vous voulez, mais l'approche est un peu différent de ce que vous avez imaginé.
L'histoire de Git est basée sur un DAG de commits. Les branches (et les «refs» en général) ne sont que des étiquettes transitoires qui pointent vers des validations spécifiques dans le DAG de validation en constante augmentation. En tant que tel, la relation entre les branches peut varier dans le temps, mais pas la relation entre les validations.
Il semble être
baz
basé sur (une ancienne version de)bar
? Mais que se passe-t-il si nous supprimonsbar
?Maintenant, on dirait qu'il
baz
est basé surfoo
. Mais l'ascendance debaz
n'a pas changé, nous venons de supprimer une étiquette (et la validation qui en résulte). Et si nous ajoutons une nouvelle étiquette à4
?Maintenant, on dirait qu'il
baz
est basé surquux
. Pourtant, l'ascendance n'a pas changé, seules les étiquettes ont changé.Si, cependant, nous demandions "est-ce que commettre est
6
un descendant de commit3
?" (en supposant3
et6
sont des noms de validation SHA-1 complets), la réponse serait «oui», que les étiquettesbar
etquux
soient présentes ou non.Ainsi, vous pouvez poser des questions comme «la validation poussée est-elle un descendant de la pointe actuelle de la branche de développement ?», Mais vous ne pouvez pas poser de manière fiable «quelle est la branche parente de la validation poussée?».
Une question principalement fiable qui semble se rapprocher de ce que vous voulez est:
Qui pourrait être implémenté comme:
Cela couvrira une partie de ce que vous souhaitez restreindre, mais peut-être pas tout.
Pour référence, voici un exemple d'historique étendu:
Le code ci - dessus peut être utilisé pour rejeter
H
etS
tout en acceptantH'
,J
,K
ouN
, mais il serait aussi accepterL
etP
(ils impliquent des fusions, mais ils ne se confondent pas la pointe de développer ).Pour refuser également
L
etP
, vous pouvez modifier la question et demanderla source
develop > release > feature
, je récupèrerais et cela nécessite de connaître le parent. La solution à mon problème était stackoverflow.com/a/56673640/2366390Une reformulation
Une autre façon de formuler la question est: "Quel est le commit le plus proche qui réside sur une branche autre que la branche actuelle, et quelle branche est-ce?"
Une solution
Vous pouvez le trouver avec un peu de magie en ligne de commande
Avec awk :
Voici comment ça fonctionne:
Et le résultat
Exécution du code ci-dessus sur
Vous donnera
develop
si vous l'exécutez à partir de H etmaster
si vous l'exécutez à partir de I.Le code est disponible sous forme de résumé
la source
cannot handle more than 25 refs
ack
n'est pas disponible sur Mac (quelqu'un a suggéré de le remplacerack
pargrep
)git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'
git show-branch | sed "s/].*//" | grep "\*" | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed "s/^.*\[//"
parent = "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//' #"
works for meVous pouvez également essayer:
la source
git log --graph --decorate --simplify-by-decoration
où--graph
est facultatif.git log --graph --decorate --simplify-by-decoration --oneline
git parent
Vous pouvez simplement exécuter la commande
git parent
pour trouver le parent de la branche, si vous ajoutez le @ Joe Chrysler réponse de comme alias git . Cela simplifiera l'utilisation.
Ouvrez le fichier gitconfig situé à l'
"~/.gitconfig"
aide de n'importe quel éditeur de texte. (Pour linux). Et pour Windows, le chemin ".gitconfig" se trouve généralement àc:\users\your-user\.gitconfig
Ajoutez la commande d'alias suivante dans le fichier:
Enregistrez et quittez l'éditeur.
Exécutez la commande
git parent
C'est ça!
la source
cannot handle more than 25 refs
exception.J'ai une solution à votre problème global (déterminez si elle
feature
descend de la pointe dedevelop
), mais cela ne fonctionne pas en utilisant la méthode que vous avez décrite.Vous pouvez utiliser
git branch --contains
pour lister toutes les branches descendantes de la pointe dedevelop
, puis utilisergrep
pour vous assurerfeature
qu'elles figurent parmi celles-ci.S'il en fait partie, il imprimera
" feature"
sur la sortie standard et aura un code retour de 0. Sinon, il n'imprimera rien et aura un code retour de 1.la source
<branch>
, où j'ai joué: àgit checkout -b <branch-2>
partir de ... CECI est la réponse! Pas besoin de grep, vraiment.git branch --contains <branch>
Cela fonctionne bien pour moi.
Réponses de courtoisie de: @droidbot et @Jistanidiot
la source
*
n'est pas une expression rationnelle appropriée pour passer à grep. Devrait utilisergrep -F '*'
ou à lagrep '\*'
place. Bonne solution sinon.Étant donné qu'aucune des réponses ci-dessus n'a fonctionné sur notre référentiel, je souhaite partager ma propre manière, en utilisant les dernières fusions dans
git log
:Mettez-le dans un script nommé
git-last-merges
, qui accepte également un nom de branche comme argument (au lieu de la branche actuelle) ainsi que d'autresgit log
argumentsÀ partir de la sortie, nous pouvons détecter manuellement la ou les branches parentes en fonction de leurs propres conventions de branchement et du nombre de fusions de chaque branche.
EDIT: Si vous utilisez
git rebase
souvent des branches enfants (et que les fusions sont souvent avancées rapidement donc il n'y a pas trop de validations de fusion), cette réponse ne fonctionnera pas bien, j'ai donc écrit un script pour compter les validations anticipées (normal et fusion) , et derrière les validations (il ne devrait pas y avoir de fusion derrière dans la branche parent) sur toutes les branches par rapport à la branche actuelle. Exécutez simplement ce script et faites-moi savoir si cela fonctionne pour vous ou nonla source
rebase
souvent (et les fusions sontfast-forward
souvent éditées). Je modifierai ma réponse si j'ai trouvé une meilleure solution.git log --oneline --merges "$@" | grep into | sed 's/.* into //g' | uniq --count | head -n 1 | cut -d ' ' -f 8
Une solution
La solution basée sur
git show-branch
ne fonctionnait pas tout à fait pour moi (voir ci-dessous), donc je l'ai combinée avec celle basée surgit log
et je me suis retrouvée avec ceci:Limitations et mises en garde
log
commandemaster
etdevelop
les résultats ( la plupart du temps) en<SHA> Initial commit
Les resultats
Malgré l'existence d'une branche locale (par exemple, seule
origin/topic
est présente puisque la validation aO
été extraite directement par son SHA), le script doit s'afficher comme suit:G
,H
,I
(branchehotfix
) →master
M
,N
,O
(branchefeature/a
) →develop
S
,T
,U
(branchefeature/c
) →develop
P
,Q
,R
(branchefeature/b
) →feature/a
J
,K
,L
(branchedevelop
) →<sha> Initial commit
*B
,D
,E
,F
(branchemaster
) →<sha> Initial commit
* - ou
master
sidevelop
les commits étaient au-dessus de la tête du maître (~ le maître serait rapidement transmissible à développer)Pourquoi n'a-t-il pas travaillé pour moi?
La solution basée sur
git show-branch
s'est révélée peu fiable pour moi dans les situations suivantes:grep '\*' \
pour `grep '! \ - et ce n'est que le début de tous les ennuismaster
etdevelop
les résultats dansdevelop
et respectivement ``master
branche (hotfix/
branches) se retrouvent avecdevelop
comme parent puisque leur parent demaster
branche le plus proche a été marqué avec!
au lieu de*
pour une raison.la source
"!git log --decorate --simplify-by-decoration --oneline | grep -v '(HEAD' | head -n1 | sed 's/.* (\\(.*\\)) .*/\\1/' | sed 's/\\(.*\\), .*/\\1/' | sed 's/origin\\///'"
N'oubliez pas que, comme décrit dans "Git: Trouver de quelle branche provient une validation" , vous ne pouvez pas facilement localiser la branche où cette validation a été effectuée (les branches peuvent être renommées, déplacées, supprimées ...), même si
git branch --contains <commit>
c'est un début.git branch --contains <commit>
que ne répertorie pas lafeature
branche et la listedevelop
,/refs/heads/develop
Si les deux commits correspondent, vous êtes prêt à partir (cela signifierait que la
feature
branche a son origine à la tête dedevelop
).la source
La magie de la ligne de commande de JoeChrysler peut être simplifiée. Voici la logique de Joe - par souci de concision, j'ai introduit un paramètre nommé
cur_branch
à la place de la substitution de commande`git rev-parse --abbrev-ref HEAD`
dans les deux versions; qui peut être initialisé comme ceci:Ensuite, voici le pipeline de Joe:
Nous pouvons accomplir la même chose que les cinq de ces filtres de commande individuels dans une
awk
commande relativement simple :Cela se décompose comme ceci:
diviser la ligne en champs à
]
,^
,~
et[
caractères.Rechercher des lignes contenant un astérisque
... mais pas le nom de la branche actuelle
Lorsque vous trouvez une telle ligne, imprimez son deuxième champ (c'est-à-dire la partie entre les première et deuxième occurrences de nos caractères de séparation de champ). Pour les noms de branche simples, ce sera juste ce qu'il y a entre les crochets; pour les références avec des sauts relatifs, ce sera juste le nom sans le modificateur. Notre ensemble de séparateurs de champs gère donc l'intention des deux
sed
commandes.Quittez ensuite immédiatement. Cela signifie qu'il ne traite que la première ligne correspondante, nous n'avons donc pas besoin de diriger la sortie
head -n 1
.la source
Voici une implémentation PowerShell de la solution de Mark Reed:
la source
Je ne dis pas que c'est un bon moyen de résoudre ce problème, mais cela semble fonctionner pour moi.
git branch --contains $(cat .git/ORIG_HEAD)
Le problème étant que cat'inguer un fichier jette un coup d'œil dans le fonctionnement interne de git, ce n'est donc pas nécessairement compatible (ou rétrocompatible).la source
Implémentation multiplateforme avec Ant
la source
@Mark Reed: Vous devez ajouter que la ligne de validation ne doit pas seulement contenir un astérisque, mais commencer par un astérisque! Sinon, les messages de validation contenant un astérisque sont également inclus dans les lignes correspondantes. Il devrait donc être:
git show-branch -a | awk -F'[]^~[]' '/^\*/ && !/'"$current_branch"'/ {print $2;exit}'
ou la version longue:
la source
Atteint les mêmes fins que la réponse de Mark Reed, mais utilise une approche beaucoup plus sûre qui ne se comporte pas mal dans un certain nombre de scénarios:
-
non visible*
*
la source
Quiconque le souhaite ces jours-ci - L'application SourceTree d'Atlassian vous montre une excellente représentation visuelle de la façon dont vos branches sont liées les unes aux autres, c'est-à-dire où elles ont commencé et où elles se trouvent actuellement dans l'ordre de validation (par exemple HEAD ou 4 commits derrière, etc.) .
la source
Si vous utilisez Source Tree regardez vos détails de commit> Parents> alors vous verrez les numéros de commit soulignés (liens)
la source
Une alternative:
git rev-list master | grep "$(git rev-list HEAD)" | head -1
Obtenez le dernier commit que c'est à la fois ma branche et
master
(ou la branche que vous souhaitez spécifier)la source
Cela n'a pas fonctionné pour moi quand j'avais fait quelque chose comme
develop > release-v1.0.0 > feature-foo
ça, cela remonterait au développement, notez qu'il y avait un rebase impliqué, je ne sais pas si cela aggrave mon problème ...Ce qui suit a donné le hachage de validation correct pour moi
la source