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

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

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

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

Обобщить,

  1. Я хотел бы создать файл, назовите его default_values.txt, который добавляется в мой репозиторий git и включается, когда кто-то клонирует этот репозиторий.
  2. git add . не должен добавлять default_values.txt к коммиту.
  3. Это поведение должно передаваться любым клонам репозитория.

person Marc    schedule 03.12.2010    source источник
comment
Можете ли вы использовать git-хуки, чтобы иметь хук перед фиксацией, который прервал бы фиксацию, если измененный файл default_values.txt (скажем)?   -  person sateesh    schedule 03.12.2010
comment
Сторонники чистоты Git скажут, что не ленитесь и правильно используйте промежуточную область, для этого она и предназначена.   -  person Xint0    schedule 03.12.2010
comment
Сторонники чистоты Git сказали бы, что используйте скрипты smudge/clean. Это самое ремонтопригодное решение.   -  person Adam Dymitruk    schedule 27.01.2011
comment
Xинт0: правда. но как предотвратить случайную регистрацию других людей?   -  person Alan    schedule 09.01.2014
comment
возможный дубликат фиксации файлов конфигурации для конкретной машины   -  person Senseful    schedule 03.09.2014
comment
смешной. второй по количеству голосов ответ имеет комментарий от OP, в котором говорится, что они не приняты, потому что вы не можете передать поведение другим клонам, но тогда принятый ответ имеет точно такую ​​​​же команду - и проблему.   -  person igorsantos07    schedule 30.12.2020


Ответы (7)


Как уже упоминалось многими другими, хорошим современным решением является:

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 будет потерян, как только будет извлечено изменение вышестоящего уровня.

person moodboom    schedule 29.09.2016
comment
Если кто-то еще вытащит репозиторий и отредактирует файл, игнорируются ли изменения в его каталоге? Я надеюсь, что им придется ввести --no-skip-worktree, чтобы добавить свои изменения. - person neaumusic; 08.12.2017
comment
То, что делается с их изменениями, контролируется ими. Другими словами, им придется установить skip-worktree для файла в своем репо, если они не хотят, чтобы их изменения были отправлены. Если это файл, предназначенный для отправки всем, а затем игнорирующий все последующие изменения, всем придется следовать этим же инструкциям. - person moodboom; 09.12.2017
comment
Обратите внимание, что вам, возможно, придется отменить статус файла --skip-worktree, прежде чем вы сможете переключать ветки, если этот же файл отслеживается в другой ветке. - person moodboom; 07.12.2018
comment
хм, работает... после внесения изменений в файл он не отображался в 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. - person ykravv; 28.11.2019
comment
@ykravch да, как я упоминал в предыдущем комментарии, статус --skip-worktree может мешать при переключении ветвей, и в этом случае вам, возможно, придется отменить статус --skip-worktree. Какая-то боль. - person moodboom; 01.12.2019
comment
У меня есть псевдонимы git ignore и git unignore. - person Michael; 09.01.2020
comment
Могу ли я сделать это, но сохранить это состояние на удаленном компьютере, чтобы другие разработчики случайно не зафиксировали изменения в неотслеживаемом файле, поскольку они забыли сделать --skip-worktree - person theonlygusti; 11.07.2020
comment
@theonlygusti --skip-worktree — это функциональность клиента. На стороне сервера, если у ваших разработчиков есть права на запись, трудно запретить им делать то, что они хотят. Вы можете попросить разработчиков добавить хук pre-commit или pre-push в свой репозиторий .git/hooks/, который будет проверять наличие изменений в этом файле и, если они будут обнаружены, запретить фиксацию/push. Вы все еще полагаетесь на то, что ваши разработчики правильно используют хук, но, возможно, в вашем случае этого достаточно. Вот пример. - person moodboom; 18.07.2020
comment
@moodboom Меня не волнует запрет, я просто хочу предотвратить несчастные случаи. Я знаю, что соответствующий файл будет обновлен точно, но я также знаю, что в 99% случаев обновления должны быть только на их локальной машине и не затрагивать центральный репозиторий, которым все пользуются. - person theonlygusti; 18.07.2020
comment
@theonlygusti в этом случае крючок должен предотвращать несчастные случаи. Попросите их установить его, когда они настроят свои локальные репозитории. - person moodboom; 18.07.2020

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

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

