Supprimer un fichier binaire volumineux de votre historique Git pour gérer la taille des référentiels clonés

Azure DevOps Services | Azure DevOps Server | Azure DevOps Server 2022

Git est un référentiel de code source (référentiel) distribué populaire qui permet aux utilisateurs de travailler avec le dépôt complet dans un état déconnecté. Les avantages de Git sont bien documentés, mais que se passe-t-il si vous devez « restaurer l’horloge » sur le référentiel principal ? Cela n’est pas intuitif et nécessite des autorisations élevées. Cette exigence est attendue pour quelque chose qui affecte chaque utilisateur du dépôt.

Comment pouvez-vous restaurer le référentiel central en toute sécurité ?

Scénario de problème

Imaginez que vous validez un fichier volumineux, tel qu’une vidéo, sur votre serveur Git. Dans un système de code source traditionnel, il est pratique de stocker tout dans un seul endroit, puis d’extraire ce dont vous avez besoin. Avec Git, l’ensemble du dépôt est cloné sur l’ordinateur local de chaque utilisateur. Avec un fichier volumineux, chaque utilisateur unique du projet doit également télécharger les fichiers volumineux.

Avec chaque fichier volumineux ultérieur validé sur le serveur, le problème augmente uniquement. Le dépôt devient trop volumineux pour être efficace pour ses utilisateurs. Même si vous supprimez le fichier volumineux de votre dépôt local et recommitez, le fichier existe toujours dans l’historique du dépôt. Par conséquent, le fichier est toujours téléchargé sur l’ordinateur local de tout le monde dans le cadre de l’historique des téléchargements.

Capture d’écran montrant la boîte de dialogue Modifications de Team Explorer avec une vidéo volumineuse dans les modifications incluses.

Ajoutez un fichier volumineux au dépôt local.

Capture écran montrant les dépôts du serveur et ceux locaux, chacun avec une copie des fichiers vidéos de grande taille.

Une fois que vous avez effectué un commit à partir du dépôt local, le serveur détient également le fichier volumineux.

Figer le référentiel

Pour résoudre le problème d’un dépôt important, vous devez commencer depuis la source. Dans ce scénario, la source est le référentiel du serveur. Demandez à l’équipe d’arrêter de pousser au dépôt. Si d’autres envois (push) se produisent pendant ce processus, vous devez les prendre en compte afin que vous ne perdiez pas de données.

Importante

Les étapes suivantes suppriment la vidéo de l’historique de votre branche, mais le fichier reste dans l’historique de votre dépôt lorsque vous clonez votre dépôt à partir d’Azure Repos. La suppression des fichiers de l’historique de votre branche empêche la mise à jour des fichiers, qui a créé une autre version du fichier volumineux dans votre dépôt.

En savoir plus sur la gestion des fichiers volumineux dans Git. Pour obtenir une explication et une solution de contournement pour ce comportement lorsque vous utilisez des dépôts Git Azure Repos, consultez Pourquoi le clonage à partir de Visual Studio Team Services renvoie-t-il les anciens objets non référencés ?.

Rebaser et forcer l’envoi (push)

Si personne d’autre de l’équipe n’a apporté de modifications au dépôt, qui se produisent généralement par le biais d’une transmission push, vous pouvez prendre l’itinéraire facile. Vous faites essentiellement en sorte que votre dépôt local ressemble à ce que vous souhaitez (c’est-à-dire, sans le fichier volumineux). Vous forcez ensuite vos modifications sur le serveur.

Vous devrez peut-être cloner ou corriger votre dépôt local avant de commencer ce travail. Ce processus peut entraîner des pertes de travail ou des modifications, de sorte que continuer avec prudence.

Par défaut, vous pouvez modifier les fichiers projet locaux et envoyer des modifications au serveur, mais vous ne pouvez pas effectuer d’opérations au niveau du serveur, telles que la suppression ou le rebasage. Pour continuer, vous devez forcer l’envoi (préféré) ou disposer des autorisations d’administrateur sur le référentiel. Veuillez contacter votre administrateur de projet pour faire des demandes d'autorisation, ou demandez à quelqu'un qui les a déjà pour vous aider. Pour plus d’informations, consultez Configurer les autorisations du dépôt Git.

