Modifications non programmées laissées après la réinitialisation de git --hard

275

Après git reset --hard, git statusme donne des fichiers dans la Changes not staged for commit:section.

J'ai également essayé git reset ., git checkout -- .et git checkout-index -f -aen vain.

Alors, comment puis-je me débarrasser de ces changements non programmés?

Cela semble toucher uniquement les fichiers de projet Visual Studio. Bizarre. Voir cette pâte: http://pastebin.com/eFZwPn9Z . Ce qui est spécial avec ces fichiers, c'est qu'en .gitattributes j'ai:

*.sln        eol=crlf
*.vcproj     eol=crlf
*.vcxproj*   eol=crlf

En outre, autocrlfest défini sur false dans mon global .gitconfig. Cela pourrait-il être pertinent d'une manière ou d'une autre?

Norswap
la source
Avez-vous appliqué ces commandes à partir de la racine du référentiel? L'avis .représente le répertoire actuel et non le répertoire racine
Alexander
1
Je les ai fait depuis le dépôt racine en effet.
Norswap
Quelle est ta gitversion? Soit vous faites une erreur idiote, soit vous avez une ancienne version qui est buggée?
Shahbaz
C'est git 1.7.4 msysgit. C'est peut-être une erreur, mais les commandes semblent assez simples et je n'ai pas repéré d'erreur.
Norswap
Pour mémoire, j'ai essayé d'utiliser la dernière version de msysgit (1.7.11), mais le problème persiste.
Norswap

Réponses:

361

J'ai eu le même problème et il était lié au .gitattributesfichier. Toutefois, le type de fichier à l'origine du problème n'a pas été spécifié dans le .gitattributes.

J'ai pu résoudre le problème en exécutant simplement

git rm .gitattributes
git add -A
git reset --hard
GameScripting
la source
7
Il s'agit de la directive * text = auto dans le fichier gitattributes. Il modifie automatiquement la fin des fichiers, de sorte que les fichiers seront automatiquement marqués comme "modifiés" lorsque vous vérifierez l'état.
Cody Django
3
Cela fonctionne, mais je ne comprends pas exactement pourquoi. Quelqu'un veut-il expliquer chaque commande?
Edwin Stoteler du
18
@NLwino, git rm .gitattributessupprime .gitattributes de l'index. git add -Aajoute tout (y compris la suppression de .gitattributes) à l'index, qui ne devrait alors être que la suppression de .gitattributes, si tel était vraiment le problème. git reset --hardréinitialise toutes les modifications non validées, ce qui inclut la suppression de .gitattributes. Essentiellement, cela ignore .gitattributes (et la * text=autodirective) pour un commit en le supprimant, puis en réinitialisant l'index pendant qu'il est supprimé, donc en le remettant, mais après avoir déjà réinitialisé les autres fichiers, ils n'ont donc pas été modifiés à nouveau.
cloudworks
4
@GameScripting, Cette solution ne fonctionne pas pour moi. Il n'existe pas de fichier tel que .gitattributes: "fatal: pathspec '.gitattributes' ne correspond à aucun fichier"
Pacerier
4
Je fais ça et ça dit fatal: pathspec '.gitattributes' did not match any files . Qu'est-ce que je fais mal?
Honey
136

RÉSOLU!!!

J'ai résolu ce problème en suivant les étapes suivantes

1) Supprimez tous les fichiers de l'index de Git.

git rm --cached -r .

2) Réécrivez l'index Git pour récupérer toutes les nouvelles fins de ligne.

git reset --hard

La solution faisait partie des étapes décrites sur le site git https://help.github.com/articles/dealing-with-line-endings/

