Close

Upstreams et forks Git : guide pratique et astuce sympa

Photo de Nicola Paolucci
Nicola Paolucci

Expert en développement


La duplication de projets pour apporter vos propres changements permet d'intégrer facilement vos propres contributions. Mais si vous ne renvoyez pas ces changements vers l'amont (c'est-à-dire vers le dépôt parent), vous risquez d'en perdre la trace, ce qui peut provoquer des lignes divergentes dans votre dépôt. Pour vous assurer que tous les contributeurs partent du même point de départ, vous devez connaître certains principes de l'interaction entre git forking et git upstream. Dans ce billet de blog, je vais vous présenter les bases, les pièges à éviter et je vais même vous confier une astuce sympa pour vous permettre de prendre de l'avance.

Git upstream : restez à jour et apportez votre contribution


Je tiens tout d'abord à vous présenter une configuration courante ainsi qu'un workflow des plus basiques pour interagir avec les dépôts upstream.

Toute configuration standard comporte généralement un remote origin et upstream. Ce dernier est le gardien du projet ou la source d'informations fiable à laquelle vous souhaitez contribuer.

Premièrement, vérifiez que vous avez déjà créé un remote pour le dépôt upstream, avec en prime une branche origin :

git remote -v

origin  git@bitbucket.org:my-user/some-project.git (fetch)
origin  git@bitbucket.org:my-user/some-project.git (push)

Si vous n'avez pas de branche upstream, vous pouvez simplement l'ajouter en utilisant la commande remote :

git remote add upstream git@bitbucket.org:some-gatekeeper-maintainer/some-project.git
Bases de données
Ressource connexe

Comment déplacer un dépôt Git complet

Logo Bitbucket
DÉCOUVRIR LA SOLUTION

Découvrir Git avec Bitbucket Cloud

Vérifiez que la branche distante est correctement ajoutée :

git remote -v

origin    git@bitbucket.org:my-user/some-project.git (fetch)
origin    git@bitbucket.org:my-user/some-project.git (push)
upstream  git@bitbucket.org:some-gatekeeper-maintainer/some-project.git (fetch)
upstream  git@bitbucket.org:some-gatekeeper-maintainer/some-project.git (push)

À présent, vous pouvez collecter les derniers changements du dépôt upstream avec fetch. Répétez cette action à chaque fois que vous voulez recevoir des mises à jour :

(Si le projet dispose de tags qui n'ont pas été mergés à la branche main, vous devez également exécuter : git fetch upsteam --tags)

git fetch upstream

En règle générale, vous souhaitez que votre branche main locale soit un parfait miroir de la branche upstream main et vous voulez travailler dans des branches de fonctionnalité, car elles pourraient bien devenir des pull requests.

Pour le moment, que vous utilisiez merge ou rebase n'a pas d'importance, puisque le résultat sera le même. Utilisons merge :

git checkout main
git merge upstream/main

Lorsque vous souhaitez partager votre travail avec les mainteneurs upstream, vous créez une branche à partir de main, puis une branche de fonctionnalité. Une fois que vous êtes satisfait, pushez-la vers votre dépôt distant.

Vous pouvez également utiliser rebase, puis merge pour vous assurer que la branche upstream dispose d'un ensemble de commits nettoyé (idéalement, un seul) à évaluer :

git checkout -b feature-x

#some work and some commits happen
#some time passes

git fetch upstream
git rebase upstream/main

Publication grâce à un fork Git


Une fois que vous aurez effectué les étapes ci-dessus, publiez votre travail dans votre fork distant en utilisant un simple push :

git push origin feature-x
git push -f origin feature-x

Personnellement, je préfère conserver l'historique aussi propre que possible et utiliser la troisième option, mais les workflows varient en fonction des équipes. Remarque : ne procédez de la sorte que lorsque vous travaillez avec votre propre fork. Vous ne devez JAMAIS procéder à la réécriture de l'historique des dépôts et des branches partagés.

Astuce du jour : nombres de commits avant/après une branche dans l'invite


Après un fetch, git status vous montrera combien de commits se trouvent avant ou après la branche remote synchronisée. Ne serait-ce pas merveilleux si vous pouviez consulter ces informations avec cette bonne vieille invite de commande ? C'est la raison pour laquelle j'ai concocté un petit quelque chose avec bash.

Une fois la configuration effectuée, voici à quoi ressemblera votre invite :

nick-macbook-air:~/dev/projects/stash[1|94]$

Voici ce que vous devez ajouter à votre fichier .bashrc ou à un fichier équivalent, c'est-à-dire une seule fonction :

function ahead_behind {
    curr_branch=$(git rev-parse --abbrev-ref HEAD);
    curr_remote=$(git config branch.$curr_branch.remote);
    curr_merge_branch=$(git config branch.$curr_branch.merge | cut -d / -f 3);
    git rev-list --left-right --count $curr_branch...$curr_remote/$curr_merge_branch | tr -s '\t' '|';
}
export PS1="\h:\w[\$(ahead_behind)]$"

Fonctionnement interne

Pour ceux qui souhaitent plus d'informations et d'explications, voici comment cela fonctionne :

Nous obtenons le nom symbolique du HEAD courant, c'est-à-dire, de la branche courante :

curr_branch=$(git rev-parse --abbrev-ref HEAD);

Nous obtenons la branche distante vers laquelle la branche courante pointe :

curr_remote=$(git config branch.$curr_branch.remote);

Nous obtenons la branche sur laquelle ce remote doit être mergé (avec un petit truc Unix pour tout ignorer, même la dernière barre oblique [ / ]) :

curr_merge_branch=$(git config branch.$curr_branch.merge | cut -d / -f 3);

À présent, nous avons ce dont nous avons besoin pour compter le nombre de commits qui se trouvent avant ou après la branche :

git rev-list --left-right --count $curr_branch...$curr_remote/$curr_merge_branch | tr -s '\t' '|';

Nous utilisons l'ancienne commande Unix tr pour convertir TAB en séparateur |.

Premiers pas avec git upstream


Il s'agit d'une présentation de base de git upstream : comment configurer un git upstream, créer une branche, collecter les changements, publier avec git fork et une astuce pour savoir combien de commits vous avez en avance/retard sur votre branche distante.

Bitbucket Server inclut la synchronisation des forks, ce qui évite aux développeurs de devoir garder leurs forks à jour, et Bitbucket Cloud permet une synchronisation facile en une étape. À tester !

Suivez-moi (@durdn) et l'incroyable équipe @Bitbucket pour plus d'infos passionnantes sur DVCS.

Nicola Paolucci

Nicola is an all-round hacker who loves exploring and teaching bleeding edge technologies. He writes and talks about Git, development workflows, code collaboration and more recently about Docker. Prior to his current role as Developer Instigator at Atlassian he led software teams, built crowd sourcing applications for geo-spacial data, worked on huge e-commerce deployments. Little known facts about Nicola: he gesticulates a lot while speaking (being Italian), lives in Amsterdam and rides a Ducati.


Partager cet article
Thème suivant

Lectures recommandées

Ajoutez ces ressources à vos favoris pour en savoir plus sur les types d'équipes DevOps, ou pour les mises à jour continues de DevOps chez Atlassian.

Des personnes qui collaborent à l'aide d'un mur rempli d'outils

Le blog Bitbucket

Illustration DevOps

Parcours de formation DevOps

Démos Des démos avec des partenaires d'Atlassian

Fonctionnement de Bitbucket Cloud avec Atlassian Open DevOps

Inscrivez-vous à notre newsletter DevOps

Thank you for signing up