Сохранять git - файлы без изменений между проверками веток

Я использовал git --assume-unchanged yacs/settings/development.py, чтобы игнорировать мой локальный файл конфигурации базы данных в моей ветке dev. Но когда я хочу переключать ветки (для развертываний), я получаю сообщение об ошибке, что у меня все еще есть изменения:

% git checkout production
error: Your local changes to the following files would be overwritten by checkout:
    yacs/settings/development.py
Please, commit your changes or stash them before you can switch branches.
Aborting

Это раздражает. Единственный способ, которым я знаю, как обойти это, - это спрятать его:

% git stash
% git checkout production
% git merge dev
% ./deploy.sh
% git checkout dev
% git stash pop
# On branch dev
# 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:   yacs/settings/development.py
#

Но теперь он снова возвращается в индекс (тьфу)! Есть ли лучшая альтернатива этому документообороту?

[Мне неинтересно, что локальные изменения остаются локально (ака, это нормально, если это производственная ветка), я просто не хочу, чтобы это было перенесено в удаленный репозиторий.]

Ответ 1

Вы можете попробовать (справочная страница git update-index):

git update-index --skip-worktree -- path

Бит Skip-worktree может быть определен в одном (длинном) предложении: если при чтении записи он помечается как skip-worktree, то Git делает вид, что версия его рабочего каталога актуальна, и вместо этого читает индексную версию.

Однако, как упоминалось в "git предположить, что оно не изменилось по сравнению с пропуском рабочего дерева":

У обоих вариантов есть проблемы. --assume-unchanged сбрасывает себя всякий раз, когда индекс сбрасывается (например, git reset), так что, вероятно, вы рано или поздно сбиваете с толку. То же самое касается --skip-worktree.


Кроме того, обязательно используйте Git 2.24 (4 квартал 2014 года).
С 2012 года (вопрос OP) git stash был портирован на C (он больше не является сценарием оболочки), но ему пришлось (в его новой реализации) (re-) научиться записывать обновленный индекс обратно на диск.

См. коммит 34933d0 (11 сентября 2019 г.) от Томаса Гаммерера (tgummerer).
(Merged by Thomas Gummerer -- [TG45] -- in commit 34933d0, 20 Sep 2019)

stash: убедитесь, что записали обновленный кеш

При преобразовании stash в C вызывает 'git update-index --refresh' были заменены функцией 'refresh_cache()'.
Это нормально, если индекс нужен только для ядра, а не для чтения re- с диска.

Однако во многих случаях нам действительно нужно записать обновленный индекс на диск, например, "merge_recursive_generic()" сбрасывает внутренний индекс перед чтением re- его с диска, а в случае "apply --quiet", "refresh_cache()", который у нас есть в данный момент, бессмысленно без записи индекса на диск.

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

Ответ 2

То, что я начал делать, это создать ветку от мастера, называемую private, которая имеет мои локальные изменения; подумайте об этом как о прокси-ветке между моей рабочей веткой и мастером. Я могу переустановить мою текущую ветку работы на частную, когда мне нужны мои локальные изменения, и у меня есть несколько псевдонимов в моем .gitconfig, которые автоматизируют хранение личных данных с мастером. Когда мне нужно объединиться для освоения, мои псевдонимы обязательно переконфигурируют - сначала откройте мою рабочую ветвь.

Я разместил запись в блоге об этом более подробно здесь http://blog.ericwoodruff.me/2013/02/git-private-branch-pattern.html

Ответ 3

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

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

Один предлагаемый способ обхода выше, это добавить файл в your_repo/.git/info/exclude. Но я не хотел добавлять файл в список исключений, поэтому я сделал следующее из моего рабочего каталога:

  • cp <local-only_file> ~/
    • копировать файл с локальными изменениями в безопасном месте в файловой системе
  • git checkout <local-only_file>
    • в рабочем дереве, файл checkout, чтобы он соответствовал файлу master branch
  • git update-index --skip-worktree -- <local-only_file>
  • cp ~/<local-only_file> .
    • копировать файл под вопросом из безопасного места обратно в рабочее дерево
  • git diff
    • Никакие изменения не должны отображаться; если вы нажмете на основное репо, никакие изменения в <local-only_file> не включены в push

Ответ 4

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