Как остановить отслеживание и игнорировать изменения в файле в Git?

1732

Я клонировал проект, который включает в себя несколько .csprojфайлов. Мне не нужно / не нравится, чтобы мои локальные csprojфайлы отслеживались Git (или появлялись при создании патча), но они явно нужны в проекте.

Я добавил *.csprojк своему МЕСТНОМУ .gitignore, но файлы уже находятся в репо.

Когда я набираю git status, он показывает мои изменения, csprojкоторые я не заинтересован в отслеживании или отправке патчей.

Как убрать «отслеживание» этих файлов из моего личного репозитория (но сохранить их в источнике, чтобы я мог их использовать), чтобы не видеть изменения при создании статуса (или создании патча)?

Есть ли правильный / канонический способ справиться с этой ситуацией?

Джошуа Болл
источник
18
Очень полезный вопрос, но мне любопытно, почему вы не хотите отслеживать изменения в .csprojфайле, который является очень важной частью любого проекта. Изменения в .csproj.userфайле или любых .Publish.XMLфайлах, которые я полностью понимаю, не отслеживание, но я заинтригован тем, почему вы не хотите отслеживать .csproj
Оуэн Блэкер
7
Может они используют другую IDE?
Джарретт
3
По иронии судьбы, я пришел к этой теме, потому что я ищу удалить файлы .suo из репозитория, но храню их локально. Для потомков .Net-разработка требует, чтобы вы хранили файлы .csproj в репозитории, и эти изменения должны всегда отслеживаться, если вы не хотите чувствовать гнев других разработчиков в вашем проекте. Если вы не уверены, взгляните на репозиторий файлов gitignore на GitHub: github.com/github/gitignore/blob/master/VisualStudio.gitignore
longda,
1
@Cupcake, вопрос, на который ты ссылался, был написан через 15 дней после этого? Возможно, вы имеете в виду другое?
stephenmurdoch
Канонические вопросы @marflar не обязательно должны быть самыми старыми , только самые лучшие . На тот, на который я

Ответы:

2130

Просто вызовите git rm --cachedкаждый из файлов, которые вы хотите удалить из контроля версий. Пока ваши локальные шаблоны игнорирования верны, вы не увидите эти файлы, включенные в вывод состояния git.

Обратите внимание, что это решение удаляет файлы из репозитория, поэтому всем разработчикам необходимо поддерживать свои собственные локальные (не контролируемые редакцией) копии файла.

Чтобы git не обнаружил изменения в этих файлах, вы также должны использовать эту команду:

git update-index --assume-unchanged [path]

Что вы, вероятно, хотите сделать: (снизу @ Райан Тейлор ответ )

  1. Это говорит git, что вы хотите свою собственную независимую версию файла или папки. Например, вы не хотите перезаписывать (или удалять) производственные / промежуточные файлы конфигурации.

git update-index --skip-worktree <path-name>

Полный ответ здесь в этом URL: http://source.kohlerville.com/2009/02/untrack-files-in-git/

Энтони
источник
187
«git rm --cached <file>» удалит <file> из управления версиями, сохранив его в рабочем хранилище. Будь то, что вы хотите ...
Jakub Narębski
51
Но когда другие будут извлекать хранилище, будет ли удален их собственный файл * .csproj? Потому что, если мы хотим, чтобы файл не отслеживался, но не удалялся.
FMaz008
23
Если вы пытаетесь удалить ВСЕ файлы в каталоге, объедините его с git ls-files: git ls-files | xargs git rm --cached- это удалит все из индекса git в данном каталоге, не удаляя фактические файлы.
Марко
129
git rm --cached -r <dir>работает рекурсивно над папкой и всеми файлами в ней.
Крис К
41
Это остановит отслеживание файла, сохранит его локально, но приведет к тому, что он будет удален для всех, кто тянет
Эдвард Ньюэлл,
249

Если вы это сделаете git update-index --assume-unchanged file.csproj, git не будет проверять file.csproj на наличие изменений автоматически: это остановит их появление в состоянии git, когда вы их измените. Таким образом, вы можете пометить все ваши файлы .csproj таким образом, хотя вам придется вручную отмечать любые новые файлы, которые отправляет вам репозиторий верхнего уровня. (Если они есть в вашем .gitignoreили .git/info/exclude, то созданные вами будут игнорироваться)