Capture d’écran montrant l’invite de commandes - git push --force permissions.

Ensuite, vous devez rebaser le dépôt.

  1. Utilisez git log pour rechercher les valeurs de hachage de l'algorithme SHA des commits récents. Vous avez besoin de ces informations dans un instant, car vous devez connaître la validation la plus récente. Vous pouvez obtenir ces informations en ouvrant une invite de commandes Git et en entrant :

    git log

    Vous pouvez également obtenir le hachage SHA à partir de l’affichage de l’historique des branches dans Visual Studio Team Explorer.

    Capture d’écran montrant l’option Afficher l'historique de la branche principale.

  2. Ouvrez un terminal de commande Git.

    Capture d’écran montrant l’action Ouvrir l’invite de commandes dans la boîte de dialogue Synchronisation.

  3. Recherchez le nombre de hachage SHA qui vous intéresse.

    Capture d’écran montrant l’invite de commandes pour la validation vidéo.

    Vous avez besoin du SHA qui démarre 25b4.

    N'oubliez pas que Git utilise des pointeurs pour déterminer où se trouvent la tête ou la branche actuelle dans le dépôt. L’état du dépôt qui vous intéresse se trouve à un certain moment dans le passé.

  4. Pour revenir en arrière et rendre l’état antérieur le nouvel état actuel, utilisez la git rebase commande :

    git rebase -i <SHA hash of desired new current branch>

    Capture d’écran montrant l’utilisation de la rebase pour supprimer le fichier vidéo.

    Le -i commutateur offre une sécurité supplémentaire, car il affiche l’historique dans un éditeur. (Cet article utilise une implémentation de Git qui affiche l’éditeur vi classique sur la ligne de commande dans Windows. Vous vous souvenez peut-être que si vous avez travaillé avec un système Unix.)

  5. Pour cet exemple, vous entrez :

    git rebase -i 25b4

  6. Une fois l’éditeur ouvert, supprimez toutes des pick lignes à l’exception de la branche que vous souhaitez conserver en tant que nouvelle tête. Lorsque tout semble correct, dans vi, entrez :w\<enter\> pour enregistrer ou entrez !q\<enter\> pour quitter sans enregistrer.

    Capture d’écran montrant l’invite de commandes - git rebase -i commande pick 25b4.

    Modifiez les lignes que vous ne souhaitez plus.

    Capture d’écran montrant l’invite de commandes - git rebase -i 25b4 drop.

  7. Changez pick en drop comme montré. Entrez :w ensuite (en vi) pour enregistrer, puis entrez :q! pour démarrer le rebase.

    Entrez git log à nouveau. La branche incriminée doit être absente du journal. Si c’est le cas, vous êtes prêt pour l’étape finale, ce qui nécessite des autorisations d’administrateur de projet :

    git log

    Capture d’écran montrant les dépôts locaux et du serveur après le rebase.

    La validation de la grande vidéo est maintenant passée du dépôt local.

  8. Entrez la commande suivante :

    git push --force

    Capture d’écran montrant l’invite de commandes - git push --force.

    Capture d’écran montrant l’invite de commandes : résultat de git push --force.

    Cette commande force votre dépôt à remplacer le dépôt sur le serveur.

    Utilisez cette commande avec précaution, car vous pouvez facilement perdre des données sur le serveur.

    Capture d’écran montrant un force push indiquant le contenu à conserver, sans le volumineux fichier vidéo.

Vous devez vous authentifier auprès du serveur pour que cette action fonctionne.

Si vous utilisez Azure Repos, vous devrez peut-être configurer une autre information d’identification qui n’utilise pas de caractères spéciaux. Un exemple est le symbole (@) dans une adresse e-mail. Pour effectuer cette tâche, suivez les instructions de l’authentification avec Azure Repos.

Maintenant, la branche est définitivement supprimée du serveur. Les clones et les synchronisations suivants par les membres de l’équipe de projet ne téléchargent pas les fichiers volumineux que vous essayez de supprimer. Les utilisateurs doivent extraire du serveur pour s’assurer qu’ils sont synchronisés avec le nouvel état du référentiel du serveur.

