Git - Différence entre «assumer-inchangé» et «sauter-worktree»


450

J'ai des modifications locales sur un fichier que je ne veux pas valider dans mon référentiel. C'est un fichier de configuration pour construire 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 en scène. Je voudrais cacher ce changement particulier et ne pas le commettre. Je n'apporterai aucune autre modification au fichier.

Après quelques recherches, je vois 2 options: 'assumer-inchangé' et 'sauter-worktree'. Une question précédente ici en parle mais n'explique pas vraiment leurs différences. Ma question est la suivante: en quoi les deux commandes sont-elles différentes? Pourquoi quelqu'un utiliserait-il l'un ou l'autre?


1
Habituellement, j'utilise .gitignoreà des fins similaires. Cette solution fonctionnerait-elle pour vous?
samuil

45
samuil, .gitignore ignore l'ajout, pas le changement. Lorsque le fichier est déjà dans git, il sera suivi de l'événement s'il est répertorié dans .gitignore
Grigory

mais ne peut-on pas tout supprimer et tout ajouter pour "rafraîchir" comme expliqué ici? stackoverflow.com/questions/7075923/… @Grigory
Daniel Springer

2
Le fichier ne doit pas être ignoré si j'obtiens correctement l'intention de OP. Le fichier doit être dans le référentiel, mais ces modifications très spécifiques qu'il a apportées ne doivent pas être validées - pas maintenant, du moins.
Simone

Réponses:


666

Tu veux skip-worktree.

assume-unchangedest conçu pour les cas où il est coûteux de vérifier si un groupe de fichiers a été modifié; lorsque vous définissez le bit, git(bien sûr) suppose que les fichiers correspondant à cette partie de l'index n'ont pas été modifiés dans la copie de travail. Cela évite donc un fouillis d' statappels. 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-worktreeest plus que cela: même s'il git sait que le fichier a été modifié (ou doit être modifié par un reset --hardou similaire), il prétendra qu'il ne l'a pas été, en utilisant plutôt la version de l'index. Cela persiste jusqu'à ce que l'index soit supprimé.

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

De cet article:

  • --assume-unchangedsuppose qu'un développeur ne doit pas modifier un fichier. Cet indicateur est destiné à améliorer les performances des dossiers qui ne changent pas comme les SDK.
  • --skip-worktreeest utile lorsque vous demandez à git de ne jamais toucher à un fichier spécifique car les développeurs doivent le modifier. Par exemple, si le référentiel principal en amont héberge des fichiers de configuration prêts pour la production et que vous ne souhaitez pas accidentellement valider les modifications apportées à ces fichiers, --skip-worktreec'est exactement ce que vous voulez.

3
Ça a du sens. skip-worktree semble en effet être la voie à suivre. Merci!
ckb

100
Une petite note pour sauver quelques secondes de recherche et de lecture. Pour annuler les --skip-worktreeeffets et désactiver le drapeau, il existe une --no-skip-worktreeoption. Fonctionne exactement de la même manière. Ceci est utile dans le cas où une main a glissé et que des fichiers incorrects ont été signalés, ou si les circonstances ont changé et que les fichiers précédemment ignorés ne doivent plus être ignorés.
drdaeman du

18
Pour répondre à ma propre question ci-dessus, la différence entre l'utilisation --skip-worktreeet le .git/info/excludefichier est que le premier fonctionnera même pour les fichiers actuellement suivis. .git/info/exclude, comme .gitignore, empêchera uniquement l'ajout accidentel de fichiers non suivis à l'index, mais n'apportera pas de modifications aux fichiers déjà suivis.
LinusR

13
Peut-il être poussé vers la télécommande et être conservé par tous les clones?
CMCDragonkai

4
Juste l'usage , madame:git update-index --skip-worktree <file_name>
ruffin

108

Remarque: fallengamer a fait quelques tests en 2011 (ils peuvent donc être obsolètes), et voici ses conclusions :

