Нестаціонарні зміни, залишені після скидання git - тверді


275

Після git reset --hard, git statusнадає мені файли в Changes not staged for commit:розділі.

Я також намагався git reset ., git checkout -- .і git checkout-index -f -aбезрезультатно.

Отже, як я можу позбутися тих нестандартних змін?

Здається, це стосується лише файлів проекту Visual Studio. Дивно. Дивіться цю пасту: http://pastebin.com/eFZwPn9Z . Особливістю цих файлів є те, що у .gitattributes я маю:

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

Також autocrlfу моєму глобальному режимі встановлено значення false .gitconfig. Це може бути якось актуально?


Чи застосували ви ці команди з кореня сховища? Повідомлення .означає, що поточний каталог не є кореневим каталогом
Олександр

1
Я дійсно робив їх із кореневого сховища.
Norswap

Яка ваша gitверсія? Чи ти робиш дурну помилку, чи ти маєш стару версію, яка баггі?
Шахбаз

Це git 1.7.4 msysgit. Це може бути помилка, але команди здаються досить простими, і я не міг помітити помилку.
Norswap

Для запиту я спробував використати останню версію msysgit (1.7.11), але проблема зберігається.
Norswap

Відповіді:


361

У мене була така ж проблема, і вона була пов'язана з .gitattributesфайлом. Однак тип файлу, що спричинив проблему, не вказаний у .gitattributes.

Я зміг вирішити проблему, просто запустившись

git rm .gitattributes
git add -A
git reset --hard

7
Це * text = auto директива у файлі gitattributes. Він автоматично змінює закінчення файлів, тому файли автоматично будуть позначені як "змінені" при перевірці стану.
Коді Джанго

3
Це працює, але я не точно розумію, чому. Комусь хочеться пояснити кожну команду?
Едвін Стотелер

18
@NLwino, git rm .gitattributesвилучає .gitattributes з індексу. git add -Aдодає всі (включаючи видалення .gitattributes) до індексу, який повинен бути лише видаленням .gitattributes, якщо це справді було проблемою. git reset --hardскидає всі невідомі зміни, які б включали видалення .gitattributes. По суті, це ігнорує .gitattributes (і * text=autoдирективу) для одного комітету , видаляючи його, потім скидаючи індекс, поки він видалений, тому повертає його назад, але після того, як ви вже скинули інші файли, щоб вони знову не були змінені.
хмарні роботи

4
@GameScripting, це рішення не працює для мене. Немає такого файлу як .gitattributes: "fatal: pathspec '.gitattributes' не відповідав жодним файлам"
Pacerier

4
Я таке роблю, і це говорить fatal: pathspec '.gitattributes' did not match any files . Що я роблю неправильно?
Мед

136

РЕШЕНИЙ !!!

Я вирішив цю проблему, виконавши наступні кроки

1) Видаліть кожен файл із індексу Git.

git rm --cached -r .

2) Перепишіть індекс Git, щоб зібрати всі нові закінчення рядків.

git reset --hard

Рішення було частиною кроків, описаних на сайті git https://help.github.com/articles/dealing-with-line-endings/


5
ЦЕ ПРАЦЮЄ, коли нічого іншого не робить! Ми пробували все в цій та багатьох інших темах - це велика команда розробників, тому потрапляння всіх на одне і те ж саме було кошмаром, але це вирішує проблему.
tkersh

Цікаво ... Я використав "git rm --chached <one_specific_file>, замість того, щоб видаляти все." Git status "повідомив про цей файл як видалений і не відстежений. Потім" git reset --hard "виправить цей файл та всі інші файли, які повідомлялося як "Зміни не інсценовані". (Перш ніж використовувати git rm, я дуже намагався скинути
безрезультатно

Ви знаєте, він видаляє весь ваш кеш. У великих проектах це може витратити багато часу.
Охар

Це жорстоко. Ви могли б зробити те ж саме, видаливши каталог repo та повторно клонувавши.
ingyhere

