Comment faciliter la vie lors de l'utilisation de Git (ainsi qu'une sélection de matériaux pour une immersion profonde)


Tree of Dragons II par surrealistguitarist

Pour ceux qui utilisent Git tous les jours mais ne se sentent pas en sécurité, l'équipeMail.ru Cloud Solutions a traduit un article du développeur front-end Shane Hudson . Vous trouverez ici quelques trucs et astuces qui peuvent faciliter le travail avec Git, ainsi qu'une sélection d'articles et de manuels d'un niveau plus avancé.

Git est apparu il y a presque 15 ans. Pendant ce temps, il est passé d'un outsider à un champion invincible. Aujourd'hui, les nouveaux projets commencent souvent par une équipe git init. Sans aucun doute, c'est un outil important que beaucoup d'entre nous utilisent quotidiennement, mais il ressemble souvent à la magie - brillant, mais dangereux.

De nombreux articles ont été publiés sur Habr, comment démarrer avec Git, comment Git fonctionne sous le capot et des descriptions des meilleures stratégies de branchement. Ici, l'auteur s'est concentré sur la façon de simplifier le travail avec Git.

Nous mettons les choses en ordre


Le but de Git est de sauvegarder votre travail, de changer de contexte - et de faire autre chose. Cela peut être une sauvegarde du code ou la possibilité de développer de manière asynchrone plusieurs fonctions différentes. Il serait terrible de jeter la deuxième version uniquement parce qu'une erreur a été trouvée dans la première. Il n'est pas moins gênant d'enregistrer des fichiers avec des noms comme v1_final_bug_fixed. Comme vous le savez, cela conduit à un gâchis complet.

Nous savons tous que la vie devient beaucoup plus facile lorsque nos mises à jour sont soigneusement disposées sur des branches Git que vous pouvez partager avec vos collègues. Mais souvent, des situations surviennent lorsque vous changez de contexte, puis revenez en arrière - et vous ne pouvez pas trouver la bonne branche. Y avait-il un engagement? Peut-être qu'il est caché? Peut-être que le commit n'a pas réussi, maintenant tout le monde est allé dans la mauvaise branche, et tout est mauvais, et je fais un très mauvais travail! Oui, tout le monde était là et ressentait de tels doutes. Il existe des moyens de faire face à cette situation.

Trier les branches par date


Le tri par date affiche toutes vos succursales locales, en commençant par la dernière. Assez banal, mais cela m'a aidé plusieurs fois:

# To sort branches by commit date
git branch --sort=-committerdate

Fil précédent


Que se passe-t-il si vous ne vous êtes pas engagé, que vous avez changé de branche et que vous souhaitez revenir à la précédente? Vous pouvez probablement le trouver dans la liste des branches si vous avez une idée de son nom. Mais que faire si ce n'est pas une branche, mais un detached HEADcommit spécifique?

Il s'avère qu'il existe une solution simple:

# Checkout previous branch
git checkout -

L'opérateur -est un raccourci pour la syntaxe @{-1}qui vous permet de basculer vers un nombre illimité de retraits. Donc, si, par exemple, vous avez créé une branche feature/thing-a, alors feature/thing-b, et puis bugfix/thing-c, le paramètre @{-2}vous renverra à feature/thing-a:

# Checkout branch N number of checkouts ago
git checkout @{-N}

Afficher des informations sur toutes les branches


L'indicateur vaffiche une liste de toutes les branches avec le dernier identifiant de validation et le dernier message. Le double vvaffichera également les branches amont distantes, suivies des branches locales:

# List branches along with commit ID, commit message and remote
git branch -vv

Trouver un fichier


Nous sommes tous tombés dans cette situation: d'une manière ou d'une autre, il s'est avéré qu'un fichier a été laissé dans la mauvaise branche. Que faire? Refaire tout le travail ou copier du code d'une branche à une autre? Non, heureusement, il existe un moyen de trouver un fichier spécifique.