Я не совсем уверен, что такое файлы .csproj ... если они что-то похожи на конфигурации IDE (аналогично файлам Eclipse .eclipse и .classpath), то я бы предложил, чтобы они никогда не контролировались исходным кодом в все. С другой стороны, если они являются частью системы сборки (например, Makefiles), то, очевидно, они должны - и был бы полезен способ получения необязательных локальных изменений (например, из local.csproj a la config.mk). разделите сборку на глобальные части и локальные переопределения.

araqnid
источник
8
csproj - это файл проекта C #, который отслеживает, какие файлы включены в ваш проект и некоторые другие конфигурации, он ДОЛЖЕН контролироваться исходным кодом, чтобы проект работал
SparK
4
Это единственный правильный ответ здесь! Я использую ответ @araqnids в течение многих лет, и он работает именно так, как было предложено для решения этой проблемы.
NHDaly
Что означает префикс «file» в аргументе команды? Почему это не просто .csproj?
GreenAsJade
1
Есть ли способ, которым вы можете обнаружить, что это было сделано для файла, или для каких файлов это было сделано в репо? Я немного нервничаю из-за того, что забыл, что сделал это, а потом удивляюсь, почему, черт возьми, этот файл не обновляется позже!
GreenAsJade
4
@GreenAsJade: git ls-files -vпокажет файлы, которые предполагается неизменными, с помощью строчного индикатора (например, hвместо обычного Hдля кэшированных файлов).
Amadan
238

Есть 3 варианта, вы, вероятно, хотите # 3

1. Это сохранит локальный файл для вас, но удалит его для всех остальных, когда они потянут.

git rm --cached <file-name> или git rm -r --cached <folder-name>

2. Это для оптимизации, как папка с большим количеством файлов, например, SDK, которые, вероятно, никогда не изменятся. Он говорит git прекратить проверять эту огромную папку каждый раз на наличие изменений, локально, поскольку она не будет иметь никаких изменений. assume-unchangedИндекс будет обнулен и файл (ы) перезаписаны , если есть вверх по течению изменения в файле / папке (при вытягивании).

git update-index --assume-unchanged <path-name>

3. Это говорит git, что вы хотите свою собственную независимую версию файла или папки. Например, вы не хотите перезаписывать (или удалять) производственные / промежуточные файлы конфигурации.

git update-index --skip-worktree <path-name>

Важно знать, что git update-index не будет распространяться с помощью git, и каждому пользователю придется запускать его независимо.

Райан Тейлор
источник
8
Этот ответ является наиболее полным - он предлагает различные решения с разветвлениями каждого. В конкретном случае, с которым я работаю, пароль встроен в файл конфигурации. Я хочу распространить файл шаблона, а затем добавить пароль к моей копии. Копия с паролем должна игнорироваться и не перезаписываться.
bmacnaughton
1
Как я могу проверить, в моем локальном компьютере, какие файлы применяются для «предположить, без изменений» или «skip-worktree»?
Супават Пусаванно
3
@SupawatPusavanno, чтобы увидеть, какие файлы вы ранее выбрали для предположения без изменений или пропустить рабочее дерево, посмотрите на этот ответ stackoverflow.com/questions/42363881/… - он использует grepиgit ls-files
Райан Тейлор,
1
Очень хороший ответ Но git выдает ошибку, когда я пытаюсь переключиться на другую ветку: error: «Ваши локальные изменения в следующих файлах будут перезаписаны извлечением .....», и решение состоит в том, чтобы спрятать изменения перед переключением и отстегнуть, когда ты возвращаешься в ветку.
PhantomReference
@RyanTaylor: Я пытался сначала предположить, что без изменений (не работает), и пропустить команду рабочего дерева (не работает), когда я проверяю с помощью состояния git, файлы не отображаются, значит команда работает. Но когда я снова it gives me error that your local changes would be overwrittenизвлекаю код из репозитория git origin в этих 2 файлах, это означает, что он не отслеживается, верно?
NeverGiveUp161
152

Это двухэтапный процесс:

  1. Удалить отслеживание файла / папки - но сохранить их на диске - используя

    git rm --cached 
    

    Теперь они не отображаются как «измененные», но все равно отображаются как

        untracked files in  git status -u  
    
  2. Добавьте их в .gitignore

rjha94
источник
56
Нет, это удалит файл из отслеживания, сохранит его локально, но приведет к тому, что он будет удален для всех, кто тянет .
Эдвард Ньюэлл,
1
В моем случае я случайно добавил папку, которую я не хотел отслеживать, так что это то, что мне нужно.
Сонни
4
Да, это действительно неправильный ответ на заданный вопрос - но, вероятно, это правильный ответ для большинства людей, которые находят этот вопрос в результатах поиска (например, я).
Эндрю Спенсер
96

