Flux de travail de développement #

Vous avez déjà votre propre copie dérivée du référentiel Matplotlib , en suivant Créer votre propre copie (fork) de Matplotlib . Vous avez configuré votre fork . Vous avez configuré git en suivant Configure git . Vous êtes maintenant prêt pour un vrai travail.

Résumé du flux de travail #

Dans ce qui suit, nous ferons référence à la branche Matplotlib en amont main, en tant que "tronc".

  • N'utilisez pas votre mainsuccursale pour quoi que ce soit. Pensez à le supprimer.

  • Lorsque vous démarrez un nouvel ensemble de modifications, récupérez toutes les modifications du tronc et démarrez une nouvelle branche de fonctionnalités à partir de celle-ci.

  • Créez une nouvelle branche pour chaque ensemble de modifications séparable — "une tâche, une branche" ( ipython git workflow ).

  • Nommez votre succursale en fonction des changements - par exemple bugfix-for-issue-14ou refactor-database-code.

  • Si vous pouvez éventuellement l'éviter, évitez de fusionner le tronc ou toute autre branche dans votre branche de fonctionnalité pendant que vous travaillez.

  • Si vous vous retrouvez à fusionner à partir du tronc, envisagez de rebaser sur le tronc

  • Demandez sur la liste de diffusion Matplotlib si vous êtes bloqué.

  • Demandez une révision de code !

