Expérimenter avec des pull requests empilées
Jeune arbre est un nouveau système de contrôle de source développé par Meta. Récemment, il a acquis la capacité de travailler avec GitHub. Je suis curieux de savoir comment cela fonctionne, j’ai donc décidé de l’essayer et j’ai fini par l’utiliser quotidiennement sur les référentiels de mon entreprise. Si vous voulez l’essayer, vérifiez leur documentation ici.
Lors du développement, je crée généralement un seul commit pour chaque PR et je les empile ensemble.
Par exemple, disons que nous développons la fonctionnalité d’inscription : l’utilisateur saisit son adresse e-mail, son mot de passe, et nous lui envoyons un e-mail de bienvenue. Du point de vue du backend, nous devons créer un nouvel utilisateur, vérifier que l’utilisateur n’existe pas et envoyer l’e-mail. Nous devons toucher à l’implémentation du package de cache, ajouter un package de messagerie, puis enfin implémenter la logique d’inscription. Cela peut être représenté comme une pile de PR :
- Mettez à jour le package de cache pour ajouter une nouvelle méthode.
- Ajoutez le système d’envoi d’e-mails. Il utilise le package de cache pour empêcher l’envoi d’e-mails en double.
- Mettre en œuvre la logique d’inscription. Cela dépend des deux changements ci-dessus.
L’avantage : cela aide les examinateurs à séparer les préoccupations. Les modifications plus petites et isolées sont plus faciles à examiner. Ils peuvent vérifier les PR un par un, chaque PR contenant une logique indépendante. Bien sûr, le système de messagerie nécessite toujours la mise à jour du package de cache, mais nous pouvons toujours examiner le système de messagerie de manière isolée.
Lorsque l’origine est mise à jour, nous récupérons les modifications et rebasons les PR au-dessus de l’origine, poussons les modifications, les examinons et les fusionnons.
L’inconvénient : il faut de la discipline pour garder les PR petits et isolés. Habituellement, lors du développement des PR supérieurs, nous devons apporter quelques modifications aux PR inférieurs. Cela peut être ennuyeux car nous devons garder une trace de ce qui change dans quel PR ou basculer constamment entre les PR pour apporter des modifications, puis rebaser les supérieurs.
git checkout mybranch/signup # checkout sign up branch
vim features/signup/signup.go # make changes to signup
vim lib/email/email.go # make changes to email packagegit add features/signup # commit the signup changes
git commit --amend
git stash # stash the cache changes
git checkout mybranch/email # checkout email branch
git stash pop # apply the cache changes
git add lib/email # commit the email changes
git commit --amend
git checkout mybranch/signup # checkout sign up branch again
git rebase mybranch/email # rebase the signup branch on top of email branch
Trop de commutations et trop de commandes à taper. Ce n’est pas amusant.
Sapling est un nouveau client git. Il encourage l’utilisation de PR empilés. Il rebasera automatiquement les PR les uns sur les autres, nous n’avons donc pas à le faire manuellement.
Étant donné la structure de commit suivante, présentée en appelant le sl
commande, voici à quoi cela ressemblera :
sl
@ 00f1749f6 30 minutes ago oliver
│ implement user signup
│
@ e0dbbc80e 50 minutes ago oliver
│ implement email package
│
o 4f6928029 Yesterday at oliver
╭─╯ update cache package
│
o 876f46044 Today at 07:45 remote/main
Le flux de travail avec le jeune arbre sera :
sl goto 00f1749f6 # checkout the sign up code
vim features/signup/signup.go # make changes to signup
vim lib/email/email.go # make changes to email packagesl absorb # magic 👻
Avec une seule commande, sl absorb
le jeune arbre va :
- Modifier le
email.go
modifications apportées au commit par e-mail. - Modifier le
signup.go
modifications apportées au commit d’inscription. - Rebasez le commit d’inscription sur le commit d’e-mail.
Vos modifications seront absorbées dans les PR, et les PR seront rebasés les uns sur les autres. Vous n’avez pas à le faire manuellement comme avant. Avec une seule commande. Bien fait!
J’utilise des gaules depuis quelques semaines maintenant. C’est un nouvel outil, donc il y a quelques problèmes, mais l’expérience globale est excellente.
Commandes couramment utilisées
Afficher l’état du référentiel :
sl
: affiche le commit-graph (ou smart-log)sl status
: affiche l’état de la branche actuelle
Se déplacer entre les commits :
sl goto <commit>
: vérifier le commitsl next
,sl prev
: vérifier le commit suivant/précédent
Travailler avec des commits :
sl add
,sl remove
,sl forget
: ajouter/supprimer/annuler le suivi des fichierssl commit
: commitez les changements comme un nouveau commitsl metaedit
: édite le message de commitsl absorb
: absorber les changements dans les PR et rebaser les PR les uns sur les autressl rebase
: rebaser les PR les uns sur les autres
Alors que git add
ajoute toutes les modifications à la zone de préparation, y compris les nouveaux fichiers et les fichiers supprimés, la commande correspondante sl add
ajoutera uniquement de nouveaux fichiers à la zone de préparation. Pour supprimer des fichiers, nous devons utiliser sl remove
. Ce sera un peu ennuyeux lors de la validation des fichiers du fournisseur, car nous devons répertorier tous les fichiers supprimés pour les supprimer. Je ne sais pas s’il existe un meilleur moyen, mais voici à quoi ressemble le code :
$ sl status? vendor/github.com/sample/cache/v2/caching.go
? vendor/github.com/sample/cache/v2/stripe.go
! vendor/github.com/sample/cache/v1/deprecated.go
! vendor/github.com/sample/cache/v1/formatter.go
$ sl add vendorA vendor/github.com/sample/cache/v2/caching.go
A vendor/github.com/sample/cache/v2/stripe.go
! vendor/github.com/sample/cache/v1/deprecated.go
! vendor/github.com/sample/cache/v1/formatter.go
# Have to list all deleted files to remove, is there a better way? 😞
$ sl remove vendor/github.com/sample/cache/v1/deprecated.go \
vendor/github.com/sample/cache/v1/formatter.goA vendor/github.com/sample/cache/v2/caching.go
A vendor/github.com/sample/cache/v2/stripe.go
R vendor/github.com/sample/cache/v1/deprecated.go
R vendor/github.com/sample/cache/v1/formatter.go
Pousser les PR vers GitHub
Sapling propose deux façons de pousser les PR vers GitHub : sl pr
et sl ghstack
. Chacun a des compromis différents. Je préfère utiliser le sl pr
commande car elle propose les éléments suivants :
- Il crée un PR pour chaque commit.
- Il pousse les PR vers GitHub dans l’ordre des commits.
- C’est plus facile à comprendre car les commits s’empilent bien les uns sur les autres.
- Cela fonctionne bien et peut être revu avec l’interface utilisateur de GitHub.
- Il ne nécessite pas d’autorisation d’écriture sur le référentiel au cas où vous feriez un fork.
La sl ghstack
commande crée un réseau plus complexe de PR. Et il arrive souvent qu’il ne réussisse pas à pousser les relations publiques. Essayez à nouveau, et cela ne fonctionnera toujours pas. Aucun correctif disponible. Je dois dupliquer à nouveau ces PR et risquer de spammer les référentiels de mon entreprise. Je ne le recommande pas.
Examen des PR
Sapling recommande d’utiliser pile de critiques pour révision. Mais je le trouve lent, moins réactif et donne parfois de mauvais changements de fichiers. Je préfère utiliser l’interface utilisateur de GitHub. Lorsque vous poussez des PR avec sl pr
, il crée un seul commit pour chaque PR. Ainsi, le réviseur peut ouvrir le dernier commit et examiner les modifications. Juste un clic supplémentaire par rapport au flux de révision habituel. Voici comment procéder :
- Accédez à l’onglet Commits.
- Choisissez le dernier commit.
- Révisez et ajoutez des commentaires. Ces commentaires apparaîtront sur le PR comme d’habitude.
Autres choses
Cela nécessite le clonage d’un nouveau référentiel, vous ne pouvez donc pas utiliser vos commandes git familières. Cela ne fonctionnera pas avec vos outils existants, IDE, etc. Vous devez utiliser le sl web
Interface utilisateur pour afficher les modifications.