Принятый ответ все еще не работал для меня

я использовал

git rm -r - кэшировано.

мерзавец добавить.

git commit -m "исправление .gitignore"

Нашел ответ отсюда

Буддика Хастанаяке
источник
Эта ссылка очень полезна, особенно для рекурсивного удаления всех файлов в .gitignore
rmcsharry
9
Я возвращался сюда 3 раза, надеюсь, я смогу сохранить память до следующего раза!
Гарри Бош
@ Комментарий Эдварда Ньюэлла, как и в приведенном выше ответе, также применим и здесь: «это удалит файл из отслеживания, сохранит его локально, но приведет к тому, что он будет удален для всех, кто извлекает »
ToJo
47

Забыли свой .gitignore?

Если у вас есть весь проект локально, но вы забыли добавить его, git ignore и теперь отслеживаете некоторые ненужные файлы, используйте эту команду, чтобы удалить все

git rm --cached -r .

убедитесь, что вы находитесь в корне проекта.

Тогда вы можете сделать обычное

Добавить

git add .

совершить

git commit -m 'removed all and added with git ignore'

От себя

git push origin master

Вывод

Надеюсь, что это поможет людям, которые должны внести изменения в их .gitignoreили забыли все это вместе.

  • Удаляет весь кеш
  • Смотрит на ваш .gitignore
  • Добавляет файлы, которые вы хотите отслеживать
  • Подталкивает к вашему репо
Джо Ллойд
источник
4
Когда вы говорите об удалении или добавлении, вы забываете сказать, когда и где. Удаление из списка треков? Из хранилища? Из локального проектного пространства? Удаление на тягу? На коммит? На толчок? Увы, у всех авторов здесь одна и та же проблема.
Гангнус
3
@Gangnus Я не думаю, что кто-то "прояснил" мысль, которую вы пытаетесь сделать, потому что совершенно очевидно, что файл на самом деле не удаляется с диска или из хранилища. Этот ответ указывает хронологический порядок команд. Это не таинственно или плохо объяснено, поскольку Ваш комментарий предположил бы.
Энтони
@ Комментарий Эдварда Ньюэлла, как и в приведенном выше ответе, применим также и к этому: «это удалит файл из отслеживания, сохранит его локально, но приведет к тому, что он будет удален для всех, кто тянет ».
ToJo
26

Как указано в других ответах, выбранный ответ является неправильным.

Ответ на другой вопрос предполагает , что это может быть пропуск worktree , которые потребуются.

git update-index --skip-worktree <file>
the_new_mr
источник
2
Нет, не совсем: --skip-worktreeиспользуется для сохранения файла в хранилище, но для остановки отслеживания его изменений . Как говорится в вашем ответе: --skip-worktree полезен, когда вы указываете git не трогать определенный файл, потому что разработчики должны его изменить
Erdal G.
4
@ErdalG. Точно. В соответствии с вопросом, они хотят игнорировать любые изменения в файле, но сохраняют файл в
репозитории
Согласитесь с @the_new_mr --assume-unchangedи --skip-worktreeполучите аналогичный эффект, но их цели совершенно другие. Первый предназначен для ускорения производительности git путем обмана git не проверять определенные файлы , а второй - для игнорирования будущих изменений в определенных файлах , которые подходят для времени выполнения, но важных файлов.
Виктор Вонг
22

Чтобы сэкономить время, вы можете использовать правила, которые вы добавляете в свой .gitignore, для удаления нескольких файлов / папок, т.е.

git rm --cached app/**/*.xml

или

git rm --cached -r app/widgets/yourfolder/

так далее

Питер
источник
Это очень хорошее решение, потому что в любом случае вы хотите починить gitignore шаг за шагом
cutiko
15

Чтобы предотвратить мониторинг файла с помощью git

git update-index --assume-unchanged [file-path]

И чтобы вернуть его обратно используйте

git update-index --no-assume-unchanged [file-path]

Репозиторий для ссылок на похожие варианты использования https://github.com/awslabs/git-secrets

Shijin
источник
1
Возвращение чаевых спасло жизнь, спасибо!
Хамман Самуил
9

Многие люди советуют вам использовать git update-index --assume-unchanged . Действительно, это может быть хорошим решением, но только в краткосрочной перспективе.

Что вы, вероятно, хотите сделать, это: git update-index --skip-worktree .

(Третий вариант, который вам, вероятно, не нужен: git rm --cached он сохранит ваш локальный файл, но будет помечен как удаленный из удаленного хранилища.)