Jacek Szybisz
la source
5
Cela fonctionne quand rien d'autre ne fait! Nous avons tout essayé dans ce sujet et dans de nombreux autres - c'est une grande équipe de développement, donc mettre tout le monde sur le même crlf a été un cauchemar, mais cela résout le problème.
tkersh
Intéressant ... J'ai utilisé "git rm --chached <one_specific_file>, au lieu de tout supprimer." Git status "a signalé que le fichier était supprimé et non suivi. Ensuite," git reset --hard "corrige ce fichier et tous les autres fichiers qui étaient signalés comme des "changements non échelonnés". (Avant d'utiliser git rm, j'ai essayé de réinitialiser dur sans effet.) J'adore ces systèmes de contrôle de source mystérieux.
joeking
Vous savez, il supprime tout votre cache. Dans les grands projets, cela peut perdre beaucoup de temps.
Ohar
C'est brutal. Vous auriez pu faire la même chose en supprimant le répertoire repo et en re-clonant.
ingyhere
4
Considérez que vous êtes sous Windows et qu'il est insensible à la casse. Si vous travaillez également avec des développeurs qui utilisent des systèmes de fichiers sensibles à la casse, tels que Mac ou Linux, ils peuvent commettre des balises, des branches ou même des fichiers dans différents cas. Dans cette situation, votre index affichera les fichiers existants qui sont remplacés par le système d'exploitation lors de son extraction. La seule façon de résoudre ce problème serait d'instaurer une politique de dénomination sur votre serveur Git (hooks) ou de détecter les erreurs à l'avance.
ingyhere
97

Git ne réinitialisera pas les fichiers qui ne sont pas sur le référentiel. Afin que vous puissiez:

$ git add .
$ git reset --hard

Cela mettra en scène toutes les modifications, ce qui amènera Git à être au courant de ces fichiers, puis à les réinitialiser.

Si cela ne fonctionne pas, vous pouvez essayer de cacher et de supprimer vos modifications:

$ git stash
$ git stash drop
YuriAlbuquerque
la source
4
Les fichiers étaient déjà suivis. J'ai quand même essayé et ça ne marche pas non plus. Il doit y avoir quelque chose de vraiment mauvais avec mon repo, mais je n'ai aucune idée de quoi. Pour le truc git stash, voir ma réponse à Shahbaz.
Norswap
Que se passe-t-il lorsque vous faites un statut git?
YuriAlbuquerque
1
J'ai pensé à une solution. Faites un commit et un rebase interactif pour effacer ce commit.
YuriAlbuquerque
J'ai essayé cela à un moment donné, et cela a fonctionné, difficile, j'ai par la suite donné un autre essai et j'ai trouvé le résultat surprenant décrit dans l'édition de ma réponse.
Norswap
@YuriAlbuquerque, Git ne comprend pas très bien POLA . Le but n'est-il pas de git reset --hard" réinitialiser à la fois la zone de transit et le répertoire de travail "? Si un fichier n'est pas mis en scène, nous souhaitons évidemment le supprimer lorsque nous le faisons reset --hard.
Pacerier
71

Si vous utilisez Git pour Windows, c'est probablement votre problème

J'ai eu le même problème et la sauvegarde, la réinitialisation matérielle, le nettoyage ou même tous laissaient des changements. Ce qui s'est avéré être le problème était le mode de fichier x qui n'était pas correctement défini par git. Il s'agit d'un "problème connu" avec git pour Windows. Les modifications locales s'affichent dans gitk et git comme l'ancien mode 100755, le nouveau mode 100644, sans aucune différence de fichier réelle.

Le correctif consiste à ignorer le mode fichier:

git config core.filemode false

Plus d'infos ici

vezenkov
la source
2
Cela a fonctionné quand même quand il rm -rf *; git checkout HEAD .ne l'a pas fait. Phew!
forumulator
A fonctionné pour moi, alors que l'attribution de la sauvegarde / réinitialisation matérielle / rm a échoué.
kakyo
Cela a également fonctionné pour moi lorsque j'ai eu des problèmes avec git repo sous Linux qui était hébergé sur un Mac
prmph
a fonctionné pour moi - a essayé tout le reste et oui l'ancien mode vs le nouveau mode était le problème (j'ai remarqué que j'avais un numéro différent mais les fichiers sont les mêmes)
Taehoon A Kim
Gain de vie et de temps.
Yogesh Patil
31

D'accord, j'ai en quelque sorte résolu le problème.