Si les utilisateurs ont des commits plus récents

Si d’autres utilisateurs ont envoyé des validations au dépôt de serveur, vous avez une autre considération. Vous souhaitez supprimer la branche qui contient les fichiers volumineux, mais vous ne souhaitez pas perdre les modifications apportées par l’équipe. Pour résoudre ce problème, lorsque vous ouvrez l’éditeur pour le rebasage, examinez attentivement les validations. Assurez-vous que les validations que vous souhaitez conserver sont répertoriées sur les pick lignes. Supprimez ceux que vous souhaitez supprimer, tels que l’emplacement où un fichier volumineux a été ajouté.

Après le rebastage, les autres utilisateurs de l’équipe doivent également rebaser afin que tout le monde ait une copie cohérente du référentiel de serveur. Ce travail est fastidieux pour tout le monde, et vous voulez l’éviter. Si vous avez besoin de supprimer un push, vous devez vous coordonner avec l’équipe. Pour plus d’informations sur le rebasing, consultez Git branching - Rebasing.

La clé consiste à vous assurer que vous connaissez les validations souhaitées et les validations que vous ne souhaitez pas. Étudiez git log ou l’historique dans votre environnement de développement intégré, par exemple Visual Studio. Notez méticuleusement les hachages SHA à conserver et les hachages à supprimer.

Dans les scénarios où le fichier volumineux est ancien et qu’il y a eu des branches et fusions ultérieures, vous pouvez peut-être supprimer le fichier à l’aide du git filter-branch commutateur. Pour plus d’informations, consultez Suppression des données sensibles d’un référentiel.

Considérations relatives aux bonnes pratiques

Assurez-vous que les fichiers volumineux restent hors du dépôt principal pour éviter un travail supplémentaire aux membres de l'équipe. Voici quelques bonnes pratiques courantes pour que l’équipe garde à l’esprit.

Tâches à effectuer

  • Valider fréquemment les modifications. Vous pouvez toujours les corriger ultérieurement avec une fusion ou une rebase.
  • Utilisez des branches pour isoler vos modifications. Les branches sont bon marché et privées, et la fusion est simple. Vous pouvez également sauvegarder les modifications sur une branche en le transmettant au serveur.
  • Utilisez une convention d’affectation de noms lorsque vous publiez des branches de rubrique. Nommez la branche users/<alias>/<branchname>. Ce nom permet de regrouper vos branches et facilite l’identification du propriétaire par d’autres personnes.
  • N'oubliez pas de pousser vos modifications. Utiliser Commit != Checkin et (Commit + Push) == Checkin.
  • Envisagez d’utiliser .gitignore pour les fichiers binaires volumineux afin qu’ils ne soient pas ajoutés au dépôt. Pour plus d’informations, consultez Ignorer les fichiers.
  • Envisagez d’utiliser le contrôle de version NuGet ou Team Foundation Server pour stocker vos fichiers binaires volumineux.

Choses à éviter

  • Ne rebasez pas après l’envoi ( push). Le rebasage des commits poussés dans Git peut être problématique, car il force tout le monde dans le dépôt à rebaser leurs propres modifications locales. Les membres de l’équipe peuvent ne pas être heureux s’ils doivent effectuer cette tâche. Rebaser les validations poussées sur votre branche personnelle, même si elles sont poussées, n'est pas un problème à moins que d'autres personnes ne tirent ces validations.
  • Ne validez pas les fichiers binaires dans votre référentiel. Git ne compresse pas les fichiers binaires de la façon dont Team Foundation Version Control le fait. Étant donné que tous les dépôts ont l’historique entier, la validation de fichiers binaires signifie un ballonnement permanent.

Résumé

Parfois, les éléments indésirables, tels que les fichiers volumineux, sont ajoutés à un dépôt et doivent être supprimés pour conserver le dépôt propre et léger. Vous pouvez effectuer cette tâche en mettant de l'ordre dans votre dépôt local. Utilisez la git rebase commande, puis utilisez la git push --force commande pour remplacer le référentiel du serveur avec votre dépôt local.