Разница между первыми двумя вариантами?

  • assume-unchangedЭто временно позволяет скрыть изменения из файла. Если вы хотите скрыть изменения, внесенные в файл, изменить файл, а затем оформить заказ в другой ветке, вам придется использовать, no-assume-unchangedвероятно, сохраненные изменения.
  • skip-worktree будет следовать за вами независимо от того, какую ветку вы заказываете, с вашими модификациями!

Случай использования assume-unchanged

Предполагается, что этот файл не должен быть изменен, и дает более чистый вывод при выполнении git status. Но когда вы переходите в другую ветку, вам необходимо сбросить флаг и зафиксировать или сохранить изменения перед этим. Если вы активируете эту опцию, вам нужно будет разрешать конфликты, а git не будет автоматически объединяться. На самом деле скрывает только модификации (git status не будет отображать помеченные файлы).

Мне нравится использовать его, когда я хочу только на некоторое время остановить отслеживание изменений + зафиксировать кучу файлов ( git commit -a), связанных с той же модификацией.

Случай использования skip-worktree

У вас есть класс настройки, содержащий параметры (например, включая пароли), которые ваши друзья должны изменить в соответствии с их настройкой.

  • 1. Создайте первую версию этого класса, заполните поля, которые вы можете заполнить, и оставьте другие поля пустыми / пустыми.
  • 2: зафиксируйте и отправьте его на удаленный сервер.
  • 3: git update-index --skip-worktree MySetupClass.java
  • 4: Обновите свой класс конфигурации с вашими собственными параметрами.
  • 5: вернитесь к работе над другой функциональностью.

Изменения, которые вы делаете, будут следовать за вами независимо от ветки. Предупреждение: если ваши друзья также хотят изменить этот класс, они должны иметь ту же настройку, иначе их изменения будут перенесены в удаленный репозиторий. При вытягивании удаленная версия файла должна перезаписать вашу.

PS: делайте одно или другое, но не оба, так как у вас будут нежелательные побочные эффекты. Если вы хотите попробовать другой флаг, вы должны сначала отключить его.

Belka
источник
7

Чтобы запретить Git отслеживать изменения в вашем локальном файле / папке (т.е. git status не обнаружит изменения в нем), выполните:

git update-index --skip-worktree path/to/file

И чтобы Git снова отслеживал изменения в вашей локальной версии (чтобы вы могли зафиксировать изменения), выполните:

git update-index --no-skip-worktree path/to/file
Руто Коллинз
источник
1

однострочный ответ git update-index --assume-unchanged [path]

Используйте это всякий раз, когда у вас есть файл, который находится в центральном репо, а также в локальном репо. Вам необходимо внести изменения в этот файл, но его нельзя ставить / фиксировать в центральном репо. Этот файл не должен быть добавлен в.gitignore . поскольку новые изменения в файле, если они внесены системными администраторами, старшие разработчики должны быть распределены среди всех локальных репозиториев.

Лучший пример: файл конфигурации для соединений с БД . В центральном репо у вас будут все имя пользователя, пароль, хост, порт со значениями рабочего сервера БД. Но в локальном dev вы должны использовать только локальный или любой другой сервер БД разработки (который есть у вашей команды). В этом случае вы хотите внести изменения в конфигурационный файл, но не должны быть зафиксированы в центральном репо.

Лучший

Seenivasan
источник
0

Я предполагаю, что вы спрашиваете, как удалить ВСЕ файлы в определенной папке или папке bin, а не выбирать каждый файл отдельно.

Вы можете использовать эту команду:

git rm -r -f /<floder-name>\*

Убедитесь, что вы находитесь в родительском каталоге этого каталога.
Эта команда рекурсивно «удалит» все файлы, которые находятся в папках bin / или build /. Под словом «удалить» я подразумеваю, что git сделает вид, что эти файлы «удалены», и эти файлы не будут отслеживаться. Git действительно отмечает, что эти файлы находятся в режиме удаления.

Убедитесь, что ваш .gitignore готов к предстоящим коммитам.
Документация: git rm

Врадж Пандя
источник
0

Проблема может быть вызвана порядком работы. Если вы сначала изменили .gitignore, а затем git rm --cached xxx, возможно, вам придется продолжать сталкиваться с этой проблемой.

Правильное решение :

  1. мерзавец - кэшированный ххх
  2. изменил .gitignore

Заказать инвариант!

.Gitignore перезагрузить после модификации!

thearyong
источник
0

Я предполагаю, что вы пытаетесь удалить один файл из git tacking. для этого я бы порекомендовал ниже команду.

git update-index --assume-неизменный