Il semble que le .gitattributesdossier, contenant:

*.sln        eol=crlf
*.vcproj     eol=crlf
*.vcxproj*   eol=crlf

fait apparaître les fichiers de projet sans mise en scène. Je ne sais pas pourquoi, et j'espère vraiment que quelqu'un connaissant les manières de git nous donnera une belle explication.

Ma solution consistait à supprimer ces fichiers et à les ajouter autocrlf = falsesous [core]dans.git/config .

Cela ne revient pas exactement à la même chose que la configuration précédente, car cela nécessite que chaque développeur ait autocrlf = false . J'aimerais trouver une meilleure solution.

ÉDITER:

J'ai commenté les lignes incriminantes, je ne les ai pas commentées et cela a fonctionné. Qu'est-ce que ... je n'ai même pas ...!

Norswap
la source
1
J'ai juste eu ce même problème exact et c'était la seule solution qui a fonctionné. Dans mon cas, je suis passé d'une branche de fonctionnalité à mon maître et j'ai retiré de nouveaux changements en amont et cela a juste commencé à se produire pour 2 fichiers qui ont été modifiés. Il semble que les fichiers aient été passés d'Unix à des fins de ligne Windows, ce qui peut avoir quelque chose à voir avec cela. Je ne sais pas comment ni pourquoi.
Steven Surowiec
+1 Même problème sur Windows Git. Déjà eu autocrlf = false. J'ai fusionné dans les changements du repo svn en amont ( git svn fetch/ git merge git-svn) et j'ai été laissé avec 1 fichier marqué comme modifié. Ce qui est étrange, c'est que j'ai déjà rencontré ce problème et tout ce que je devais faire était de vérifier une autre branche (avec le -fdrapeau), puis de revenir en arrière. Je l'ai fait, et cela a fonctionné, mais quand je suis passé à une branche de fonctionnalité, le "changement" était de retour! Votre modification au bas de la réponse était la solution. Dans mon cas, j'ai commenté / décommenté une ligne en haut de mon fichier .gitattributes:* text=auto !eol
Aaron Blenkush
1
Cette modification a également fonctionné pour moi: commentez les lignes .gitattributes, exécutez git status, décommentez les lignes .gitattributes, exécutez à git statusnouveau
Ignitor
En effet, git réinitialise ces fichiers, puis applique à nouveau les fins de ligne spécifiées dans le .gitattributes. Le git diffmontre probablement le célèbre mur de rouge / mur de vert qui est typique des différences de fin de ligne.
Dagrooms
22

Cause possible n ° 1 - Normalisation de fin de ligne

Une situation dans laquelle cela peut se produire est lorsque le fichier en question a été archivé dans le référentiel sans la configuration correcte pour les fins de ligne (1) résultant en un fichier dans le référentiel avec soit des fins de ligne incorrectes, soit des fins de ligne mixtes. Pour confirmer, vérifiez que git diffne montre que les changements dans les fins de ligne (ceux-ci peuvent ne pas être visibles par défaut, essayez git diff | cat -vde voir les retours chariot comme littéraux^M caractères ).

Par la suite, quelqu'un a probablement ajouté .gitattributesou modifié lecore.autocrlf paramètre pour normaliser les fins de ligne (2). Sur la base de la .gitattributesconfiguration globale ou, Git a appliqué des modifications locales à votre copie de travail qui appliquent la normalisation de fin de ligne demandée. Malheureusement, pour une raison quelconquegit reset --hard ces modifications de normalisation de ligne ne sont pas annulées.

Solution

Les solutions de contournement dans lesquelles les terminaisons de ligne locales sont réinitialisées ne résoudront pas le problème. Chaque fois que le fichier est "vu" par git, il essaiera de réappliquer la normalisation, entraînant le même problème.

La meilleure option est de laisser git appliquer la normalisation qu'il souhaite en normalisant toutes les fins de ligne dans le repo pour correspondre à .gitattributes, et en validant ces changements - voir Essayer de réparer les fins de ligne avec git filter-branch, mais sans chance .

