488 votes

Comment trouver le parent le plus proche d'une branche Git ?

Disons que j'ai le dépôt local suivant avec un arbre de commit comme ceci :

master --> a
            \
             \
      develop c --> d
               \
                \
         feature f --> g --> h

master est mon il s'agit du dernier code de la version stable , develop est mon il s'agit du code de la "prochaine" version y feature es une nouvelle fonctionnalité en préparation pour develop .

En utilisant des crochets, je veux être capable de refuser les poussées pour feature à mon référentiel distant, à moins que le commit f est un descendant direct de develop HEAD. C'est à dire que l'arbre de commit ressemble à ceci, parce que la fonctionnalité a été git rebase en d .

master --> a
            \
             \
      develop c --> d
                     \
                      \
               feature f --> g --> h

Alors, est-il possible de :

  • Identifiez la branche mère de feature ?
  • Identifiez le commit de la branche mère qui f est un descendant de ?

A partir de là, je vérifierais quel est le HEAD de la branche mère, et voir si f Le prédécesseur correspond à la branche parent HEAD, pour déterminer si la fonctionnalité doit être rebasée.

0 votes

Cette question devrait être reformulée pour trouver le parent d'un parent.

7voto

Mark Reed Points 23817

La magie de la ligne de commande de Joe Chrysler peut être simplifié. Voici la logique de Joe - par souci de brièveté, j'ai introduit un paramètre appelé cur_branch à la place de la substitution de commande `git rev-parse --abbrev-ref HEAD` dans les deux versions ; cela peut être initialisé comme suit :

cur_branch=$(git rev-parse --abbrev-ref HEAD)

Ensuite, voici le pipeline de Joe :

git show-branch -a           |
  grep '\*'                  | # we want only lines that contain an asterisk
  grep -v "$cur_branch"      | # but also don't contain the current branch
  head -n1                   | # and only the first such line
  sed 's/.*\[\(.*\)\].*/\1/' | # really, just the part of the line between []
  sed 's/[\^~].*//'            # and with any relative refs (^, ~n) removed

Nous pouvons accomplir la même chose que ces cinq filtres de commande individuels en un seul et même processus relativement simple awk commandement :

git show-branch -a |
  awk -F'[]^~[]' '/\*/ && !/'"$cur_branch"'/ {print $2;exit}'

Cela se décompose comme suit :

-F'[]^~[]'

diviser la ligne en champs à ] , ^ , ~ y [ des personnages.

/\*/

Trouver les lignes qui contiennent un astérisque

&& !/'"$cur_branch"'/

...mais pas le nom de la branche actuelle

{ print $2;

Lorsque vous trouvez une telle ligne, imprimez son deuxième champ (c'est-à-dire la partie située entre la première et la deuxième occurrence de nos caractères de séparation de champs). Pour les noms de branches simples, ce sera juste ce qui se trouve entre les parenthèses ; pour les références avec des sauts relatifs, ce sera juste le nom sans le modificateur. Ainsi, notre jeu de séparateurs de champs prend en compte les intentions des deux types d'éléments suivants sed des commandes.

  exit }

Puis quittez immédiatement. Cela signifie qu'il ne traite que la première ligne correspondante, donc nous n'avons pas besoin de faire passer la sortie par le canal head -n 1 .

3 votes

Notez que certaines branches peuvent être absentes de la sortie en raison d'un trop grand nombre de réfs. Elles sont affichées comme des avertissements sur stderr à la place.

7voto

chrisevett Points 113

Voici une implémentation PowerShell de La solution de Mark Reed :

git show-branch -a | where-object { $_.Contains('*') -eq $true} | Where-object {$_.Contains($branchName) -ne $true } | select -first 1 | % {$_ -replace('.*\[(.*)\].*','$1')} | % { $_ -replace('[\^~].*','') }

5voto

user1529413 Points 164

Je ne dis pas que c'est une bonne façon de résoudre ce problème, mais cela semble fonctionner pour moi :

git branch --contains $(cat .git/ORIG_HEAD)

Le problème est que cat'ing d'un fichier est un coup d'œil dans le fonctionnement interne de Git, donc ce n'est pas nécessairement compatible en avant (ou en arrière).

3voto

ENargit Points 173

Mise en œuvre multiplateforme avec Ant

    <exec executable="git" outputproperty="currentBranch">
        <arg value="rev-parse" />  
        <arg value="--abbrev-ref" />  
        <arg value="HEAD" />  
    </exec>

    <exec executable="git" outputproperty="showBranchOutput">
        <arg value="show-branch" />  
        <arg value="-a" />  
    </exec>

    <loadresource property="baseBranch">
      <propertyresource name="showBranchOutput"/>
          <filterchain>
            <linecontains>
              <contains value="*"/>
            </linecontains>
            <linecontains negate="true">
              <contains value="${currentBranch}"/>
            </linecontains>
            <headfilter lines="1"/>
            <tokenfilter>
                <replaceregex pattern=".*\[(.*)\].*" replace="\1"/>
                <replaceregex pattern="[\^~].*" replace=""/>
            </tokenfilter>
          </filterchain>
    </loadresource>

    <echo message="${currentBranch} ${baseBranch}" />

0 votes

Une explication s'impose. Par exemple, quelle est l'idée ou l'essentiel ?

3voto

Justin Grote Points 67

Voici ma version PowerShell :

function Get-GHAParentBranch {
    [CmdletBinding()]
    param(
        $Name = (git branch --show-current)
    )
    git show-branch |
      Select-String '^[^\[]*\*' |
      Select-String -NotMatch -Pattern "\[$([Regex]::Escape($Name)).*?\]" |
      Select-Object -First 1 |
      Foreach-Object {$PSItem -replace '^.+?\[(.+)\].+$','$1'}
}

1 votes

Bonjour ! Bien que ce code puisse résoudre la question, y compris une explication En expliquant comment et pourquoi cela résout le problème, vous contribuerez vraiment à améliorer la qualité de votre article et obtiendrez probablement plus de votes positifs. N'oubliez pas que vous répondez à la question pour les lecteurs à venir, et pas seulement pour la personne qui pose la question maintenant. Veuillez consulter le site modifier votre réponse pour ajouter des explications et donner une indication des limites et des hypothèses applicables.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X