Ex - git update-index --assume-неизмененный .gitignore .idea / compiler.xml

Панкадж Сонани
источник
0

Чтобы игнорировать любые изменения всех файлов (определенного типа) в каталоге, мне пришлось объединить некоторые из этих подходов, в противном случае файлы были созданы, если их ранее не существовало.

В приведенном ниже тексте «excirir» - это имя каталога, в который я не хочу смотреть изменения.

Сначала удалите все существующие новые файлы из кэша отслеживания изменений (без удаления из файловой системы).

git status | grep "new file:" | cut  --complement -d " " -f1-4 | grep "^excludedir" | xargs git rm --cache

Вы можете сделать то же самое с modified:. renamed:немного сложнее, так как вам придется посмотреть ->бит сообщения для нового имени файла и выполнить предварительный ->бит, как описано deleted:ниже.

deleted: файлы оказываются немного сложнее, так как вы не можете обновить индекс для файла, который не существует в локальной системе

echo .deletedfiles >> .gitignore
git status | grep "deleted:" | cut  --complement -d " " -f1-4 | grep "^excludedir" > .deletedfiles
cat .deletedfiles | xargs -d '\n' touch
cat .deletedfiles | xargs -d '\n' git add -f
cat .deletedfiles | xargs -d '\n' git update-index --assume-unchanged
cat .deletedfiles | xargs -d '\n' rm

Последняя команда в списке выше снова удалит файлы из вашей файловой системы, поэтому не стесняйтесь опускать это.

Затем заблокируйте отслеживание изменений из этого каталога

git ls-files excludedir/ | xargs git update-index --skip-worktree
git update index --skip-worktree excludedir/
МПа
источник
0

В этом ответе был дан почти бесподобный подход без команд :

Чтобы игнорировать определенные файлы для каждого локального репо :

  1. Создайте файл ~/.gitignore_global, например, touch ~/.gitignore_globalв вашем терминале.
  2. Запустите git config --global core.excludesfile ~/.gitignore_globalна этот раз.
  3. Запишите пути к файлам / каталогам, в которые вы хотите игнорировать ~/.gitignore_global. например modules/*.H, которые будут считаться в рабочем каталоге, то есть $WORK_DIR/modules/*.H.

Чтобы игнорировать определенные файлы для одного локального репо :

  1. Выполните описанный выше третий шаг для файла .git/info/excludeв репозитории, то есть запишите пути file / dir, в которые вы хотите игнорировать .git/info/exclude. например modules/*.C, которые будут считаться в рабочем каталоге, то есть $WORK_DIR/modules/*.C.
Инженер герпеса
источник
0

Применить .gitignore к настоящему / будущему

Этот метод применяет стандартное поведение .gitignore и не требует ручного указания файлов, которые необходимо игнорировать .

Больше не могу использовать --exclude-from=.gitignore: / - Вот обновленный метод:

Общий совет: начните с чистого репо - все зафиксировано, ничего не ожидается в рабочем каталоге или индексе, и сделайте резервную копию !

#commit up-to-date .gitignore (if not already existing)
#this command must be run on each branch
git add .gitignore
git commit -m "Create .gitignore"

#apply standard git ignore behavior only to current index, not working directory (--cached)
#if this command returns nothing, ensure /.git/info/exclude AND/OR .gitignore exist
#this command must be run on each branch
git ls-files -z --ignored --exclude-standard | xargs -0 git rm --cached

#optionally add anything to the index that was previously ignored but now shouldn't be:
git add *

#commit again
#optionally use the --amend flag to merge this commit with the previous one instead of creating 2 commits.

git commit -m "re-applied modified .gitignore"

#other devs who pull after this commit is pushed will see the  newly-.gitignored files DELETED

Если вам также необходимо удалить недавно проигнорированные файлы из истории коммитов ветви, или если вы не хотите, чтобы недавно игнорируемые файлы были удалены из будущих извлечений , посмотрите этот ответ .

goofology
источник
-1

после долгого поиска найди способ сделать это. Псевдоним команда git в .gitconfig.like в проекте android studio , перед веткой оформления заказа верните файл конфигурации, а затем пропустите его , после ветки проверки используйте sedфайл конфигурации изменения для моей локальной конфигурации. checkoutandmodifylocalproperties = !git update-index --no-skip-worktree local.properties && git checkout local.properties && git checkout $1 && git update-index --skip-worktree local.properties && sed -i '' 's/.*sdk.dir.*/sdk.dir=\\/Users\\/run\\/Library\\/Android\\/sdk/g' local.properties && :

chinaanihchen
источник