La méthode est un peu étrange, étant donné qu'elle git checkout -vous ramène à la branche précédente. En général, si vous spécifiez --après le nom de la branche lors du paiement, cela vous permettra de spécifier le fichier spécifique que vous recherchez. Vous ne devinerez pas une telle fonction sans un indice, mais c'est très pratique si vous savez:

git checkout feature/my-other-branch -- thefile.txt

Effacer le statut


Tomasz Lacoma a tweeté sur la réduction de l'émission git statusà l'aide de drapeaux -sbet a ajouté: "Pendant de nombreuses années, j'utilise Git, mais personne ne m'en a parlé." Il ne s'agit pas seulement de retrouver des fichiers perdus. Il arrive que la simplification du problème facilite la visualisation des modifications.

La plupart des commandes Git ont ces indicateurs, vous devez donc apprendre à les utiliser pour personnaliser votre flux de travail:

# Usually we would use git status to check what files have changed
git status

# Outputs:
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified: README.md

Untracked files:
(use "git add <file>..." to include in what will be committed)

another-file
my-new-file

# Using the flags -sb we can shorten the output
git status -sb

# Outputs:
## master
M README.md
?? another-file
?? my-new-file

L'histoire toute entière


Il y a des moments où quelque chose a complètement mal tourné, par exemple, vous avez accidentellement ignoré les modifications (préparatoires) par étapes avant de les valider. Si cela git logne vous permet pas de revenir à l'état précédent et qu'aucun des conseils ci-dessus ne vous aide, c'est git reflog.

Toutes vos actions dans Git qui modifient le contenu par référence HEAD@{}(par exemple push/pull/branch/checkout/commit) tombent dans le reflog (journal de référence). En fait, c'est l'histoire de toutes vos actions, quelle que soit la branche dans laquelle vous vous trouvez. C'est la différence avec git log, qui montre les changements pour une branche particulière.


Vous pouvez le faire git showavec l'ID de validation - et voir la modification spécifique. Si c'est ce que vous cherchiez, il git checkoutvous transférera vers la branche souhaitée ou même vous permettra de sélectionner un fichier spécifique, comme indiqué ci-dessus:

# See the reference log of your activity
git reflog --all

# Look at the HEAD at given point from reflog
git show HEAD@{2}

# Checkout the HEAD, to get back to that point
git checkout HEAD@{2}

Fichiers de préparation qui ont manqué la validation


Dans les cas extrêmes, si cela git reflogn'aide pas à récupérer vos fichiers (par exemple, vous avez effectué une réinitialisation matérielle avec des fichiers intermédiaires), il y a une autre astuce.

Chaque modification est stockée dans des objets .git/objectsremplis de fichiers dans le projet actif, il est donc presque impossible de le comprendre. Cependant, il existe une commande Git appelée git fsck, qui est utilisée pour vérifier l'intégrité (présence de fichiers endommagés) dans le référentiel. Nous pouvons l'utiliser avec un indicateur --lost-foundpour rechercher tous les fichiers non liés à une validation. Ces fichiers sont appelés "blob pendants".

Cette commande vous permet également de trouver des «arbres suspendus» et des «commits suspendus». Si vous le souhaitez, vous pouvez utiliser le drapeau --dangling, mais l'avantage--lost-founden ce qu 'il extrait tous les fichiers pertinents dans un dossier .git/lost-found. Très probablement, dans un projet actif, vous aurez de nombreux fichiers "suspendus". Git a une commande d'élimination des déchets qui s'exécute régulièrement et les supprime.

Ainsi, il --lost-foundaffichera tous les fichiers et l'heure / la date de création, ce qui facilite grandement la recherche. Notez que chaque fichier séparé sera toujours séparé, c'est-à-dire que vous ne pouvez pas utiliser le paiement. De plus, tous les fichiers auront des noms incompréhensibles (hachage), vous devez donc copier les fichiers nécessaires vers un autre emplacement:

# This will find any change that was staged but is not attached to the git tree
git fsck --lost-found

# See the dates of the files
ls -lah .git/lost-found/other/

# Copy the relevant files to where you want them, for example:
cp .git/lost-found/other/73f60804ac20d5e417783a324517eba600976d30 index.html

Git dans le travail d'équipe


Utiliser Git seul est une chose, mais lorsque vous travaillez dans une équipe de personnes, généralement avec des expériences, des compétences et des outils complètement différents, Git peut être à la fois une bénédiction et une malédiction. Il s'agit d'un outil puissant pour partager la même base de code, effectuer une revue de code et suivre les progrès de toute l'équipe. Dans le même temps, tous les employés doivent avoir une compréhension commune de la façon de l'utiliser dans le travail d'équipe. Peu importe de quoi il s'agit: la convention de nommer les branches, de formater le message d'accompagnement dans le commit, ou de choisir les fichiers à inclure dans le commit, il est important d'assurer une bonne communication et de s'entendre sur la façon d'utiliser cet outil.

Il est toujours important d'assurer la simplicité de l'intégration pour les débutants et de penser à ce qui se passera s'ils commencent à commettre sans connaître les principes et conventions adoptés par l'entreprise. Ce n'est pas la fin du monde, mais cela peut créer une certaine confusion et prendre du temps pour revenir à une approche coordonnée.

Cette section contient quelques recommandations sur la façon d'intégrer les accords acceptés directement dans le référentiel lui-même, d'automatiser et d'émettre le nombre maximal de tâches dans les déclarations. Dans le cas idéal, tout nouvel employé commence presque immédiatement à travailler dans le même style que le reste de l'équipe.

Les mêmes fins de ligne


Par défaut, Windows utilise des fins de ligne DOS \r\n(CRLF), tandis que Mac et Linux utilisent des fins de ligne UNIX \n(LF), tandis que les anciennes versions de Mac utilisent \r(CR). Ainsi, à mesure que l'équipe s'agrandit, le problème des fins de ligne incompatibles devient plus probable. Ceci n'est pas pratique, ils (généralement) ne cassent pas le code, mais à cause d'eux, les validations et les requêtes de pool affichent diverses modifications non pertinentes. Souvent, les gens les ignorent simplement, car il est assez difficile de se promener et de changer toutes les mauvaises terminaisons de ligne.

Il existe une solution - vous pouvez demander à tous les membres de l'équipe de configurer leurs configurations locales pour l'achèvement automatique de la ligne:

# This will let you configure line-endings on an individual basis
git config core.eol lf
git config core.autocrlf input

Bien sûr, vous devez vous inscrire à cette convention et un débutant, ce qui est facile à oublier. Comment faire cela pour toute l'équipe? Conformément à l'algorithme d'opération, Git vérifie la présence d'un fichier de configuration dans le référentiel .git / config, puis vérifie la configuration à l'échelle du système de l'utilisateur dans ~/.gitconfig, puis vérifie la configuration globale dans /etc/gitconfig.

Tout cela est bien, mais il s'avère qu'aucun de ces fichiers de configuration ne peut être installé via le référentiel lui-même. Vous pouvez ajouter des configurations spécifiques au référentiel, mais elles ne s'étendent pas aux autres membres de l'équipe.

Cependant, un fichier est réellement validé dans le référentiel. Il s'appelle .gitattributes . Par défaut, vous ne l’avez pas, alors créez un nouveau fichier et enregistrez-le sous*.gitattributes*. Il définit des attributs pour chaque fichier. Par exemple, vous pouvez forcer git diff à utiliser les en-têtes exif des fichiers image au lieu d'essayer de calculer la différence dans les fichiers binaires. Dans ce cas, nous pouvons utiliser un caractère générique afin que le paramètre fonctionne pour tous les fichiers, agissant, en fait, comme un fichier de configuration commun pour la commande entière:

