@VinceOPS

Git : Astuces et productivité #2

git

Dans ce second article de la série, je parle d’alias, de git add -p (patch) et de l’intégration de git dans VS Code.


Alias de commandes

Ce n’est pas grand chose, car on parle de quelques secondes grattées par-ci par-là. Mais grattées jusqu’à plusieurs dizaines de fois par jour, ça compte comme de la productivité 😏 !

Au quotidien, j’utilise le Z shell aka zsh, avec oh-my-zsh. L’idée n’est pas de vous présenter mon thème ou mon setup (Debian 9 avec i3wm), mais de partager quelques alias très pratiques importés par le plugin git de oh-my-zsh. Il est activé par défaut. Vous pouvez aussi les récupérer directement ici et les intégrer à votre fichier run commands (.bashrc, .zshrc…).

Parmi ceux que j’utilise souvent :

  • g : git
  • ga : git add (gaa pour git add --all)
  • gcb : git checkout -b
  • gcm : git checkout master
  • gc : git commit
  • gcn! : git commit --no-edit --amend
  • gd : git diff
  • ggpur : git pull --rebase origin <current_branch>
  • gfa : git fetch --all --prune
  • gpf : git push --force--with-lease (gpf! pour --force)
  • grb : git rebase (grba pour --abort, grbc pour --continue, grbi pour -i) 💖
  • groh : git reset --hard origin/<current_branch>
  • gst : git status

Évidemment, on les mémorise à force de réutilisation.

Au passage, oh-my-zsh a aussi un plugin yarn avec quelques alias tous aussi efficaces :

  • y : yarn
  • ya : yarn add (yad pour --dev)
  • yb : yarn build
  • yrm : yarn remove
  • yst : yarn start
  • yt : yarn test 🔥

Et maintenant, parlons de trucs utiles !

Indexation partielle avec git add -p

C’est une option présentée dans le mode interactif (-i) de git add (cf. le ”Book” 📚 !) qui permet l’indexation (staging) partielle d’un fichier.

Exemple “True story”

Vous travaillez sur une évolution de votre produit en suivant votre cycle Red/Green/Refacto habituel. Et là, c’est le drame. Vous trouvez un bout de code “legacy” (“oh my god, he said the L word! 😱”) que vous savez refacto par cœur.

- 👼 : “Fais d’abord passer ton test. Cette refacto peut attendre.”
- 👿 : “C’est quoi ce code ?! Allez nettoie, y en a pour 20 secondes !”

Quoi qu’il arrive, le fichier va subir deux modifications, une pour l’évolution, une pour le refactoring.

REFACTOR ME

Plusieurs options s’offrent à vous, dont :

  • Pousser tous les changements dans un seul et même commit (DON’T, les commits atomiques, tout ça…)
  • Remiser (git stash) les changements, faire et enregistrer le refactoring dans un commit dédié, reprendre les changements remisés (git stash pop)
  • Avoir recours à git add -p pour indéxer et commit seulement le refactoring 🤷

Pour traiter un cas simple, les exemples qui suivent montrent l’ajout d’un test unitaire 🙄.

Via la CLI

Vous devez faire évoluer le code d’un collègue fan de retrospective testing (ou “j’écris mes tests une fois que je crois avoir fini”) et vous constatez qu’un cas d’usage n’a pas été couvert. Vous écrivez le test qui va bien et décidez de l’indexer immédiatement :

$ git add -p
diff --git a/src/input-parsing/input-reporting.service.spec.ts b/src/input-parsing/input-reporting.service.spec.ts
index 10e5cc8..b9cf134 100644
--- a/src/input-parsing/input-reporting.service.spec.ts
+++ b/src/input-parsing/input-reporting.service.spec.ts

Pour chaque fichier modifié, ici src/input-parsing/input-reporting.service.spec.ts, le terminal affiche les changements indexables :