4
Подумайте, що ви перебуваєте в Windows і що це нечутливе до регістру. Якщо ви також працюєте з розробниками, які працюють на файлових системах, залежних від регістру, таких як Macs або Linux, вони можуть вводити теги, гілки або навіть файли в різних випадках. У цій ситуації ваш індекс покаже наявні файли, які перезаписуються ОС, коли він тягне. Єдиний спосіб виправити це - запровадити політику іменування на своєму сервері Git (гачки) або заздалегідь обнюхати помилки.
ingyhere

97

Git не скидає файли, які не знаходяться у сховищі. Отже, ви можете:

$ git add .
$ git reset --hard

Це дозволить змінити всі зміни, через які Git буде знати про ці файли, а потім скине їх.

Якщо це не допомогло, ви можете спробувати приховати та відхилити зміни:

$ git stash
$ git stash drop

4
Файли вже відстежуються. Спробував це все одно, і це не працює. З моїм репо повинно бути щось не так, але я не маю поняття, що. Про те, що сховано на гет, дивіться мою відповідь Шахбазу.
Norswap

Що відбувається, коли ти робиш статус git?
ЮрійАльбукерке

1
Я думав про рішення. Зробіть команду та інтерактивну базу даних, щоб стерти це.
ЮрійАльбукерке

Я спробував це в один момент, і це спрацювало, але я згодом спробував ще раз і придумав дивовижний результат, викладений у редакції моєї відповіді.
Norswap

@YuriAlbuquerque, Git не зовсім розуміє POLA . Чи не вся суть у тому, git reset --hardщоб " скинути і область постановки, і робочий каталог, щоб відповідати "? Якщо файл не ставиться, ми, очевидно, хотіли б його видалити, коли це робимо reset --hard.
Пейсьєр

71

Якщо ви використовуєте Git для Windows, це, ймовірно, ваша проблема

У мене були ті ж проблеми, і приховування, жорсткий перезавантаження, чистий або навіть усі вони все ще залишали зміни. Проблема виявилася в режимі файлів x, який не встановлений належним чином git. Це "відома проблема" з git для windows. Локальні зміни показують статус gitk та git як старий режим 100755 новий режим 100644, без фактичних відмінностей у файлі.

Виправлення полягає в ігноруванні режиму файлів:

git config core.filemode false

Більше інформації тут


2
Це спрацювало тоді, коли навіть rm -rf *; git checkout HEAD .не було. Фу!
форумчатор

Працював для мене, тоді як приховування падіння / жорсткий скидання / rm .attributes все не вдалося.
kakyo

Це також спрацювало для мене, коли у мене виникли проблеми з git repo в Linux, який розміщений на Mac
prmph

працював на мене - спробував все інше, і так, старий режим проти нового режиму був проблемою (зауважив, що у мене інша кількість, але файли однакові)
Taehoon A Kim

Життя та економія часу.
Йогеш Патіль

31

Гаразд, я якось вирішив проблему.

Здавалося, що .gitattributesфайл, що містить:

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

зробив файли проекту нестандартними. Я не знаю, чому це так, і я дуже сподіваюся, що хтось прихильний до способів git дасть нам приємне пояснення.

Моє виправлення було видалити ці файли, і додати autocrlf = falseпід [core]в .git/config.

Це не означає абсолютно те саме, що і попередня конфігурація, оскільки вимагає наявності кожного розробника autocrlf = false. Я хотів би знайти краще виправлення.

Редагувати:

Я коментував звинувачувальні рядки, коментував їх, і це спрацювало. Що ... я навіть не ...!


1
У мене просто була така сама точна проблема, і це було єдиним рішенням, яке спрацювало. У моєму випадку я перейшов з гілки функцій до мого майстра і витягнув нові зміни з висхідного потоку, і це почалося з двома зміненими файлами. Схоже, файли, можливо, були переключені з Unix на закінчення рядків Windows, що може мати щось спільне з цим. Не впевнений, як і чому все-таки.
Стівен Суровец

+1 Той самий випуск у Windows Git. Вже мав autocrlf = false. Я злився в змінах від upnv svpo repo ( git svn fetch/ git merge git-svn) і залишив 1 файл, позначений як змінений. Дивна річ у тому, що у мене була ця проблема раніше, і все, що мені потрібно було зробити, це перевірити іншу гілку (з -fпрапором), а потім переключитися назад. Я це зробив, і це спрацювало, але коли я перейшов до гілки функцій, "зміна" повернулася! Ваша редакція внизу відповіді була рішенням. У моєму випадку я прокоментував / коментував один рядок у верхній частині мого файлу .gitattributes:* text=auto !eol
Аарон Бленкуш