Si vous voulez vraiment essayer d'annuler les modifications du fichier manuellement, la solution la plus simple semble être d'effacer les fichiers modifiés, puis de dire à git de les restaurer, bien que je note que cette solution ne semble pas fonctionner de manière cohérente à 100%. l'heure ( AVERTISSEMENT: NE l' exécutez PAS si vos fichiers modifiés ont des changements autres que des fins de ligne !!):

    git status --porcelain | grep "^ M" | cut -c4- | xargs rm
    git checkout -- .

Notez que, à moins que vous ne normalisiez les fins de ligne dans le référentiel à un moment donné, vous continuerez à rencontrer ce problème.

Cause possible n ° 2 - Insensibilité à la casse

La deuxième cause possible est l'insensibilité à la casse sous Windows ou Mac OS / X. Par exemple, supposons qu'un chemin comme celui-ci existe dans le référentiel:

/foo/bar

Maintenant, quelqu'un sur Linux valide les fichiers /foo/Bar(probablement à cause d'un outil de construction ou de quelque chose qui a créé ce répertoire) et pousse. Sous Linux, il s'agit en fait maintenant de deux répertoires distincts:

/foo/bar/fileA
/foo/Bar/fileA

La vérification de ce dépôt sur Windows ou Mac peut entraîner une modification fileAqui ne peut pas être réinitialisée, car à chaque réinitialisation, git sur Windows extrait /foo/bar/fileA, puis parce que Windows ne respecte pas la casse, écrase le contenu de fileAavec /foo/Bar/fileA, ce qui entraîne leur "modification".

Un autre cas peut être un ou des fichiers individuels qui existent dans le référentiel et qui, lorsqu'ils sont extraits sur un système de fichiers insensible à la casse, se chevauchent. Par exemple:

/foo/bar/fileA
/foo/bar/filea

Il peut y avoir d'autres situations similaires qui pourraient causer de tels problèmes.

