Configurer les branches cibles pour les pull requests

Azure DevOps Services

Par défaut, Azure DevOps suggère la création de nouveaux pull requests sur la branche par défaut. Dans un référentiel avec plusieurs branches utilisées pour les demandes de tirage, les propriétaires de référentiels peuvent configurer la liste des branches cibles de demande de tirage afin que ces suggestions sélectionnent la branche cible appropriée.

Pour activer cette fonctionnalité, créez un fichier avec un nom .azuredevops/pull_request_targets.yml dans le branche par défaut du référentiel. Ce fichier YAML doit contenir une seule liste, intitulée pull_request_targets, contenant les noms de branche ou les préfixes qui correspondent aux branches candidates.

Par exemple, tenez compte de ce contenu :

pull_request_targets:
  - main
  - release/*
  - feature/*

Cette liste de cibles potentielles spécifie main en tant que branche cible à sélectionner en premier, mais si une branche commençant release/ par ou feature/ est un meilleur choix, cette branche est choisie à la place.

Pour plus d’instructions sur les demandes de tirage et les considérations de gestion, consultez À propos des demandes de tirage.

Prerequisites

Catégorie Spécifications
Accès au projet Membre d’un projet.
Permissions - Afficher le code dans des projets privés : accès au moins De base.
- Clonez ou contribuez au code de projets privés : membre du groupe de sécurité "Contributeurs" ou disposant des autorisations correspondantes dans le projet.
- Définir des autorisations de branche ou de référentiel : les autorisations de gestion sont des autorisations pour la branche ou le référentiel.
- Modifier la branche par défaut : les politiques d'édition sont des autorisations pour le référentiel.
- Importez un référentiel : membre du groupe de sécurité Administrateurs de projet ou détenant l'autorisation Créer un référentiel au niveau du projet Git, réglée sur Autoriser. Pour plus d’informations, consultez Définir des autorisations de dépôt Git.
Services Référentiels activés.
Outils Optional. Utilisez az repos : Azure DevOps CLI.

Note

Dans les projets publics, les utilisateurs disposant d’un accès aux parties prenantes ont un accès complet à Azure Repos, notamment l’affichage, le clonage et la contribution au code.

Catégorie Spécifications
Accès au projet Membre d’un projet.
Permissions - Afficher le code : Au moins un accès de base.
- Cloner ou contribuer au code : membre du groupe de sécurité Contributeurs ou autorisations correspondantes dans le projet.
Services Référentiels activés.

Quand cette configuration est-elle utilisée ?

Il existe plusieurs points d'entrée pour utiliser une branche cible dynamique.

  • Suggestions de demande de tirage. Lorsqu’un utilisateur pousse une branche vers Azure DevOps, sa prochaine visite sur la page Repos peut suggérer de créer une pull request à partir de cette branche. Ce bouton « Créer une pull request » choisit la branche cible de manière dynamique.

  • URL de la demande de tirage( Pull Request). Lorsqu’un utilisateur accède directement à la page de création de demande de tirage à l’aide d’un sourceRef paramètre et en omettant le targetRef paramètre, Azure DevOps sélectionne une branche cible en fonction de ce choix dynamique.

  • Menu déroulant de branche. Lorsqu’un utilisateur ouvre le menu déroulant des branches dans Azure DevOps, les branches spécifiées dans les cibles de requête de tirage s’affichent dans une section appelée « Cibles » entre les sections « Les miennes » et « Toutes ».

    Capture d’écran de la liste déroulante de branches avec la section Cibles.

Il existe une fonctionnalité permettant aux clients-outils de créer des demandes de fusion grâce à ce choix dynamique, mais ces clients doivent ajouter un signal facultatif indiquant que l’utilisateur n’a pas spécifié une branche cible. Vérifiez l’outil client de votre choix pour voir si l’option est activée.

Quels sont les bons candidats pour les cibles de branche ?

Nous recommandons que la liste configurée des branches candidates inclut uniquement les branches protégées par les politiques de pull request. Ces branches sont probablement modifiées uniquement en effectuant des demandes de tirage, ce qui garantit que la position de branche précédente se trouve dans l’historique du premier parent de la validation du pourboire. Si une stratégie de fusion est utilisée, le deuxième parent représente les validations introduites dans la branche cible par l'achèvement d'une pull request et le premier parent est la pointe précédente.

Comment Azure DevOps sélectionne-t-il une branche ?

Git ne suit pas les métadonnées autour de la création d’une branche. Il n’existe aucun moyen exact de déterminer quelle branche a été utilisée lors de la création d’une branche de rubrique. Au lieu de cela, Azure DevOps utilise une heuristique basée sur l’historique du premier parent des branches.

Parmi les branches cibles possibles, Azure DevOps sélectionne la branche dont l’historique du premier parent se croise avec l’historique du premier parent de la branche source le plus.

Exemple : Pas de validation de fusion

Considérez la structure de branche suivante, qui est simplifiée plus que normale, car il n’y a pas de validations de fusion. Dans cet exemple, l’historique entier est représenté par l’historique du premier parent.

  ,-E---F <-- release/2024-September
 /
A---B---C---D <--- main
     \
      `-G---H <--- feature/targets
         \
          `-I <--- topic

Avec cet historique et l’exemple pull_request_targets de liste utilisé précédemment, nous avons trois branches cibles candidates, par ordre de priorité :

  • main
  • release/2024-September
  • feature/targets

La branche source, topicest ensuite comparée à ces branches.

  • main croise topic à B, ce qui laisse G,I dans topic et non dans main.
  • release/2024-September croise topic à A laissant B,G,I dans topic et non dans release/2024-September.
  • feature/targets intersecte avec topic à G, laissant I dans topic et non dans feature/targets.

Par conséquent, dans cet exemple, la feature/targets branche est choisie comme branche cible pour une demande de tirage avec topic comme branche source.

Exemple : validations de fusion

Dans un exemple plus compliqué, où la branche feature/targets a été fusionnée dans main et fusionnée dans elle-même main, l’historique des validations comporte plus de cas à prendre en compte :

  ,-E---F <-- release/2024-September
 /
A---B---C---D---J---K <--- main
     \    _/     \
      \  /        \
       `G---H---L--\--M <--- feature/targets
         \          \/
          \
           `I <--- topic

Ici, le commit D dans main représente un moment où feature/targets a été fusionné dans main. La validation M représente un moment où main a été fusionné avec feature/targets. Le lien entre les validations M et J est dessiné de manière à souligner que J est le deuxième parent de M tandis que L est le premier parent.

Dans ce cas, lorsque vous considérez l'historique de validation complète, main et feature/targets intersectent tous deux l'historique de topic à G. Toutefois, le premier historique parent illustre toujours une préférence pour feature/targets.

Rompant les liens

Si deux branches ont la même intersection d’historique de premier parent, Azure DevOps sélectionne la branche qui apparaît en premier dans la pull_request_targets liste. Si plusieurs branches sont toujours liées à cause de la pull_request_targets liste en raison d’une correspondance de préfixe, la première dans l’ordre alphabétique gagne.

Ces types de liens sont généralement présents lorsque de nouvelles branches candidates sont créées, telles que le début d'une nouvelle branche de fonctionnalité ou la bifurcation d'une branche de version.

          ,-E---F <-- release/2024-October
         /
A---B---C---D <--- main
     \
      \
       `G <--- topic

Dans cet exemple, la branche release/2024-October a été créée à partir de la main après que la topic a été dérivée de la main. Bien que cela soit intuitif pour un lecteur humain, l'ordre des catégories main et release/* dans la liste pull_request_targets indique l'ordre préféré d'Azure DevOps.

Que se passe-t-il si Azure DevOps choisit la branche cible incorrecte ?

La page de création de pull request comprend un sélecteur pour ajuster la branche cible si le choix dynamique ne correspond pas aux attentes. La branche cible peut également être modifiée une fois le pull request créé.

Plus important encore, il peut être utile de comprendre pourquoi l’heuristique peut sélectionner la branche cible « incorrecte ».

Cette heuristique s’appuie sur certaines hypothèses sur la façon dont les branches cibles et la branche source ont été créées. Voici quelques raisons potentielles pour lesquelles l’heuristique ne fonctionne pas :

  • Les branches visées ne sont pas protégées par les stratégies de pull request. Si les branches cibles peuvent être envoyées arbitrairement, l’historique du premier parent n’est pas un indicateur fiable de l’emplacement précédent de cette branche.

  • La branche source a été créée à partir d'une version antérieure d'une branche candidate. Si la branche source a choisi une validation arbitraire dans l’historique, il n’existe aucune garantie sur le premier historique parent dont elle dépend.

  • La branche source a été avancée à l’aide de git commit et git merge commandes. Les commandes telles que git reset --hard ou git rebase peuvent modifier l’historique de la branche de manière imprévisible.

Si vous n’êtes pas d’accord avec la branche cible choisie par cette heuristique, envisagez de mettre à jour le choix à l’aide git rebase --onto <new-target> <old-target> <source>de . La git rebase commande réécrit l’historique du premier parent pour que l’heuristique choisisse la nouvelle cible.

Une erreur courante que les utilisateurs font quand ils se rendent compte qu’ils sont basés sur la branche incorrecte consiste à utiliser git merge pour amener la branche appropriée dans leur historique. La fusion ne modifie pas l’historique du premier parent et ne modifie donc pas le choix de la branche cible.

Comment puis-je tester cette décision localement ?

L’heuristique utilisée par Azure DevOps a été contribué au client Git principal et est disponible dans les versions 2.47.0 et ultérieures de Git.

Pour tester cette logique dans votre propre référentiel, commencez par exécuter git fetch origin pour vous assurer que vous disposez de la dernière version des branches cibles. Exécutez ensuite la commande suivante git for-each-ref , ajustée pour correspondre à votre liste de branches candidates :

$ git for-each-ref --format="%(is-base:HEAD) %(refname)" \
           refs/remotes/origin/main \
           "refs/remotes/origin/release/*" \
           "refs/remotes/origin/feature/*"
 refs/remotes/origin/main
 refs/remotes/origin/release/2024-September
(HEAD) refs/remotes/origin/feature/targets

Dans cette commande, la HEAD validation est utilisée comme source et compare l’historique du premier parent des branches cibles de la même façon. Bien que chaque branche candidate soit répertoriée dans la sortie, la chaîne (HEAD) indique quelles branches doivent être utilisées comme branche cible.

Étapes suivantes