535 votes

Git - Différence entre "assume-unchanged" et "skip-worktree".

J'ai des modifications locales à un fichier que je ne veux pas livrer à mon dépôt. Il s'agit d'un fichier de configuration pour la construction de l'application sur un serveur, mais je veux construire localement avec des paramètres différents. Naturellement, le fichier apparaît toujours lorsque je fais 'git status' comme quelque chose à mettre à disposition. Je voudrais cacher cette modification particulière et ne pas la commiter. Je n'apporterai pas d'autres modifications au fichier.

Après quelques recherches, je vois 2 options : 'assume-unchanged' et 'skip-worktree'. Une question précédente aquí parle d'eux mais n'explique pas vraiment leurs différences. Ma question est la suivante : en quoi les deux commandes sont-elles différentes ? Pourquoi utiliser l'une ou l'autre ?

3 votes

Habituellement, j'utilise .gitignore à des fins similaires. Cette solution vous conviendrait-elle ?

56 votes

Samuil, .gitignore ignore les ajouts, pas les modifications. Lorsque le fichier est déjà dans git, il sera suivi si il est listé dans .gitignore.

0 votes

Mais ne peut-on pas tout supprimer et tout ajouter afin de "rafraîchir" comme expliqué ici ? stackoverflow.com/questions/7075923/ @Grigory

774voto

Borealid Points 35075

Vous voulez skip-worktree .

assume-unchanged est conçu pour les cas où il est coûteux de vérifier si un groupe de fichiers a été modifié ; lorsque vous mettez le bit, git (bien sûr) suppose que les fichiers correspondant à cette portion de l'index n'ont pas été modifiés dans la copie de travail. Cela permet donc d'éviter un fouillis de stat appels. Ce bit est perdu chaque fois que l'entrée du fichier dans l'index change (donc, lorsque le fichier est modifié en amont).

skip-worktree est plus que cela : même lorsque git connaît que le fichier a été modifié (ou doit être modifié par une reset --hard ou autre), il fera comme si ce n'était pas le cas et utilisera la version de l'index à la place. Ceci persiste jusqu'à ce que l'index soit supprimé.

Vous trouverez ici un bon résumé des ramifications de cette différence et des cas d'utilisation typiques : http://fallengamer.livejournal.com/93321.html .

De cet article :

  • --assume-unchanged suppose qu'un développeur ne devrait pas modifier un fichier. Ce drapeau est destiné à amélioration des performances pour les dossiers qui ne changent pas, comme les SDK.
  • --skip-worktree est utile lorsque vous demandez à git de ne jamais toucher à un fichier spécifique parce que les développeurs debe le changer. Par exemple, si le dépôt principal en amont héberge des fichiers prêts à être mis en production les fichiers de configuration et vous ne voulez pas accidentellement apporter des modifications à ces fichiers, --skip-worktree est exactement ce que vous voulez.

4 votes

C'est tout à fait logique. L'option " skip-worktree " semble en effet être la meilleure solution. Merci.

4 votes

Vous trouverez plus d'informations sur ces deux commandes dans le manuel de l'utilisateur. Page de manuel de git-update-index(1) .

125 votes

Une petite note pour gagner quelques secondes de recherche et de lecture. Pour annuler --skip-worktree et désactive le drapeau il y a --no-skip-worktree option. Cela fonctionne exactement de la même manière. Ceci est utile dans le cas où une main a glissé et que de mauvais fichiers ont été marqués, ou si les circonstances ont changé et que les fichiers précédemment ignorés ne doivent plus être ignorés.

126voto

VonC Points 414372

Note : fallengamer a effectué des tests en 2011 (ils peuvent donc être périmés), et voici ses conclusions :