1
Цей EDIT працював і для мене: прокоментуйте рядки в .gitattributes, запустіть git status, скаментуйте рядки .gitattributes, запустіть git statusзнову
Ignitor

Це пов’язано з тим, що git скидає ці файли, а потім застосовує закінчення рядків, зазначені в .gitattributesповторі. git diff, Ймовірно , показує знамениту стіну червоного / зеленого кольору стіни , що є типовим для завершень рядків відмінностей.
Dagrooms

21

Можлива причина №1 - Нормалізація закінчення рядків

Одна з ситуацій, в якій це може статися, - коли відповідний файл був зареєстрований у сховище без правильної конфігурації для закінчень рядків (1), в результаті чого файл у сховищі має неправильні закінчення рядків або змішані закінчення рядків. Щоб підтвердити, переконайтеся, що git diffвідображаються лише зміни в закінченнях рядків (вони можуть не бути видимими за замовчуванням, спробуйте git diff | cat -vпобачити повернення каретки як буквальне^M символи).

Згодом хтось, ймовірно, додав .gitattributesабо змінив core.autocrlfналаштування для нормалізації закінчень рядків (2). На основі .gitattributesконфігурації або глобальної конфігурації, Git застосував локальні зміни до вашої робочої копії, які застосовують рядок, що закінчує запит на нормалізацію. На жаль, чомусьgit reset --hard не скасовує ці зміни в нормалізації лінії.

Рішення

Обхідні шляхи, в яких скидаються закінчення локальних рядків, не вирішать проблему. Кожен раз, коли файл "бачить" git, він намагатиметься повторно застосувати нормалізацію, внаслідок чого виникає та сама проблема.

Найкращий варіант - дозволити git застосувати нормалізацію, яку він хоче, шляхом нормалізації всіх закінчень рядків у репо, щоб вони відповідали .gitattributes, та внесення цих змін - див. Спроба виправити закінчення рядків за допомогою git filter-branch, але не маючи удачі .

Якщо ви дійсно хочете спробувати повернути зміни до файлу вручну, то, як видається, найпростішим рішенням є видалити змінені файли, а потім сказати git відновити їх, хоча зауважу, це рішення, здається, не працює стабільно на 100% час ( ПОПЕРЕДЖЕННЯ: НЕ запускайте це, якщо ваші змінені файли мають інші зміни, ніж закінчення рядків !!):

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

Зауважте, що якщо ви не нормалізуєте закінчення рядків у сховищі в якийсь момент, ви продовжуєте працювати з цією проблемою.

Можлива причина №2 - Нечутливість до справи

Друга можлива причина - нечутливість випадків у Windows чи Mac OS / X. Наприклад, скажіть, що в сховищі існує такий шлях, як наступний:

/foo/bar

Тепер хтось із Linux здійснює /foo/Barвведення файлів у файли (можливо, завдяки інструменту збирання або тому, що створив цей каталог) і натискає. В Linux це фактично зараз два окремі каталоги:

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

Перевірка цього репо з на Windows , Mac або може привести до модифікованого , fileAякі не можуть бути скинуті, тому що на кожному скиданні, мерзотника на Windows , перевіряє /foo/bar/fileA, а потім з - за Windows , не чутлива до регістру, переписує вміст fileAз/foo/Bar/fileA , в результаті чого в них бути «змінені».

Іншим випадком можуть бути окремі файли (файли), які існують у репо, які при перевірці на файлову систему, нечутливу до справ, перекриватимуться. Наприклад:

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

Можуть бути й інші подібні ситуації, які можуть спричинити такі проблеми.