git sur les systèmes de fichiers insensibles à la casse devrait vraiment détecter cette situation et afficher un message d'avertissement utile, mais ce n'est pas le cas actuellement (cela pourrait changer à l'avenir - voir cette discussion et les correctifs proposés sur la liste de diffusion git.git).

Solution

La solution consiste à aligner la casse des fichiers dans l'index git et la casse sur le système de fichiers Windows. Cela peut être fait sous Linux qui montrera le vrai état des choses, OU sous Windows avec l'utilitaire open source très utile Git-Unite . Git-Unite appliquera les modifications de cas nécessaires à l'index git, qui pourra ensuite être validé dans le dépôt.

(1) Cela était probablement dû à une personne utilisant Windows, sans aucune .gitattributesdéfinition du fichier en question, et utilisant le paramètre global par défaut core.autocrlfqui est false(voir (2)).

(2) http://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/

Raman
la source
Putain de fils, a pris tout le chemin vers celui-ci. J'ai dû m'engager après la première ligne, mais j'ai finalement pu passer ma commande. Ce n'était pas amusant.
Tim Lieberman
16

Si les autres réponses ne fonctionnent pas, essayez d'ajouter les fichiers, puis réinitialisez

$ git add -A
$ git reset --hard

Dans mon cas, cela a aidé quand il y avait un tas de fichiers vides que git suivait.

joshuakcockrell
la source
Cela marche. Je viens d'utiliser à la $ git add .place de$ git add -A
Bjarne Gerhardt-Pedersen
8

Une autre cause à cela pourrait être les systèmes de fichiers insensibles à la casse . Si vous avez plusieurs dossiers dans votre référentiel au même niveau dont les noms ne diffèrent que par cas, vous serez frappé par cela. Parcourez le référentiel source à l'aide de son interface Web (par exemple GitHub ou VSTS) pour vous en assurer.

Pour plus d'informations: https://stackoverflow.com/a/2016426/67824

Ohad Schneider
la source
Pour trouver les noms de ces fichiers, exécutezgit ls-tree -r --name-only HEAD | tr A-Z a-z | sort | uniq -d
Diomidis Spinellis
5

Vous pouvez stashsupprimer vos modifications, puis laisser tomber la cachette:

git stash
git stash drop
Shahbaz
la source
1
Vous pouvez également être intéressé par ce .
Shahbaz
5

Aucune de ces méthodes n'a fonctionné pour moi, la seule solution était de neutraliser l'ensemble du référentiel et de le recloner. Cela inclut le stockage, la réinitialisation, l'ajout puis la réinitialisation, les paramètres clrf, la sensibilité à la casse, etc. Soupir.

John Hunt
la source
Mise à jour, il s'est avéré que mon système de fichiers monté sensible à la casse n'était pas réellement sensible à la casse. Après avoir corrigé ce problème, il était possible de le résoudre en utilisant les techniques mentionnées ci-dessus.
John Hunt
4

Exécuter la commande de nettoyage :

# Remove all untracked files and directories. (`-f` is `force`, `-d` is `remove directories`)

git clean -fd
mrks
la source
3
Malheureusement, cela ne résout pas les problèmes liés aux fins de ligne.
Christopher Schneider
C'est la seule chose qui résout mon problème, quel que soit mon problème. Je n'avais aucun .gitattributesfichier et les fins de ligne n'étaient pas un problème car je suis sur une boîte Linux et tous les développeurs et notre serveur sont Linux.
Samuel Neff
4

Vérifiez votre .gitattributes.

Dans mon cas, je l'ai *.js text eol=lfet l'option git core.autocrlfétait true.

Cela m'amène à la situation où git convertit automatiquement les fins de ligne de mes fichiers et m'empêche de le réparer et git reset --hard HEADn'a même rien fait.

Je le corrige en commentant *.js text eol=lfdans mon .gitattributeset je le commente après.

On dirait que c'est juste de la magie.

Ohar
la source
C'était tout pour moi, la mise à niveau de mon projet présenté *.bat text eol=crlfà mon projet.
Leo
1

J'ai rencontré un problème similaire impliquant également .gitattributes, mais pour mon cas, il s'agissait du LFS de GitHub. Bien que ce ne soit pas exactement le scénario de l'OP, je pense qu'il fournit une occasion d'illustrer ce que fait le .gitattributesfichier et pourquoi il peut conduire à des changements non organisés sous la forme de différences "fantômes".

Dans mon cas, un fichier était déjà dans mon référentiel, comme depuis le début des temps. Dans un commit récent, j'ai ajouté une nouvelle git-lfs trackrègle en utilisant un modèle qui était rétrospectivement un peu trop large, et finissant par correspondre à cet ancien fichier. Je sais que je ne voulais pas changer ce fichier; Je sais que je n'ai pas modifié le fichier, mais maintenant il était dans mes modifications non programmées et aucune quantité de retraits ou de réinitialisations matérielles sur ce fichier n'allait le réparer. Pourquoi?

L'extension GitHub LFS fonctionne principalement en tirant parti des crochets qui gitpermettent d'accéder via le .gitattributesfichier. Généralement, les entrées dans .gitattributesspécifient comment les fichiers correspondants doivent être traités. Dans le cas du PO, il s'agissait de normaliser les fins de ligne; dans le mien, il s'agissait de laisser LFS gérer le stockage des fichiers. Dans les deux cas, le fichier qui gits'affiche lors du calcul d'un git diffne correspond pas au fichier que vous voyez lorsque vous inspectez le fichier. Par conséquent, si vous modifiez la façon dont un fichier est traité via le .gitattributesmodèle qui lui correspond, il apparaîtra comme des modifications non programmées dans le rapport d'état, même s'il n'y a vraiment pas de modification dans le fichier.

Cela dit, ma «réponse» à la question est que si le changement de .gitattributesfichier est quelque chose que vous vouliez faire, vous devriez vraiment simplement ajouter les changements et continuer. Sinon, modifiez le .gitattributespour mieux représenter ce que vous voulez faire.

Références

  1. Spécification GitHub LFS - Grande description de la façon dont ils se connectent aux appels de fonction cleanet smudgepour remplacer votre fichier dans les gitobjets par un simple fichier texte avec un hachage.

  2. gitattributes Documentation - Tous les détails sur ce qui est disponible pour personnaliser la façon dont gittraite vos documents.

merv
la source
0

J'ai eu le même problème. Je l'ai fait, git reset --hard HEADmais chaque fois que je l'ai fait, git statusje voyais certains fichiers modifiés.

Ma solution était relativement simple. Je viens de fermer mon IDE (ici c'était Xcode) et de fermer ma ligne de commande (ici c'était un terminal sur mon Mac OS) et je l'ai réessayé et cela a fonctionné.

Pourtant, je n'ai jamais pu trouver l'origine du problème.

Mon chéri
la source
0

Je crois qu'il y a un problème avec git pour Windows où git écrit au hasard les mauvaises fins de ligne lors du paiement et la seule solution consiste à extraire une autre branche et à forcer git à ignorer les modifications. Vérifiez ensuite la branche sur laquelle vous souhaitez réellement travailler.

git checkout master -f
git checkout <your branch>

Sachez que cela annulera toutes les modifications que vous pourriez avoir intentionnellement apportées, donc ne faites cela que si vous rencontrez ce problème immédiatement après le paiement.

Edit: j'aurais peut-être eu de la chance la première fois. Il s'avère que je me suis de nouveau mordu après avoir changé de branche. Il s'est avéré que les fichiers git rapportaient comme modifiés après le changement de branche. (Apparemment, car git n'appliquait pas correctement la fin de la ligne CRLF aux fichiers.)

