Как я могу заставить git игнорировать будущие изменения файла?

140

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

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

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

Подвести итоги,

  1. Я хотел бы создать файл, назовите его default_values.txtдобавленным в мой репозиторий git и включенным, когда кто-то клонирует этот репозиторий.
  2. git add .не следует добавлять default_values.txtв коммит.
  3. Это поведение следует передать любым клонам репозитория.
Марк
источник
1
Можете ли вы использовать хуки git, чтобы иметь ловушку перед фиксацией, которая прерывала бы фиксацию, если измененным файлом является default_values.txt (скажем)?
сатиш 03
1
Пуристы в Git сказали бы, что не ленитесь и правильно используйте промежуточную область, для этого она и предназначена.
Xint0 03
Сторонники Git сказали бы использовать скрипты smudge / clean. Это наиболее удобное в обслуживании решение.
Адам Димитрук
1
Xint0: правда. но как предотвратить случайную регистрацию других людей?
Алан
возможный дубликат
фиксации

Ответы:

115

Как отмечали многие другие, хорошее современное решение:

git update-index --skip-worktree default_values.txt

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

git update-index --no-skip-worktree default_values.txt

Вы можете получить список файлов, которые отмечены как пропущенные:

git ls-files -v . | grep ^S

Обратите внимание, что в отличие от этого --skip-worktree, --assume-unchangedстатус будет потерян после того, как произойдет изменение восходящего потока.

moodboom
источник
2
Если кто-то другой извлекает репо и редактирует файл, игнорируются ли изменения в его каталоге? Я надеюсь, что им придется вводить текст, --no-skip-worktreeчтобы добавить свои изменения.
neaumusic
3
Что делается с их изменениями, контролируется ими. Другими словами, они должны будут установить skip-worktree для файла в своем репо, если они не хотят, чтобы их изменения были отправлены. Если это файл, который предназначен для отправки всем, а затем игнорируются все последующие изменения, все должны будут следовать этим же инструкциям.
moodboom
3
Обратите внимание, что вам может потребоваться отменить --skip-worktreeстатус файла, прежде чем вы сможете переключать ветви, если этот же файл отслеживается в другой ветви.
moodboom
3
хм, это работает ... после того, как я внес некоторые изменения в файл, он не был показан git status, но когда я попытался оформить заказ в другую ветку, у меня получилось error: Your local changes to the following files would be overwritten by checkout: , даже -f не помогаетerror: Entry 'wix-stores-merchant-app/demo/credentials.js' not uptodate. Cannot merge.
ykravv
1
У меня эти псевдонимы git ignoreи git unignore.
Майкл
48

То, что вы ищете, это git update-index --assume-unchanged default_values.txt.

См. Дополнительные сведения в документации: http://www.kernel.org/pub/software/scm/git/docs/git-update-index.html.

tamasd
источник
11
это не работает. хотя это делает git add. игнорировать файл в локальной ветке, клон архива не имеет такого поведения (если вы измените default_values.txt в клонированном архиве, он будет добавлен в коммит с помощью «git add.»)
Marc
6
Да, потому что вы устанавливаете его только для локального репо. Вы не можете распространять такую ​​информацию.
tamasd 03
8
@Indradhanush - это решение не удовлетворяет критерию 3 - «поведение должно передаваться любым клонам репозитория» - поэтому я его не принял. Это не значит, что это плохой ответ.
Marc
Третий критерий так и не заметил. Потому что я этого не искал. :)
Индрадхануш Гупта 08
3
Для локальных файлов конфигурации с частными настройками приложения вы, вероятно, захотите использовать skip-worktreeвместо assume-unchangedдополнительной информации stackoverflow.com/questions/13630849/…
Аарон Хоффман
22

Подход, который я обычно видел, - это создать файл с другим именем, например: default_values_template.txt, и поместить default_values.txt в ваш .gitignore. Попросите людей скопировать default_values_template.txt в default_values.txt в своих локальных рабочих областях и внести необходимые изменения.

Лоуренс Гонсалвес
источник
хммм ... может, я мог бы написать ловушку для автоматического копирования default_values_template в default_values, если default_values ​​не существует?
Marc
2
По моему опыту, это наиболее распространенный способ решить эту проблему. Это в значительной степени путь наименьшего сопротивления, поскольку он «просто работает», и вы можете легко заставить свой код проверять, существует ли локальный файл конфигурации, и выдавать полезную ошибку, если это не так.
Яни Хартикайнен
Я думаю, что решение действительно в том, чтобы сделать что-то подобное, желательно со сценарием, выполняемым всякий раз, когда вы тянете или клонируете. Одна из идей заключается в том, что что-либо с определенным расширением (скажем .basefile) копируется в файл с удаленным расширением, а затем имя файла добавляется в .gitignore в этом каталоге. Поэтому я бы создал файл default_values.txt.basefile и зафиксировал его. У меня нет для этого git или perl chops, но я спрошу друга, у которого есть, и расскажу, как это работает.
Marc
1
@AdamDymitruk: Да, в этом случае можно использовать clean / smudge, но далеко не ясно, что это лучший вариант. Например, это усложнит задачу, если люди действительно захотят изменить файл, так как чистый / пятнистый будет мешать. Я бы предпочел описанный здесь подход.
sleske
1
Я беру реплику из самого git (в частности, git hooks) и использую .sampleсуффикс. Так что в вашем случаеdefault_values.txt.sample
tir38
5