git на нечутливі до випадку файлові системи повинні дійсно виявити цю ситуацію та показати корисне попереджувальне повідомлення, але наразі цього немає (це може змінитися в майбутньому - див. цю дискусію та пов'язані із запропонованими виправленнями у списку розсилки git.git).

Рішення

Рішення полягає в тому, щоб привести у відповідність регістр файлів у індексі git та регістр файлової системи Windows. Це можна зробити в Linux, який покаже справжній стан речей, АБО в Windows з дуже корисною утилітою з відкритим кодом Git-Unite . Git-Unite застосує необхідні зміни до індексу git, які потім можуть бути передані репо.

(1) Це, швидше за все, хтось, хто використовує Windows, без будь-якого .gitattributesвизначення відповідного файлу та використовував глобальну настройку за замовчуванням, core.autocrlfяка є false(див. (2)).

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


Чортовий син, пройшов увесь шлях до цього. Мені довелося скористатися після першого рядка, але мені вдалося нарешті перевірити майстра. Це було не весело.
Тім Ліберман

16

Якщо інші відповіді не працюють, спробуйте додати файли, а потім скиньте

$ git add -A
$ git reset --hard

У моєму випадку це допомогло, коли з’явилася купа порожніх файлів, які git відстежував.


Це працює. Я щойно використав $ git add .замість$ git add -A
Bjarne Gerhardt-Pedersen

8

Ще однією причиною цього можуть бути нечутливі до регістру файлові системи . Якщо у вас є кілька папок у вашому РЕПО на одному рівні, імена яких залежать лише від випадку, ви отримаєте це від удару. Перегляньте джерело сховища за допомогою його веб-інтерфейсу (наприклад, GitHub або VSTS), щоб переконатися.

Для отримання додаткової інформації: https://stackoverflow.com/a/2016426/67824


Щоб знайти назви таких файлів, запустітьgit ls-tree -r --name-only HEAD | tr A-Z a-z | sort | uniq -d
Diomidis Spinellis


5

Жоден із цих методів для мене не працював, єдиним рішенням було занурити всю репо і повторно її клонувати. Сюди входить зберігання, скидання, додавання та скидання, налаштування clrf, чутливість регістру тощо.


Оновлення, виявилось, що моя монтована файлова система, що відрізняється від регістру, насправді не відрізнялася від регістру Після того як я встановив, що цю проблему можна вирішити за допомогою згаданих вище методик.
Джон Хант

4

Виконати чисту команду:

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

git clean -fd

3
На жаль, це не вирішує питань, пов’язаних із закінченнями рядків.
Крістофер Шнайдер

Це єдине, що вирішує мою проблему, якою б не була моя проблема. У мене не було .gitattributesзакінчень файлів і рядків, це не було проблемою, оскільки я перебуваю на linux box, і всі розробники та наш сервер є Linux.
Семюел Нефф

4

Перевірте своє .gitattributes.

У моєму випадку у мене є *.js text eol=lfі git варіант core.autocrlfбув true.

Це приводить мене до ситуації, коли git автоперетворює закінчення моїх файлів і заважає мені виправити це, і навіть git reset --hard HEADнічого не робив.

Я це виправляю, коментуючи *.js text eol=lfсвою, .gitattributesі коментую її після неї.

Схоже, це просто грі магія.


Це було для мене, модернізувавши проект, представлений *.bat text eol=crlfмоїм проектом.
Лев

1

Я потрапив у подібну проблему також .gitattributes, але в моєму випадку був пов'язаний LFS GitHub. Хоча це не зовсім сценарій роботи ОП, я думаю, що це дає можливість проілюструвати, що .gitattributesробить файл і чому це може призвести до нестандартних змін у вигляді "фантомних" відмінностей.

У моєму випадку файл уже був у моєму сховищі, як з початку часу. У недавньому комітеті я додав новийgit-lfs track правило, використовуючи шаблон, який був заднім оглядом трохи занадто широким, і закінчуючи відповідності цьому старовинному файлу. Я знаю, що не хотів змінювати цей файл; Я знаю, що я не змінив файл, але тепер це було в моїх нестандартних змінах, і жодна кількість перевірок або жорстких перезавантажень у цьому файлі не збиралася виправити його. Чому?

Розширення GitHub LFS працює в основному за рахунок використання гачків, що gitзабезпечує доступ через .gitattributesфайл. Як правило, записи .gitattributesвказують, як повинні бути оброблені відповідні файли. У випадку з ОП це стосувалося нормалізації закінчень рядків; в моєму випадку було, чи дозволити LFS обробляти файли для зберігання. В будь-якому випадку фактично файл, який бачите при gitобчисленні а git diff, не відповідає файлу, який ви бачите під час огляду файлу. Отже, якщо ви зміните, як файл обробляється за відповідною .gitattributesсхемою, він відображатиметься як нестандартні зміни у звіті про стан, навіть якщо у ньому дійсно не відбувається змін.

Все, що було сказано, моя "відповідь" на питання полягає в тому, що якщо зміна .gitattributesфайлу - те, що ви хотіли зробити, вам слід просто додати зміни та рухатися далі. Якщо ні, то внесіть зміни, .gitattributesщоб краще представити, що ви хочете робити.

Список літератури

  1. Специфікація GitHub LFS - Чудовий опис того, як вони підключаються до функції cleanта smudgeвимагає заміни вашого файлу в gitоб'єктах простим текстовим файлом з хешем.

  2. gitattributes Documentation - Усі деталі щодо того, що є для налаштування способів gitобробки ваших документів.


0

У мене була така ж проблема. Я це робив, git reset --hard HEADале все одно щоразу, коли я робив, git statusя бачив деякі файли як змінені.

Моє рішення було відносно простим. Я щойно закрив свій IDE (тут це був Xcode) і закрив свій командний рядок (тут він був терміналом на моїй Mac OS) і спробував його знову, і він спрацював.

І все ж мені так і не вдалося знайти те, що спричинило проблему.


0

Я вважаю, що існує проблема з git для Windows, де git випадковим чином записує неправильні закінчення рядка під час оформлення замовлення, і єдине рішення - це перевірити якусь іншу гілку та змусити git ігнорувати зміни. Потім перевірте відділення, над яким ви дійсно хочете працювати.

git checkout master -f
git checkout <your branch>

Майте на увазі, що це відкине будь-які зміни, які ви могли навмисно внести, тому зробіть це лише в тому випадку, якщо у вас виникнуть ці проблеми відразу після оформлення замовлення.

Редагувати: Мені, можливо, вперше пощастило. Виявляється, я знову покусав після перемикання гілок. Виявилося, що файли git звітували як змінені після зміни гілок. (Мабуть, тому, що git послідовно не застосовував належним чином файл CRLF, який закінчується до файлів.)

Я оновив до останнього git для Windows і сподіваюся, що проблеми вже немає.


0

Подібне питання, хоча я впевнений лише на поверхні. У будь-якому випадку це може комусь допомогти: те, що я зробив (FWIW, в SourceTree): приховав непосланий файл, а потім провів жорсткий скидання.


0

Як вказували інші відповіді, проблема полягає в автоматичному виправленні рядків в кінці. Я зіткнувся з цією проблемою з файлами * .svg. Я використовував файл svg для іконок у своєму проекті.

Щоб вирішити цю проблему, я повідомляю git знати, що файли svg слід розглядати як бінарні замість тексту, додаючи нижній рядок до .gitattributes

* .svg двійковий


0

У подібній ситуації. В результаті багаторічних мук багатьох програмістів, які змогли скласти різні кодування кінців рядків (. Asp , .js, .css ... не суть) в один файл. Деякий час тому відмовився .gitattributes. Налаштування для репо зліва autorclf = trueта safecrlf = warn.

Остання проблема виникла при синхронізації з архіву з різними кінцями рядків. Після копіювання з архіву, у статусі git багато файлів змінюються на замітку

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

Поради, як нормалізувати робочі закінчення дерев в Git? допомогли

git add -u


0

Іншою можливістю, з якою я стикався, було те, що один із пакунків у сховищі закінчувався окремою HEAD. Якщо жодна з відповідей тут не допомагає, і ви натрапили на повідомлення про статус git, подібне до цього, у вас може виникнути та сама проблема:

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)

Перехід у path/to/packageпапку a git statusповинен отримати такий результат:

HEAD detached at 7515f05

І наступна команда повинна вирішити проблему, де її masterслід замінити вашою місцевою гілкою:

git checkout master

І ви отримаєте повідомлення про те, що ваша локальна філія буде деякою кількістю комісій за віддаленою гілкою. git pullі ти повинен бути з лісу!


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.