J'ai mis à jour le dernier git pour Windows et j'espère que le problème a disparu.

mrfelis
la source
0

Problème similaire, bien que je ne sois sûr qu'en surface. Quoi qu'il en soit, cela peut aider quelqu'un: ce que j'ai fait (FWIW, dans SourceTree): a caché le fichier non engagé, puis a fait une réinitialisation matérielle.

aîné aîné
la source
0

Comme d'autres réponses l'ont souligné, le problème est dû à la correction automatique de fin de ligne. J'ai rencontré ce problème avec les fichiers * .svg. J'ai utilisé le fichier svg pour les icônes dans mon projet.

Pour résoudre ce problème, je préviens git que les fichiers svg doivent être traités comme binaires au lieu de texte en ajoutant la ligne ci-dessous à .gitattributes

* .svg binaire

vuamitom
la source
0

Dans une situation similaire. À la suite de nombreuses années de tourments avec de nombreux programmeurs qui ont pu bourrer différents encodages des fins de lignes (. Asp , .js, .css ... pas l'essentiel) dans un seul fichier. Il y a quelque temps a refusé .gitattributes. Paramètres de repo gauche autorclf = trueet safecrlf = warn.

Le dernier problème est survenu lors de la synchronisation à partir de l'archive avec différentes extrémités de lignes. Après avoir copié à partir de l'archive, dans l'état git, de nombreux fichiers sont modifiés avec la note

The line will have its original line endings in your working directory. warning: LF will be replaced by CRLF in ...

Conseils de Comment normaliser les fins de ligne d'arbre de travail dans Git? aidé

git add -u

MrSwed
la source
0

Une autre possibilité que j'ai rencontrée était que l'un des packages du référentiel se soit retrouvé avec une HEAD détachée. Si aucune des réponses ici n'aide et que vous rencontrez un message d'état git comme celui-ci, vous pourriez avoir le même problème:

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:   path/to/package (new commits)

Entrer dans le path/to/packagedossier a git statusdevrait donner le résultat suivant:

HEAD detached at 7515f05

Et la commande suivante devrait alors résoudre le problème, où masterdevrait être remplacé par votre branche locale:

git checkout master

Et vous obtiendrez un message indiquant que votre branche locale aura un certain nombre de validations derrière la branche distante. git pullet vous devriez être hors des bois!

Robin De Schepper
la source
0

Pour certaines raisons

git add .

n'a pas fonctionné , mais

$ git add -A

élaboré!

Daniel Danielecki
la source