# Adding this to your .gitattributes file will make it so all files
# are checked in using UNIX line endings while letting anyone on the team
# edit files using their local operating system’s default line endings.
* text=auto

Masquage automatique


Il est habituel d'ajouter des fichiers compilés (tels que node_modules/) à .gitignore afin qu'ils soient stockés localement et non téléchargés dans le référentiel. Cependant, parfois, vous souhaitez toujours télécharger le fichier, mais vous ne voulez pas le rencontrer plus tard à chaque fois dans la demande de pool.

Dans cette situation (au moins sur GitHub), vous pouvez ajouter des chemins marqués à .gitattributes linguist-generatedet vous assurer que .gitattributes se trouve dans le dossier racine du référentiel. Cela masquera les fichiers dans la demande de pool. Ils seront «minimisés»: vous pouvez toujours voir le fait du changement, mais sans le code complet.

Tout ce qui réduit le stress et la charge cognitive dans le processus de révision du code améliore sa qualité et réduit le temps.

Par exemple, vous souhaitez ajouter des fichiers de ressources (actif) au référentiel, mais vous n'allez pas les modifier et les suivre plus tard, vous pouvez donc ajouter la ligne suivante au fichier avec des attributs:

*.asset linguist-generated

Utilisez le blâme plus souvent


L'article de Harry Roberts «Petites choses que j'aime faire avec Git» recommande git blame(attribuer la git praisetraduction ) d'attribuer un alias (traduire de la traduction «anglais») pour que cette équipe soit une action positive. Bien sûr, renommer ne change pas le comportement de l'équipe. Mais chaque fois que la discussion aborde l'utilisation d'une fonction git blame, tout le monde devient tendu, et bien sûr moi aussi. Il est naturel de percevoir le mot blâme (culpabilité) comme quelque chose de négatif ... mais c'est complètement faux!

Une fonction puissante git blame (ou git praise, si vous le souhaitez) montre qui a été le dernier à travailler avec ce code. Nous n'allons pas le blâmer ni le féliciter, mais nous voulons simplement clarifier la situation. Il devient plus clair quelles questions poser et à qui, ce qui fait gagner du temps.

Il doit être présenté git blamenon seulement comme quelque chose de bien, mais aussi comme un moyen de communication qui aide toute l'équipe à réduire le chaos et à ne pas perdre de temps à déterminer qui sait quoi. Certains IDE, tels que Visual Studio, activent cette fonctionnalité sous forme d'annotations. Pour chaque fonction, vous voyez instantanément qui l'a modifiée en dernier (et, par conséquent, avec qui en parler).

Git analogique blâme pour les fichiers manquants


Récemment, j'ai vu un développeur de notre équipe essayer de comprendre qui avait supprimé un fichier, quand et pourquoi. Il semble que cela puisse aider ici git blame, mais cela fonctionne avec les lignes du fichier et est inutile si le fichier est manquant.

Cependant, il existe une autre solution. Vieux fidèles git log. Si vous regardez le journal sans arguments, vous verrez une longue liste de toutes les modifications dans la branche actuelle. Vous pouvez ajouter un identifiant de validation pour voir le journal de cette validation particulière, mais si vous spécifiez --(que nous avons utilisé plus tôt pour cibler un fichier spécifique), vous pouvez obtenir un journal pour un fichier - même celui qui n'existe plus:

# By using -- for a specific file,
# git log can find logs for files that were deleted in past commits
git log -- missing_file.txt

Modèle de message de validation


Les messages de validation doivent souvent être améliorés. Tôt ou tard, les développeurs de l'équipe arrivent à cette conclusion. Il existe de nombreuses façons de s'améliorer. Par exemple, vous pouvez vous référer à des identifiants de bogues à partir d'un outil de gestion de projet interne, ou peut-être encourager à écrire au moins du texte au lieu d'un message vide.