Взгляните на скрипты smudge / clean. Таким образом, вы можете управлять версиями файла, но когда он будет извлечен, вы "размазываете" его, заменяя общие данные / данные-заполнители машинными данными в файле.

Когда вы его фиксируете, вы «очищаете» его, заменяя информацию, относящуюся к машине, общей или замещающей информацией.

Скрипты размазывания / очистки должны быть детерминированными в том смысле, что их многократное применение в разном порядке будет эквивалентно простому запуску последнего в последовательности.

То же самое можно применить и к паролям, если вам нужно открыть репозиторий, но его содержимое может содержать конфиденциальную информацию.

Адам Димитрук
источник
Скрипты Clean и Smudge являются локальными или являются частью репозитория?
Алан
да. :) ... то есть вы можете поделиться чистым пятном через репо, но это не лучшая идея, когда они содержат конфиденциальные данные, такие как производственные пароли. Если это не проблема, git требует, чтобы вы явно включили скрипт. В противном случае люди могут делать вредоносные вещи через github и другие общие репозитории для других пользователей.
Адам Димитрук
Мне нужно прочитать об этом немного подробнее. По сути, я хочу настроить проект, у которого есть значение по умолчанию, user.jsonкоторое нужно перезаписать с помощью каждого кредита разработчика, но я не хочу, чтобы разработчик случайно проверил его кредиты.
Алан
Я бы погуглил, чтобы найти сценарии с примерами чистых пятен. Посмотри, что получится. Кроме того, прыгайте в комнату git irc на freenode. Вам сразу же помогут.
Адам Димитрук
3

Я решил эту проблему, определив «чистый» фильтр, чтобы просто отбирать содержимое файла в индексе.

git show :path/to/myfile должен просто распечатать содержимое индекса для указанного файла, чтобы мы могли использовать это в сценарии для замены рабочей копии нетронутой копией в индексе:

#! /bin/sh

git show :$1

Установите это как «чистый» фильтр для соответствующего файла (при условии, что вы поместили его в «discard_changes»):

$ git config filter.ignore_myfile.clean "discard_changes path/to/myfile"
$ echo "path/to/myfile filter=ignore_myfile" >> .gitattributes

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

Хэддон CD.
источник
1

Я нашел решение, которое подходит моей команде. Мы делимся нашими githooks через символические ссылки, и после добавления файла шаблона в git я добавил ловушку предварительной фиксации, которая проверяет, был ли изменен файл шаблона, и если да, то я git reset -- templatefile.txt. Если это единственный измененный файл, я также прерываю фиксацию.

fruitcoder
источник
-1

Предлагаю изучить подмодули. Если вы помещаете файлы, специфичные для компьютера, в подмодуль, git add игнорирует его.

ivanpro
источник
это хорошая идея, но тогда мне также нужно разместить единый файловый репозиторий на сервере git, что не совсем оптимально, только потому, что мы используем github и имеем ограниченное количество репозиториев.
Marc
@Marc взгляните на Visual Studio Team Services, неограниченное количество бесплатных частных проектов и репозитории git. Канбан-доски, отслеживание рабочих элементов и ошибок, связывание проверок с рабочими элементами, управление спринтами, если вы участвуете в схватке или других типах проектов. Кроме того, у него есть отличные инструменты для сборки на нескольких платформах, слишком много вещей, чтобы упоминать, что все они бесплатны. Некоторые люди критикуют его, потому что это Microsoft, но он явно превосходит то, что может предложить github с точки зрения инструментов, помимо простого хостинга репозитория. Есть пределы того, что вы можете делать бесплатно, но я редко их превышаю.
Аран Малхолланд
@Marc еще одна вещь, которая мне очень удобна, - это то, что я могу настроить столько учетных записей, сколько хочу, поэтому, если я пишу проект для клиента, который хочет владеть системой управления версиями, я могу создать учетную запись, использовать ее для планирования, разработки и выполнения проекта, и когда я закончу, я могу передать право собственности на учетную запись клиенту.
Аран Малхолланд