Cette façon de travailler aide à garder le travail bien organisé, avec un historique lisible. Cela permet aux mainteneurs du projet (c'est peut-être vous) de voir plus facilement ce que vous avez fait et pourquoi vous l'avez fait.

Voir linux git workflow et ipython git workflow pour des explications.

Pensez à supprimer votre branche principale #

Cela peut sembler étrange, mais la suppression de votre propre mainbranche peut aider à réduire la confusion quant à la branche sur laquelle vous vous trouvez. Voir supprimer main sur github pour plus de détails.

Mettre à jour le miroir du coffre #

Assurez-vous d'abord que vous avez fait Lier votre dépôt au dépôt en amont .

De temps en temps, vous devriez récupérer les modifications en amont (tronc) à partir de github :

git fetch upstream

Cela supprimera tous les commits que vous n'avez pas et définira les branches distantes pour qu'elles pointent vers le bon commit. Par exemple, 'trunk' est la branche référencée par (remote/branchname) upstream/main- et s'il y a eu des validations depuis la dernière vérification, upstream/maincela changera après la récupération.

Créer une nouvelle branche de fonctionnalité #

Lorsque vous êtes prêt à apporter des modifications au code, vous devez démarrer une nouvelle branche. Les branches destinées à un ensemble de modifications associées sont souvent appelées "branches de fonctionnalités".

La création d'une nouvelle branche pour chaque ensemble de modifications associées permettra à une personne examinant votre branche de voir plus facilement ce que vous faites.

Choisissez un nom informatif pour la branche pour vous rappeler, ainsi qu'au reste d'entre nous, à quoi servent les changements dans la branche. Par exemple add-ability-to-fly, ou bugfix-for-issue-42.

# Update the mirror of trunk
git fetch upstream
# Make new feature branch starting at current trunk
git branch my-new-feature upstream/main
git checkout my-new-feature

En règle générale, vous souhaiterez conserver vos branches de fonctionnalités sur votre fork github public de Matplotlib . Pour ce faire, vous git poussez cette nouvelle branche vers votre référentiel github. Généralement (si vous avez suivi les instructions de ces pages, et par défaut), git aura un lien vers votre référentiel github, appelé origin. Vous accédez à votre propre référentiel sur github avec :

git push origin my-new-feature

Dans git >= 1.7, vous pouvez vous assurer que le lien est correctement défini en utilisant l' --set-upstreamoption :

git push --set-upstream origin my-new-feature

À partir de maintenant, git saura que my-new-featurec'est lié à la my-new-featurebranche dans le dépôt github.

Le workflow d'édition #

Aperçu #

# hack hack
git add my_new_file
git commit -am 'NF - some message'
git push

Plus en détail #

  1. Faire quelques changements

  2. Voir avec quels fichiers ont été modifiés (voir git status ). Vous verrez une liste comme celle-ci :git status

    # On branch ny-new-feature
    # Changed but not updated:
    #   (use "git add <file>..." to update what will be committed)
    #   (use "git checkout -- <file>..." to discard changes in working directory)
    #
    #  modified:   README
    #
    # Untracked files:
    #   (use "git add <file>..." to include in what will be committed)
    #
    #  INSTALL
    no changes added to commit (use "git add" and/or "git commit -a")
    
  3. Vérifiez quelles sont les modifications réelles avec ( git diff ).git diff

  4. Ajoutez tout nouveau fichier au contrôle de version (voir git add ).git add new_file_name

  5. Pour valider tous les fichiers modifiés dans la copie locale de votre dépôt, faites . Notez les options de . Le drapeau signale simplement que vous allez taper un message sur la ligne de commande. Le drapeau - vous pouvez simplement croire en vous - ou voir pourquoi le drapeau -a ? - et la description utile du cas d'utilisation dans le problème de la copie de travail enchevêtrée . La page de manuel de git commit peut également être utile.git commit -am 'A commit message'-amcommitma

  6. Pour pousser les modifications jusqu'à votre repo forké sur github, faites un (voir git push ).git push

Demandez que vos modifications soient examinées ou fusionnées #

Lorsque vous êtes prêt à demander à quelqu'un de revoir votre code et d'envisager une fusion :

  1. Accédez à l'URL de votre référentiel forké, par exemple https://github.com/your-user-name/matplotlib.

  2. Utilisez le menu déroulant "Changer de branche" en haut à gauche de la page pour sélectionner la branche avec vos modifications :

    ../../_images/branch_dropdown.png
  3. Cliquez sur le bouton 'Pull request' :

    ../../_images/pull_button.png

    Entrez un titre pour l'ensemble de modifications et une explication de ce que vous avez fait. Dites s'il y a quelque chose pour lequel vous aimeriez une attention particulière - comme un changement compliqué ou un code dont vous n'êtes pas satisfait.

    Si vous pensez que votre demande n'est pas prête à être fusionnée, dites-le simplement dans votre message de demande d'extraction. C'est toujours un bon moyen d'obtenir une révision préliminaire du code.

D'autres choses que vous voudrez peut-être faire #

Supprimer une branche sur github #

git checkout main
# delete branch locally
git branch -D my-unwanted-branch
# delete branch on github
git push origin :my-unwanted-branch

Notez les deux-points :avant my-unwanted-branch. Voir aussi : https://help.github.com/articles/pushing-to-a-remote/#deleting-a-remote-branch-or-tag

Plusieurs personnes partageant un seul référentiel #

Si vous souhaitez travailler sur des éléments avec d'autres personnes, où vous vous engagez tous dans le même référentiel, ou même dans la même branche, partagez-le simplement via github.

D'abord fork Matplotlib dans votre compte, à partir de Making your own copy (fork) of Matplotlib .

Ensuite, accédez à la page github de votre référentiel fourchu, dites https://github.com/your-user-name/matplotlib

Cliquez sur le bouton "Admin" et ajoutez quelqu'un d'autre au référentiel en tant que collaborateur :

../../_images/pull_button.png

Maintenant, toutes ces personnes peuvent faire :

git clone https://github.com/your-user-name/matplotlib.git

N'oubliez pas que les liens commençant par httpsou git@sont en lecture-écriture, et qu'ils git@utilisent le protocole ssh.

Vos collaborateurs peuvent ensuite s'engager directement dans ce référentiel avec l'habituel :

git commit -am 'ENH - much better code'
git push origin main # pushes directly into your repo

Explorez votre référentiel #

Pour voir une représentation graphique des branches et des commits du référentiel :

gitk --all

Pour voir une liste linéaire des commits pour cette branche :

git log

Vous pouvez également consulter le visualiseur de graphique de réseau pour votre référentiel github.

Enfin, l' alias de sortie du journal Fancy lg vous donnera un graphique textuel raisonnable du référentiel.

Rebasage sur tronc #

Disons que vous avez pensé à un travail que vous aimeriez faire. Vous mettez à jour le miroir du tronc et créez une nouvelle branche de fonctionnalité appelée cool-feature. À ce stade, le tronc est à un certain commit, appelons-le E. Maintenant, vous faites de nouveaux commits sur votre cool-featurebranche, appelons-les A, B, C. Peut-être que vos modifications prennent un certain temps, ou vous y revenez après un certain temps. Entre-temps, le tronc est passé du commit E au commit (disons) G :

      A---B---C cool-feature
     /
D---E---F---G trunk

À ce stade, vous envisagez de fusionner le tronc dans votre branche de fonctionnalités, et vous vous souvenez que cette page ici vous conseille sévèrement de ne pas le faire, car l'historique deviendra désordonné. La plupart du temps, vous pouvez simplement demander une révision et ne pas vous inquiéter que le coffre ait un peu d'avance. Mais parfois, les modifications apportées au coffre peuvent affecter vos modifications et vous devez les harmoniser. Dans cette situation, vous préférerez peut-être effectuer un rebase.

rebase prend vos modifications (A, B, C) et les rejoue comme si elles avaient été apportées à l'état actuel de trunk. En d'autres termes, dans ce cas, il prend les modifications représentées par A, B, C et les rejoue au-dessus de G. Après le rebase, votre historique ressemblera à ceci :

              A'--B'--C' cool-feature
             /
D---E---F---G trunk

Voir rebase sans déchirure pour plus de détails.

Pour faire un rebasage sur tronc :

# Update the mirror of trunk
git fetch upstream
# go to the feature branch
git checkout cool-feature
# make a backup in case you mess up
git branch tmp cool-feature
# rebase cool-feature onto trunk
git rebase --onto upstream/main upstream/main cool-feature

Dans cette situation, où vous êtes déjà sur branch cool-feature, la dernière commande peut être écrite plus succinctement comme suit :

git rebase upstream/main

Lorsque tout semble bon, vous pouvez supprimer votre branche de sauvegarde :

git branch -D tmp

Si cela ne semble pas bon, vous devrez peut-être jeter un coup d'œil à Recovering from mess-ups .

Si vous avez apporté des modifications à des fichiers qui ont également été modifiés dans le tronc, cela peut générer des conflits de fusion que vous devez résoudre - consultez la page de manuel git rebase pour obtenir des instructions à la fin de la section "Description". Il existe une aide connexe sur la fusion dans le manuel de l'utilisateur de git - voir résoudre une fusion .

Récupération de mess-ups #

Parfois, vous gâchez des fusions ou des rebases. Heureusement, dans git, il est relativement simple de se remettre de telles erreurs.

Si vous vous trompez lors d'un rebase :

git rebase --abort

Si vous remarquez que vous vous êtes trompé après le rebase :

# reset branch back to the saved point
git reset --hard tmp

Si vous avez oublié de créer une branche de sauvegarde :

# look at the reflog of the branch
git reflog show cool-feature

8630830 [email protected]{0}: commit: BUG: io: close file handles immediately
278dd2a [email protected]{1}: rebase finished: refs/heads/my-feature-branch onto 11ee694744f2552d
26aa21a [email protected]{2}: commit: BUG: lib: make seek_gzip_factory not leak gzip obj
...

# reset the branch to where it was before the botched rebase
git reset --hard [email protected]{2}

Réécriture de l'historique des commits #

Noter

Faites cela uniquement pour vos propres branches de fonctionnalités.

Il y a une faute de frappe embarrassante dans un commit que vous avez fait ? Ou peut-être que vous avez fait plusieurs faux départs que vous aimeriez que la postérité ne voie pas.

Cela peut être fait via un rebasage interactif .

Supposons que l'historique des commits ressemble à ceci :

git log --oneline
eadc391 Fix some remaining bugs
a815645 Modify it so that it works
2dec1ac Fix a few bugs + disable
13d7934 First implementation
6ad92e5 * masked is now an instance of a new object, MaskedConstant
29001ed Add pre-nep for a copule of structured_array_extensions.
...

et 6ad92e5est le dernier commit de la cool-featurebranche. Supposons que nous souhaitions apporter les modifications suivantes :

  • Réécrivez le message de validation pour 13d7934quelque chose de plus sensé.

  • Combinez les commits 2dec1ac, a815645, eadc391en un seul.

Nous procédons comme suit :

# make a backup of the current state
git branch tmp HEAD
# interactive rebase
git rebase -i 6ad92e5

Cela ouvrira un éditeur contenant le texte suivant :

pick 13d7934 First implementation
pick 2dec1ac Fix a few bugs + disable
pick a815645 Modify it so that it works
pick eadc391 Fix some remaining bugs

# Rebase 6ad92e5..eadc391 onto 6ad92e5
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

Pour réaliser ce que nous voulons, nous y apporterons les modifications suivantes :

r 13d7934 First implementation
pick 2dec1ac Fix a few bugs + disable
f a815645 Modify it so that it works
f eadc391 Fix some remaining bugs

Cela signifie que (i) nous voulons éditer le message de commit pour 13d7934, et (ii) regrouper les trois derniers commits en un seul. Maintenant, nous sauvegardons et quittons l'éditeur.

Git affichera alors immédiatement un éditeur pour éditer le message de validation. Après révision, nous obtenons la sortie :

[detached HEAD 721fc64] FOO: First implementation
 2 files changed, 199 insertions(+), 66 deletions(-)
[detached HEAD 0f22701] Fix a few bugs + disable
 1 files changed, 79 insertions(+), 61 deletions(-)
Successfully rebased and updated refs/heads/my-feature-branch.

et l'historique ressemble maintenant à ceci :

0f22701 Fix a few bugs + disable
721fc64 ENH: Sophisticated feature
6ad92e5 * masked is now an instance of a new object, MaskedConstant

Si cela s'est mal passé, la récupération est à nouveau possible comme expliqué plus haut .