Cette commande doit être exécutée manuellement chaque fois que quelqu'un clone le référentiel, car les fichiers de configuration ne sont pas validés dans le référentiel. Cependant, c'est pratique car vous pouvez créer un fichier commun avec n'importe quel nom qui agit comme un modèle de message de validation:

# This sets the commit template to the file given,
# this needs to be run for each contributor to the repository.
git config commit.template ./template-file

Git pour l'automatisation


Git est un puissant outil d'automatisation. Ce n'est pas immédiatement évident, mais pensez par vous-même: il voit toute votre activité dans le référentiel - ainsi que l'activité des autres participants - et il a beaucoup d'informations qui peuvent être très utiles.

Crochets Git


Très souvent, vous voyez que les membres de l'équipe effectuent des tâches répétitives tout en travaillant. Cela peut être un test de réussite des tests et du linter avant d'envoyer une branche au serveur (hook avant l'envoi) ou une stratégie forcée pour nommer les branches (hook avant de valider). À ce sujet, Konstantinos Lamonis a écrit un article dans le magazine Smashing intitulé «Comment simplifier le flux de travail en utilisant des crochets Git» .

Automatisation manuelle


L'une des principales fonctionnalités d'automatisation de Git est git bisect. Beaucoup en ont entendu parler, mais peu l'utilisent. L'essentiel est de traiter l'arbre Git (historique des validations) et de trouver où l'erreur est entrée.

La façon la plus simple de le faire est à la main. Vous commencez git bisect start, définissez les identifiants des bons et mauvais commits (là où il n'y a pas de bogue et où il y a un bogue), puis exécutez git bisect goodou git bisect badpour chaque validation.

Il s'agit d'une fonctionnalité plus puissante qu'il n'y paraît à première vue, car elle n'exécute pas le journal Git de manière linéaire, ce qui pourrait être fait manuellement en tant que processus itératif. Au lieu de cela, il utilise une recherche binaire qui passe efficacement par les validations avec le moins d'étapes:

# Begin the bisect
git bisect start

# Tell git which commit does not have the bug
git bisect good c5ba734

# Tell git which commit does have the bug
git bisect bad 6c093f4

# Here, do your test for the bug.
# This could be running a script, doing a journey on a website, unit test etc.

# If the current commit has bug:
git bisect bad

# If the current commit does not have the bug
git bisect good

# This will repeat until it finds the first commit with the bug
# To exit the bisect, either:

# Go back to original branch:
git bisect reset

# Or stick with current HEAD
git bisect reset HEAD

# Or you can exit the bisect at a specific commit
git bisect reset <commit ID>

En route: l'automatisation scientifique


Dans son rapport de débogage scientifique, Stuart Halloway a expliqué comment utiliser la commande git bisectpour automatiser le débogage.
Il se concentre sur Clojure, mais nous n'avons pas besoin de connaître cette langue pour bénéficier de son discours.

Git bisect est en partie une automatisation scientifique. Vous écrivez un petit programme qui testera quelque chose, et Git saute d'avant en arrière, coupant le monde en deux à chaque saut, jusqu'à ce qu'il trouve la frontière à laquelle votre test change d'état.
Stuart Halloway

Au début, cela git bisectpeut sembler être une fonctionnalité intéressante et plutôt cool, mais au final, ce n'est pas très utile. Les performances de Stewart montrent dans une large mesure qu'il est en fait contre-productif de déboguer comme nous en avons l'habitude. Si, au contraire, vous vous concentrez sur des faits empiriques, que le test réussisse ou non, vous pouvez l'exécuter sur toutes les validations, en commençant par la version de travail, et réduire le sentiment de «vagabonder dans le noir» auquel nous sommes habitués.

Alors, comment automatisons-nousgit bisect? Vous pouvez lui passer un script pour chaque commit correspondant. Plus tôt, j'ai dit que vous pouvez exécuter manuellement le script à chaque étape de la bissecte, mais si vous passez une commande à exécuter, il exécutera automatiquement le script à chaque étape. Il peut s'agir d'un script spécifiquement pour déboguer ce problème spécifique ou d'un test (modulaire, fonctionnel, intégration, tout type de test). Ainsi, vous pouvez écrire un test pour vérifier que la régression ne se répète pas et exécuter ce test sur les validations précédentes:

# Begin the bisect
git bisect start

# Tell git which commit does not have the bug
git bisect good c5ba734

# Tell git which commit does have the bug
git bisect bad 6c093f4

# Tell git to run a specific script on each commit
# For example you could run a specific script:
git bisect run ./test-bug

# Or use a test runner
git bisect run jest

À chaque commit passé


L'un des points forts git bisectest l'utilisation efficace de la recherche binaire pour contourner tous les événements de l'histoire de manière non linéaire. Mais parfois, un bypass linéaire est nécessaire. Vous pouvez écrire un script qui lit le journal Git et parcourt le code à chaque validation. Mais il est un ami, qui le fera pour vous: git rebase.

Kamran Ahmed dans un tweet écrit tel rebasequel, quel commit ne passe pas le test:

Trouvez un commit qui échoue au test:

$ git rebase -i --exec "yarn test" d294ae9

La commande exécute le test de fil sur toutes les validations entre d294ae9 et HEAD et s'arrête au commit où le test se bloque.

Nous avons déjà envisagé git bisectcette tâche, qui peut être plus efficace, mais dans ce cas, nous ne sommes pas limités à un cas d'utilisation.

Il y a une place pour la créativité. Vous souhaitez peut-être générer un rapport sur l'évolution du code au fil du temps (ou afficher l'historique des tests), et l'analyse du journal Git ne suffit pas. Ce n'est peut-être pas l'astuce la plus utile dans cet article, mais elle est intéressante et montre une tâche dont nous ne pouvions pas croire la réalité auparavant:

# This will run for every commit between current and the given commit ID
git rebase -i --exec ./my-script

Une sélection d'articles et de manuels pour vous aider à approfondir Git


Dans un tel article, il est impossible de se plonger dans le sujet, sinon tout le livre se révélera. J'ai choisi quelques petites astuces que même les utilisateurs expérimentés ne connaissent peut-être pas. Mais Git a bien plus de fonctionnalités: des fonctions de base aux scripts complexes, aux configurations précises et à l'intégration de la console. Par conséquent, voici quelques ressources qui pourraient vous intéresser:

  1. Explorer git . Un site interactif qui vous aide à comprendre facilement comment réaliser ce que vous voulez.
  2. Dang it git! . Chacun de nous à un moment donné peut se perdre dans Git et ne sait pas comment résoudre un problème. Ce site fournit des solutions à bon nombre des problèmes les plus courants.
  3. Pro git . Ce livre gratuit est une ressource inestimable pour comprendre Git.
  4. Git Docs. — . , Git Docs, Git (, man git-commit) Git .
  5. Thoughtbot. Git Thoughtbot .
  6. Git. Git.
  7. Git. , … . Git, .
  8. Git: du niveau débutant au niveau avancé . Mike Ritmüller a écrit cet article utile, idéal pour les utilisateurs novices de Git.
  9. Les petites choses que j'aime faire avec Git . C'est cet article de Harry Roberts qui m'a fait réaliser combien de possibilités se cachent encore dans Git, à part le déplacement de code entre les branches.
  10. Atlassian Advanced Git Guides . Ces didacticiels détaillent de nombreux sujets mentionnés dans cet article.
  11. Git cheat sheet sur Github . Il est toujours pratique d'avoir une bonne feuille de triche pour des outils comme Git.
  12. Réduction de Git . Cet article détaille divers indicateurs de commande Git et recommande de nombreux alias.

Mais que pouvez-vous lire d'autre :

  1. Git. №1: , .git
  2. Git. №2: rebase.
  3. .

All Articles