Opérations

  • Le fichier est modifié à la fois dans le dépôt local et dans le dépôt amont.
    git pull :
    Git conserve les modifications locales de toute façon.
    Ainsi, vous ne perdrez pas accidentellement les données que vous avez marquées avec l'un des drapeaux.

    • Dossier avec assume-unchanged drapeau : Git n'écraserait pas le fichier local. Au lieu de cela, il affichera les conflits et conseillera sur la manière de les résoudre.
    • Dossier avec skip-worktree flag : Git n'écraserait pas le fichier local. Au lieu de cela, il affichera les conflits et conseillera sur la manière de les résoudre.
  • Le fichier a été modifié à la fois dans le dépôt local et dans le dépôt amont, mais j'essaie de le tirer quand même.
    git stash
    git pull
    Utilisation de skip-worktree entraîne un travail manuel supplémentaire, mais au moins vous ne perdrez pas de données en cas de modifications locales.

    • Dossier avec assume-unchanged drapeau : Supprime toutes les modifications locales sans possibilité de les restaurer. L'effet est comme ' git reset --hard '. ' git pull L'appel ' réussira
    • Dossier avec skip-worktree drapeau : Stash ne fonctionne pas sur skip-worktree fichiers. ' git pull ' échouera avec la même erreur que ci-dessus. Le développeur est obligé de réinitialiser manuellement skip-worktree drapeau pour pouvoir planquer et compléter l'échec pull .
  • Pas de changement local, le fichier amont a été modifié
    git pull
    Les deux drapeaux ne vous empêcheront pas d'obtenir les changements en amont. Git détecte que vous avez cassé assume-unchanged et choisit de refléter la réalité en réinitialisant le drapeau.

    • Dossier avec assume-unchanged drapeau : Le contenu est mis à jour, le drapeau est perdu.
      ' git ls-files -v ' montrerait que le drapeau est modifié en H (de h ).
    • Dossier avec skip-worktree drapeau : Le contenu est mis à jour, le drapeau est préservé.
      ' git ls-files -v montrerait le même S comme avant le pull .
  • Avec le fichier local modifié
    git reset --hard
    Git ne touche pas skip-worktree et reflète la réalité (le fichier promis comme étant inchangé a en fait été modifié) pour assume-unchanged fichier.

    • Dossier avec assume-unchanged drapeau : Le contenu du fichier est inversé. Le drapeau est réinitialisé à H (de h ).
    • Dossier avec skip-worktree drapeau : F [ ]

Il ajoute l'analyse suivante :

  • On dirait que skip-worktree est s'efforcer de préserver vos données locales . Mais cela ne vous empêche pas d'obtenir des modifications en amont si cela est sûr. De plus, git ne remet pas à zéro le drapeau sur pull .
    Mais ignorer le reset --hard Cette commande pourrait devenir une mauvaise surprise pour un développeur.

  • Assume-unchanged pourrait être perdu sur le pull et les changements locaux à l'intérieur de tels fichiers ne semblent pas être importants pour git.

Voir :

Il conclut :

En fait, aucun des deux drapeaux n'est assez intuitif .

  • assume-unchanged part du principe qu'un développeur ne doit pas modifier un fichier. Si un fichier a été modifié - alors ce changement n'est pas important. Ce drapeau est destiné à améliorer les performances pour les dossiers qui ne changent pas, comme les SDK.
    Mais si la promesse n'est pas tenue et qu'un fichier est effectivement modifié, git renverse le drapeau pour refléter la réalité. Il est probablement acceptable d'avoir des indicateurs incohérents dans les dossiers qui ne doivent pas être modifiés.

  • D'autre part skip-worktree est utile lorsque vous demandez à git de ne jamais toucher à un fichier spécifique. C'est utile pour un fichier de configuration déjà suivi.
    Le dépôt principal d'Upstream héberge une configuration prête pour la production, mais vous souhaitez modifier certains paramètres de la configuration pour pouvoir effectuer des tests locaux. Et vous ne voulez pas que les changements dans ce fichier affectent accidentellement la configuration de production. Dans ce cas skip-worktree fait une scène parfaite.