person tamasd    schedule 03.12.2010
comment
это не работает. хотя это заставляет git добавить . игнорировать файл на локальной ветке, клон архива не имеет такого поведения (если вы измените default_values.txt в клонированном архиве, он будет добавлен в коммит с помощью git add .) - person Marc; 04.12.2010
comment
Да, потому что вы устанавливаете его только для локального репо. Вы не можете продвигать такого рода информацию. - person tamasd; 04.12.2010
comment
@Indradhanush - это решение не удовлетворяет критерию 3 - поведение должно быть передано любым клонам репозитория - поэтому я его не принял. Это не значит, что это плохой ответ. - person Marc; 08.09.2014
comment
Я никогда не замечал 3-й критерий. Потому что я не искал его. :) - person Indradhanush Gupta; 08.09.2014
comment
Для локальных файлов конфигурации с настройками частного приложения вы, вероятно, захотите использовать skip-worktree вместо assume-unchanged. -worktree" title="Разница git между предположением о неизменности и пропуском рабочего дерева"> stackoverflow.com/questions/13630849/ - person Aaron Hoffman; 11.12.2015
comment
Я предпочитаю этот ответ в большинстве случаев, так как это означает, что вы никогда не пропустите изменения в восходящем направлении. - person DrCord; 21.05.2021

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

person Laurence Gonsalves    schedule 03.12.2010
comment
хм... может быть, я мог бы написать хук для автоматического копирования default_values_template в default_values, если default_values ​​не существует? - person Marc; 03.12.2010
comment
Это самый распространенный способ решить эту проблему по моему опыту. Это в значительной степени путь наименьшего сопротивления в том смысле, что он просто работает, и вы можете легко заставить свой код проверять, существует ли локальный файл конфигурации, и предоставлять полезную ошибку, если это не так. - person Jani Hartikainen; 03.12.2010
comment
Я думаю, что решение действительно состоит в том, чтобы сделать что-то подобное, желательно со сценарием, выполняемым всякий раз, когда вы извлекаете или клонируете. Одна из идей заключается в том, что все, что имеет определенное расширение (скажем, .basefile), копируется в файл с удаленным расширением, а затем имя файла добавляется в .gitignore в этом каталоге. Поэтому я бы создал файл default_values.txt.basefile и зафиксировал его. У меня нет навыков git или perl, чтобы сделать это, но я спрошу друга, у которого есть, и дам вам знать, как это работает. - person Marc; 04.12.2010
comment
За это проголосовали, потому что для этого были созданы чистые и нечеткие сценарии. - person Adam Dymitruk; 09.12.2010
comment
@AdamDymitruk: Да, в этом случае можно использовать очистку / размазывание, но далеко не ясно, является ли это лучшим вариантом. Например, это будет довольно сложно, если люди действительно захотят изменить файл, так как очистка/размазывание будут мешать. На самом деле я бы предпочел подход, описанный здесь. - person sleske; 31.08.2013
comment
Что касается людей, которые могут забыть скопировать файл: обычно default_values.txt создается как часть (локального) процесса сборки любым инструментом сборки, который вы используете. Инструмент может даже проверять default_values_template.txt на наличие изменений и объединять их в default_values.txt. - person sleske; 15.11.2013
comment
Это невозможно для проектов, где файлы должны быть добавлены в решение. Например. класс констант в C#. Если я поручу пользователям переименовать файл и добавить его в проект, добавление приведет к изменению файла *.csproj, который затем будет проверен. - person ganeshran; 25.02.2015
comment
Я беру пример с самого git (в частности, git hooks) и использую суффикс .sample. Итак, в вашем случае default_values.txt.sample - person tir38; 03.04.2020

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

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

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

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

person Adam Dymitruk    schedule 03.12.2010
comment
Являются ли скрипты Clean и Smudge локальными или частью репозитория? - person Alan; 09.01.2014
comment
да. :) ... то есть вы можете поделиться чистыми пятнами через репо, но это не очень хорошая идея, когда они содержат конфиденциальные данные, такие как производственные пароли. Если это не проблема, git требует, чтобы вы явно включили скрипт. В противном случае люди могли бы совершать вредоносные действия через github и другие общие репозитории с другими пользователями. - person Adam Dymitruk; 10.01.2014
comment
Мне нужно прочитать немного больше об этом. По сути, я хочу настроить проект со значением по умолчанию user.json, которое необходимо перезаписать с помощью кредитов каждого разработчика, но я не хочу, чтобы разработчик случайно проверил свои кредиты. - person Alan; 10.01.2014
comment
Я бы погуглил, чтобы найти примеры сценариев для чистых пятен. Посмотрите, что получится. Кроме того, прыгайте в комнату git irc на freenode. Вы получите помощь немедленно. - person Adam Dymitruk; 10.01.2014

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

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

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

person Haddon CD.    schedule 20.05.2013
comment
почти понятно. Почему, если вы добавили фильтр к определенному пути в .gitattributes, вам нужно указать файл, с которым нужно действовать, в команде «отменить изменения»? почему эта команда не работает с любым файлом, который вы передали? например, если в .gitattributes вы указали */ProjectSettings.asset в качестве рассматриваемого файла с примененным фильтром, фильтр должен иметь возможность работать с ЛЮБЫМ файлом в репозитории! Как это сделать? - person eric frazer; 04.02.2021

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

person fruitcoder    schedule 24.04.2018

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

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