Как запретить git совершать указанный c набор локальных изменений - PullRequest
1 голос
/ 05 марта 2020

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

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

Есть ли способ сказать git (или, может быть, Visual Studio Code / Spacemacs) это?

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

Спасибо!

1 Ответ

1 голос
/ 05 марта 2020

Основным механизмом, встроенным в Git, который может здесь помочь, является использование грязных и чистых фильтров. См. Вопросы и ответы, которые ElpieKay связал в комментарии , git пятно / чистый фильтр между ветвями , или перейдите непосредственно к ответу Von C здесь .

Ваши грязные и чистые фильтры могут делать все что угодно: это просто текстовые фильтры общего назначения.

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

  • Когда Git копирует файл из вашего рабочего дерева в индекс, он пропускает текст через чистое фильтр. Очищенный текст - это то, что появится в индексной копии файла. 1 Индексная копия файла - это та, которая будет зафиксирована.

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

В файле .gitattributes указывается, какие файлы будут проходить через какие фильтры, и Ваш основной файл .git/config или ~/.gitconfig описывает доступные программы фильтрации.

Альтернативный механизм, который, вероятно, не подходит для вашего конкретного случая, заключается в том, что после извлечения файлов из некоторого коммита как в индекс, так и в ваш Рабочее дерево, т. е. после некоторого начального git checkout, вы можете использовать git update-index для особой пометки индексной копии файла. С этого момента Git операций, которые будут сравнивать копию индекса и копию рабочего дерева в основном просто , предполагают , что копия индекса правильная и соответствует копия рабочего дерева.

Флаги, которые вы можете установить здесь, называются , предполагают неизменными и пропуск рабочего дерева . Чтобы установить один такой флаг, вы должны использовать git update-index --skip-worktree <em>path</em>. Два флага в основном делают одно и то же, но их внутренние цели различны: предположить, что без изменений предназначен для систем, в которых lstat вызовы очень медленные, чтобы пропустить их, а skip-worktree предназначен для функции разреженного извлечения. Если вы на самом деле используете разреженную проверку, Git будет включать и выключать эти биты сам, поэтому вы захотите использовать другой флаг. В противном случае, общая рекомендация - использовать флаг skip-worktree (но на практике оба фактически работают одинаково).

Обратите внимание, что после установки одного из этих флагов тот факт, что вы сделали это, в значительной степени невидимый. 2 Вы должны помнить, что вы это сделали. Если вы забудете, это приведет к крайне странному поведению. Использование этих битов таким способом довольно болезненно, потому что Git требует замены индексной копии файла - например, при переключении на коммит, чья копия файла не соответствует копия, загруженная в данный момент в ваш индекс - Git нужно перезаписать копию индекса, что означает, что Git также хочет перезаписать копию рабочего дерева. Если флаг установлен и копия рабочего дерева существует и не соответствует копии индекса, Git откажется продолжить. Чтобы заставить Git продолжить, вам, как правило, нужно отключить флаг , как-то обработать файл, переключить коммиты, снова обработать файл, снова включить флаг , и возобновить работу.


1"Копия" файла в индексе на самом деле является копией в хранилище в виде большого двоичного объекта объект. Индекс содержит ссылку на объект blob. Если и когда вы делаете новый коммит, новый коммит содержит ссылку на этот же объект BLOB-объекта (через объект дерева). Когда вы запускаете git add, Git очищает файл, создает временный объект блоба из результата, находит его блоб ha sh ID и выясняет, существует ли объект уже. Если объект уже существует, git add в основном готово: все, что нам нужно, это его ha sh ID, и это входит в индекс. Если объект не существует, git add помещает объект в базу данных объектов, и теперь все готово: идентификатор ha sh нового объекта входит в индекс.

Это означает, что когда вы git add файл несколько раз перед фиксацией, вы можете создать мусор: неиспользованный BLOB-объект. В конечном итоге мусор будет вычищен через Git git gc. Git создает мусорные объекты все время самостоятельно, так что вам не нужно об этом беспокоиться. Исключением из этого правила является случайное добавление огромного файла, например, файла размером 500 ГБ. По умолчанию этот мусорный объект будет сохраняться как минимум две недели, занимая при этом заметное количество дискового пространства.

2 Я написал скрипт, git-flagged, найти (и при необходимости снять флажок) мои файлы. Иногда я оказываюсь в досадной ситуации, когда мне приходится помечать некоторые файлы с помощью skip-worktree на некоторое время и вспоминать, где они были болезненными, отсюда и сценарий. Теперь я могу запустить git flagged, чтобы их было легче увидеть.

...