Les opérations

  • Le fichier est modifié à la fois dans le référentiel local et en amont
    git pull:
    Git conserve de toute façon les modifications locales.
    Ainsi, vous ne perdriez pas accidentellement les données que vous avez marquées avec l'un des indicateurs.
    • Fichier avec assume-unchangedindicateur: Git n'écraserait pas le fichier local. Au lieu de cela, il produirait des conflits et des conseils sur la façon de les résoudre
    • Fichier avec skip-worktreeindicateur: Git n'écraserait pas le fichier local. Au lieu de cela, il produirait des conflits et des conseils sur la façon de les résoudre

  • Le fichier est modifié à la fois dans le référentiel local et en amont, essayant de toute façon d' utiliser les résultats en effectuant un travail manuel supplémentaire, mais au moins vous ne perdriez aucune donnée si vous aviez des modifications locales.
    git stash
    git pull
    skip-worktree
    • Fichier avec assume-unchangedindicateur: annule toutes les modifications locales sans possibilité de les restaurer. L'effet est comme ' git reset --hard'. ' git pull' l'appel réussira
    • Fichier avec skip-worktreeindicateur: Stash ne fonctionnerait pas sur les skip-worktreefichiers. ' git pull' échouera avec la même erreur que ci-dessus. Le développeur est obligé de réinitialiser manuellement l' skip-worktreeindicateur pour pouvoir cacher et terminer l'échec pull.

  • Aucune modification locale, fichier en amont modifié Les deux indicateurs ne vous empêcheraient pas d'obtenir des modifications en amont. Git détecte que vous avez rompu votre promesse et choisit de refléter la réalité en réinitialisant le drapeau.
    git pull
    assume-unchanged
    • Fichier avec assume-unchangedindicateur: le contenu est mis à jour, l'indicateur est perdu.
      ' git ls-files -v' montrerait que l'indicateur est modifié en H(de h).
    • Fichier avec skip-worktreeindicateur: le contenu est mis à jour, l'indicateur est conservé.
      ' git ls-files -v' afficherait le même Sdrapeau qu'avant le pull.

  • Avec le fichier local modifié, Git ne touche pas le fichier et reflète la réalité (le fichier promis d'être inchangé a été changé) pour le fichier.
    git reset --hard
    skip-worktreeassume-unchanged
    • Fichier avec assume-unchangedindicateur: le contenu du fichier est rétabli. Le drapeau est réinitialisé à H(de h).
    • Fichier avec skip-worktreeindicateur: le contenu du fichier est intact. Le drapeau reste le même.

Il ajoute l'analyse suivante:

  • Il ressemble skip-worktreeest d' essayer très difficile de conserver 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 réinitialise pas le drapeau pull.
    Mais ignorer la reset --hardcommande ' ' pourrait devenir une mauvaise surprise pour un développeur.

  • Assume-unchangedl'indicateur pourrait être perdu sur l' pullopération et les changements locaux à l'intérieur de ces fichiers ne semblent pas être importants pour git.

Voir:

Il conclut:

En fait, aucun des drapeaux n'est suffisamment intuitif .

  • assume-unchangedsuppose qu'un développeur ne doit pas modifier un fichier. Si un fichier a été modifié - alors ce changement n'est pas important. Cet indicateur est destiné à améliorer les performances des dossiers qui ne changent pas comme les SDK.
    Mais si la promesse est rompue et qu'un fichier est réellement modifié, git rétablit le drapeau pour refléter la réalité. Il est probablement correct d'avoir des indicateurs incohérents dans des dossiers généralement non destinés à être modifiés.

  • D'un autre côté, skip-worktreeest utile lorsque vous demandez à git de ne jamais toucher à un fichier spécifique. Cela est utile pour un fichier de configuration déjà suivi.
    Le référentiel principal en amont héberge une configuration prête pour la production, mais vous souhaitez modifier certains paramètres dans la configuration pour pouvoir effectuer des tests locaux. Et vous ne voulez pas vérifier accidentellement les modifications dans un tel fichier pour affecter la configuration de production. Dans ce cas, skip-worktreefait une scène parfaite.


Avec Git 2.25.1 (février 2020), le "En fait, aucun des drapeaux n'est suffisamment intuitif" mentionné ci-dessus est clarifié:

Voir commit 7a2dc95 , commit 1b13e90 (22 janvier 2020) par brian m. carlson ( bk2204) .
(Fusionné par Junio ​​C Hamano - gitster- dans commit 53a8329 , 30 janvier 2020)
( Git Mailing list )

doc: dissuader les utilisateurs d'essayer d'ignorer les fichiers suivis

Signature: Jeff King
Signature: brian m. Carlson

Il est assez courant que les utilisateurs souhaitent ignorer les modifications apportées à un fichier que Git suit.

Les scénarios courants pour ce cas sont les paramètres 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èle.

Cependant, les utilisateurs découvrent les bits supposés inchangés et ignorés et essaient de les utiliser de toute façon.

Cela est problématique, car lorsque ces bits sont définis, de nombreuses opérations se comportent comme le souhaite l'utilisateur, mais elles ne sont généralement pas utiles lorsque vous git checkoutdevez remplacer un fichier.

Il n'y a pas de comportement sensé dans ce cas, car parfois les données sont précieuses, comme certains fichiers de configuration, et parfois ce sont des 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 enclins à abuser des fonctionnalités existantes à des fins non intentionnelles, provoquant une tristesse et une confusion générales , documentons le comportement existant et les pièges dans la documentation pour git update-indexque les utilisateurs sachent qu'ils devraient explorer d'autres solutions.

De plus, fournissons une solution recommandée pour traiter le cas commun des fichiers de configuration, car il existe des approches bien connues utilisées avec succès dans de nombreux environnements.

La git update-indexpage de manuel comprend désormais:

Les utilisateurs essaient souvent d'utiliser les bits assume-unchangedet skip-worktreepour dire à Git d'ignorer les modifications apportées aux fichiers suivis. Cela ne fonctionne pas comme prévu, car Git peut toujours vérifier les fichiers de l'arborescence de travail par rapport à l'index lors de l'exécution de certaines opérations. En général, Git ne fournit pas un moyen d'ignorer les modifications apportées aux fichiers suivis, donc des solutions alternatives sont recommandées.

Par exemple, si le fichier que vous souhaitez 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 l'exemple de fichier comme un modèle, le modifiant et le copiant automatiquement.

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


7
Si vous avez skip-worktree sur un fichier et que les modifications en amont, vous obtenez "veuillez valider ou ranger" lorsque vous essayez de tirer, même si git status ne rapporte pas le fichier comme modifié. Comment pouvez-vous éviter cela, afin que les changements locaux puissent persister pendant que les gens fouillent avec les paramètres de production à l'origine?
GreenAsJade

3
Oui, je peux confirmer que oui. Cela signifie qu'il est encore très difficile d'avoir un fichier local que vous souhaitez simplement conserver différemment de l'origine.
GreenAsJade

1
@GreenAsJade semble ancien. Avez-vous des chances de le tester avec un 2.2.x?
VonC

1
@VonC, Le lien vers le "commentaire de Junio" n'est pas dans l'historique des révisions. Est - ce à cela que vous faisiez référence?
Michael - Où est Clay Shirky

1
@Michael Bonne prise, merci. J'ai remis ce lien dans la réponse.
VonC
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.