Чи можу я "git fix" файл і ігнорувати його зміст вмісту?


355

У кожного розробника в моїй команді є своя локальна конфігурація. Ця інформація про конфігурацію зберігається у файлі під назвою, devtargets.rbякий використовується у наших завданнях збору граблів. Хоча я не хочу, щоб розробники прикували один до одного файли девтарських цілей.

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

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

Це можливо? Це, безумовно, буде приємною особливістю ...


1
Дивіться також stackoverflow.com/questions/3318043/… на подібну тему.
VonC


Відповіді:


458

Звичайно, я роблю саме це час від часу, використовуючи

git update-index --assume-unchanged [<file> ...]

Щоб скасувати та почати відстеження ще раз (якщо ви забули, які файли не було вилучено, див. Це питання ):

git update-index --no-assume-unchanged [<file> ...]

Відповідна документація :

- [no-] припустити-не
змінити Коли вказаний цей прапор, імена об'єктів, записані для шляхів, не оновлюються. Натомість ця опція встановлює / знімає біт "припустити незмінний" для шляхів. Коли біт "припустити незмінний" увімкнено, користувач обіцяє не змінювати файл і дозволяє Git припускати, що робочий файл дерева відповідає тому, що записано в індексі. Якщо ви хочете змінити файл робочого дерева, вам потрібно зняти біт, щоб повідомити Git. Іноді це корисно при роботі з великим проектом у файловій системі, що має дуже повільний lstat(2)системний виклик (наприклад, cifs).

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

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

$ git pull
…
From https://github.com/x/y
   72a914a..106a261  master     -> origin/master
Updating 72a914a..106a261
error: Your local changes to the following files would be overwritten by merge:
                filename.ext

і відмовиться від злиття.

Після цього ви можете подолати це, скасувавши місцеві зміни, ось один із способів:

 $ git checkout filename.ext

потім знову потягніть і повторно модифікуйте свій локальний файл, або його можна встановити, –no-assume-unchangedі ви можете зробити звичайний приховування та злиття тощо у цьому пункті.


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

16
@Magus: Ні. Це працюватиме лише для вас.
Роб Вілкерсон

3
І незабаром пізніше ви будете хотіти знати , як визначити , є файл передбачається незмінним: stackoverflow.com/questions/2363197 / ...
Чіро Сантіллі郝海东冠状病六四事件法轮功

10
Зміни у файлах, проігнорованих таким чином, втрачаються, коли використовується "git stash". Чи є шлях до цього?
Олексій

5
Це не для чого git update-index --assume-unchanged. public-inbox.org/git/…
jsageryd

97

Кращим способом цього є використання git update-index --skip-worktree <file>, як пояснено у цій відповіді :

assume-unchangedпризначений для випадків, коли дорого перевірити, чи була змінена група файлів; коли ви встановлюєте біт, git (звичайно) припускає, що файли, відповідні цій частині індексу, не були змінені в робочій копії. Так це дозволяє уникнути безладу статичних дзвінків. Цей біт втрачається щоразу, коли запис файлу в індексі змінюється (наприклад, коли файл змінюється вище).

skip-worktreeнавіть більше: навіть коли git знає, що файл був змінений (або його потрібно змінити шляхом скидання --hard або подібне), він буде робити вигляд, що його не було, використовуючи натомість версію з індексу. Це зберігається, поки індекс не буде відкинутий.

Щоб скасувати це, скористайтеся git update-index --no-skip-worktree <file>

Оскільки версія git 2.25.1, це вже не є рекомендованим способом, цитуючи:

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

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


Чи працює це для всіх користувачів, які оглядають сховище? Вони отримають певні файли, але більше не зможуть додавати зміни помилково, якщо прямо не сказати цього?
ммм

2
@momomo прапор зберігається в індексі, так що ні, це лише для одного користувача. Дивіться відповідь erjiang про те, що працює для всіх користувачів.
1615903

Я намагаюся розібратися, яким повинен бути вміст файлу. Я прокоментував відповідь, про яку ви посилалися, але не отримав відповіді. Де він повинен бути розташований і який у ньому вміст? Чи ти знаєш?
ммм

Я не слідкую. Команда використовується для ігнорування одного конкретного файлу, який ви вказали в команді. Зміст цього файлу не відповідає.
1615903

1
У документації Git конкретно сказано, що не використовувати git update-index --skip-worktreeдля цієї мети.
bk2204

43

Звичайна практика полягає в тому, щоб створити devtargets.default.rbта скористатися ним, а потім доручити кожному користувачу скопіювати цей файл devtargets.rb(який знаходиться у списку .gitignore). Наприклад, CakePHP робить те ж саме для свого файлу конфігурації бази даних, який природно змінюється від машини до машини.


6
Ви не можете .gitignored файл, який відслідковується. .gitignore впливає лише на файли, які не входять до індексу.
CB Bailey

1
я намагався уникати цього, хоча у мене справді немає вагомих причин. ми це робимо зараз, і я думаю, що це болісно пам’ятати, що мені потрібно створити власну версію без «.default» в імені.
Дерик Бейлі

11
@DerickBailey Але, якщо чесно, легше запам’ятати скопіювати файл, ніж запам'ятати, використовуючи --assume-unchangedпараметр для всіх, хто клонує сховище.
Dan

1
@DerickBailey ви також можете встановити збірку граблів за замовчуванням, devtargets.default.rbякщо її devtargets.rbнемає.
Лука

@erjang що в цьому файлі devtargets.default.rb? Приклад?
ммм

2

Для користувачів IntelliJ IDEA: Якщо ви хочете ігнорувати зміни у файлі (або файлах), ви можете перемістити його до іншого Change Set.

  • Перейдіть до Local Changes( Cmd + 9)
  • Виберіть файли, які ви хочете проігнорувати
  • F6 щоб перемістити їх до іншого Change Set
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.