Avec Git 2.25.1 (fév. 2020), la question "En fait, aucun des deux drapeaux n'est assez intuitif" mentionnée ci-dessus est clarifiée :

Voir commettre 7a2dc95 , commettre 1b13e90 (22 janvier 2020) par brian m. carlson ( bk2204 ) .
(fusionné par Junio C Hamano -- gitster -- en commettre 53a8329 , 30 janvier 2020)
( Liste de diffusion Git )

doc : dissuader les utilisateurs d'essayer d'ignorer les fichiers tracés

Signé par : Jeff King
Signé par : brian m. carlson

Il est assez courant pour les utilisateurs de vouloir ignorer les modifications d'un fichier que Git suit.

Les scénarios courants pour ce cas sont les paramètres de l'IDE et les fichiers de configuration, qui ne devraient généralement pas être suivis et éventuellement générés à partir de fichiers suivis à l'aide d'un mécanisme de modélisation.

Cependant, les utilisateurs apprennent l'existence des bits assume-unchanged et skip-worktree et essaient de les utiliser pour le faire quand même.

Cela pose un problème, car lorsque ces bits sont activés, de nombreuses opérations se comportent comme l'utilisateur s'y attend, mais ils n'aident généralement pas quand git checkout doit remplacer un fichier.

Il n'y a pas de comportement raisonnable dans ce cas, car parfois les données sont précieuses, comme certains fichiers de configuration, et parfois il s'agit de données non pertinentes que l'utilisateur serait heureux de jeter.

Étant donné qu'il ne s'agit pas d'une configuration prise en charge et que les utilisateurs sont susceptibles d'utiliser les fonctionnalités existantes à des fins non souhaitées, ce qui entraîne une tristesse et une confusion générales. Dans le cas de la version 1.0, documentons le comportement existant et les pièges dans la documentation de la version 1.0. git update-index afin que les utilisateurs sachent qu'ils doivent explorer d'autres solutions.

En outre, nous proposons une solution recommandée pour traiter le cas courant des fichiers de configuration, car il existe des approches bien connues utilisées avec succès dans de nombreux environnements.

El git update-index page de manuel comprend maintenant :

Les utilisateurs essaient souvent d'utiliser le assume-unchanged y skip-worktree pour indiquer à Git d'ignorer les modifications apportées aux fichiers qui font l'objet d'un suivi. Cela ne fonctionne pas comme prévu, puisque Git peut toujours vérifier les fichiers de l'arbre de travail par rapport à l'index lors de certaines opérations. En général, Git ne fournit pas de moyen d'ignorer les modifications apportées aux fichiers suivis, aussi d'autres solutions sont recommandées.

Par exemple, si le fichier que vous voulez modifier est une sorte de fichier de configuration, le référentiel peut inclure un exemple de fichier de configuration qui peut ensuite être copié dans le nom ignoré et modifié. Le référentiel peut même inclure un script pour traiter le fichier d'exemple comme un modèle, le modifiant et le copiant automatiquement.

Cette dernière partie est ce que je décris comme un typique pilote de filtre de contenu basé sur les scripts smudge/clean .

8 votes

Si vous avez skip-worktree sur un fichier et que l'amont change, vous obtenez "please commit or stash" lorsque vous essayez de tirer, même si git status ne signale pas le fichier comme modifié. Comment éviter cela, afin que les changements locaux puissent persister pendant que les gens s'amusent avec les paramètres de production sur l'origine ?

0 votes

@GreenAsJade pas sûr : ce serait une bonne question à part entière (avec un lien vers celle-ci). Je suppose que vous obtiendriez un message similaire avec assume-unchanged au lieu de skip-worktree .

3 votes

Oui, je peux le confirmer. Cela signifie qu'il est toujours très difficile d'avoir un fichier local que l'on souhaite simplement gérer différemment de l'origine.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X