@@ -10,6 +10,11 @@ describe('InputReportingService', () => {
     const separatorRow = `🤸;🏋;🚴;🚣;🏊;`;
     const emptyRow = `;;;;;`;

+    it('writes any new file starting with a "separator"', () => {
+      const result = service.generateSynthesis([]);
+      expect(result.startsWith(separatorRow)).toEqual(true);
+    });
+
     it('adds an empty row after a new entry', () => {
       const result = service.generateSynthesis([]);
       expect(result.startsWith(separatorRow)).toEqual(true);

💡 Voici du bullshit code : totalement factice, à usage purement démonstratif. Et oui Jamy !

Stage this hunk [y,n,q,a,d,e,?]? ?

Différentes options s’offrent à vous pour le traitement de ce ”hunk” (morceau) :

  • y - Indexer le morceau présenté
  • n - Ignorer ce morceau et passer au suivant
  • q - Abandonner / quitter ce mode interactif
  • a - Indexer ce morceau et tous ceux du fichier courant
  • d - Ignorer ce morceau et passer au fichier suivant
  • e - Modifier manuellement le morceau courant (pour les ajouts !)

💡 Sur des plus gros hunks, quelques autres options sont disponibles :

  • g - Sélectionner un morceau dans le fichier courant
  • / - Chercher un morceau en utilisant une Regex
  • s - Proposer à nouveau ces options avec un morceau plus petit (découpé en plusieurs morceaux)
  • j - Marquer ce morceau comme “indécis” et sélectionner le prochain morceau indécis
  • J - Marquer ce morceau comme “indécis” et sélectionner le morceau suivant

Dans le cas d’un fichier ayant été modifié à deux endroits, on peut donc indexer un premier morceau, enregistrer un commit, puis à nouveau indexer le deuxième morceau et enregistrer un autre commit.
Comme argumenté dans le premier article de cette série : un historique plus clair, un versionning plus granulaire et des reviewers plus heureux !

Dans VS Code

L’éditeur offre une interface très pratique pour l’indexation de hunks :

Stage a Hunk with VS Code

En ouvrant un fichier depuis l’onglet Source Control, on peut sélectionner des morceaux (changés, ajoutés, ou supprimés) et les indexer, ou les désindexer. Je préfère cette approche visuelle, que je trouve plus efficace pour les besoins les plus communs. C’est d’ailleurs une habitude bien ancrée : j’alterne en permanence entre les terminaux et l’éditeur, en fonction de ce qui me proccure la meilleure vélocité 🚀.

VS Code + Git = 💕

En ce qui concerne VS Code, il y a quelques “trucs” qu’il faut absolument connaître :

Éditeur

Vous pouvez définir VS Code comme éditeur pour git.
En effet, après avoir vérifié que code était disponible dans votre PATH, lancez la commande git config --global core.editor "code --wait".
La modification de la configuration Git, les rebasages intéractifs, etc, peuvent ainsi être effectués via VS Code :

VSCode comme Éditeur git

Ici, il est question d’être efficace : je préfère me retrouver sur VSCode que sur un éditeur vi-like pour ce genre d’opérations. C’est personnel.

GitLens

Extension absolument incontournable de VS Code, GitLens offre entre autres :

  • L’affichage du git blame (auteur/date de la dernière modification) de la ligne courante
const weekMoment = moment() // VinceOPS, a month ago • feat: a week as a period  .set("week", weekNumber)
  .set("year", year);
  • La comparaison, pour le fichier courant, de ses révisions N et N-1 (puis N-1 et N-2, et ainsi de suite)…

VSCode & GitLens - Diff

Au quotidien, ce sont ces deux premières fonctionnalités qui me sont les plus utiles.

  • Dans un onglet dédié de la side bar :

    • L’historique des commits de la branche courante, avec affichage (diff) de chaque modification
    • La navigation dans les différentes branches du dépôt
    • La liste des différentes remises (stash) du dépôt
    • La recherche de commits par auteur, message, SHA1, fichiers modifiés…
    • Plein de trucs que l’on peut faire plus vite depuis un terminal (créer/supprimer/merge une branche, etc)

VSCode & GitLens - Diff

L’historique des commits d’une branche est très utile pour de la code review, ou pour se remémorer ses derniers travaux 😁. Consultez la liste exhaustive des fonctionnalités, vous dénicherez peut-être votre pépite.

C’est tout pour ce second article. #teaser Dans le prochain, on parlera de amend, de rebase (avec squash et fixup), ainsi que du reflog.


VinceOPS

Retrouvez-moi sur Twitter 🤷
@VinceOPS