Может ли git игнорировать конкретную строку?
Я использую Git для синхронизации с PhoneGap во время тестирования на родном браузере телефона. Таким образом, у меня есть следующая строка:
var isPhoneGap = false;
Очевидно, я изменяю это при сборке, но есть ли способ настроить git, чтобы игнорировать эту строку или мне нужно пойти и поместить его в свой собственный файл и игнорировать таким образом?
Я использую Gitx и терминал на OSX 10.6.
9 ответов
Если ваш файл имеет определенный тип, вы можете объявить драйвер фильтра содержимого, который вы можете объявить в .gitattributes
файл (как представлено в "Расширении ключевых слов" в " Атрибутах Git"):
*.yourType filter=yourFilterName
(вы можете даже установить этот фильтр для определенного файла, если хотите)
Воплощать в жизнь:
yourFilterName.smudge
(срабатывает наgit checkout
) а такжеgit config --global filter.yourFilterName.smudge 'sed "s/isPhoneGap = .*/isPhoneGap = true/"'
yourFilterName.clean
(срабатывает наgit add
)git config --global filter.yourFilterName.clean 'sed "s/isPhoneGap = .*/isPhoneGap = false/"'
Ваш файл будет отображаться без изменений git status
, но его проверенная версия будет иметь правильное значение для isPhoneGap
,
Ты можешь использовать
git update-index --assume-unchanged [file]
игнорировать изменения одного файла, который вы не хотите отслеживать. Я использую это решение, когда мне нужен файл в хранилище, но в этом файле есть некоторые части, которые меняются, и мне не всегда нужно отслеживать.
Когда в файле есть важные изменения, вы должны сделать это:
git update-index --no-assume-unchanged [file]
Также см. Git doc update-index для --[no-]assume-unchanged
параметр.
Когда эти флаги указаны, имена объектов, записанные для путей, не обновляются. Вместо этого эти опции устанавливают и сбрасывают бит "предположить, что он не изменен" для путей. Когда бит "предположить, что без изменений" включен, git перестает проверять файлы рабочего дерева на предмет возможных изменений, поэтому вам нужно вручную сбросить бит, чтобы сообщить git, когда вы изменяете файл рабочего дерева.
Продолжая /questions/21741805/kak-skazat-git-ignorirovat-otdelnyie-stroki-te-gitignore-dlya-opredelennyih-strok-koda/21741819#21741819, Mike предложил создать pre-commit
крюк, который будет grep
в готовых файлах для строк, которые можно игнорировать. Хук проверяет, были ли эти строки поставлены. Если так, то это echo
предупреждение и это exit
с кодом 1
поэтому процесс фиксации не будет продолжаться.
Вдохновленный ответом @ Mike, я обнаружил, что использую, возможно, улучшенную версию его хука, которая автоматически reset
с (с -p
флаг) конкретная строка, которую мы хотим игнорировать.
Я не уверен, что этот хук будет работать для ситуации, когда у вас есть много файлов с этой строкой, которые нужно игнорировать, но это pre-commit
ловушка ищет изменения в этой строке в конкретном файле buildVars.java
, Скрипт хука выглядел так, когда я тестировал его на своей машине.
#!/bin/sh
# this hook looks for lines with the text `var isPhoneGap = false;` in the file `buildVars.java` and it resets these lines to the previous state before staged with `reset -p`
if [[ $(git diff --no-ext-diff --cached buildVars.java | grep --count -e "var\ isPhoneGap[\ ]*=[\ ]*") -ne 0 ]]; then
cat <<EOW
WARNING: You are attempting to commit changes which are not supposed to be commited according to this \`pre-commit\` hook
This \`pre-commit\` hook will reset all the files containing this line to it's previous state in the last commit.
EOW
echo /$'\n'isPhoneGap$'\n'y$'\n'q | git reset -p
# BONUS: Check if after reseting, there is no actual changes to be commited and if so, exit 1 so the commit process will abort.
if [[ $(git diff --no-ext-diff --cached | wc -l) -eq 0 ]]; then
echo there are no actual changes to be commited and besides the change to the variable \'isPhoneGap\' so I won\'t commit.
exit 1
fi
fi
объяснение
То, что я сделал, повторило контрольные последовательности, которые ищут регулярное выражение isPhoneGap
во время интерактивного reset
процесс. Таким образом, подражая пользователю, который нажимает /
искать isPhoneGap
, прессы y
когда его спросили, хочет ли он отказаться от этого патча и наконец нажимает q
выйти из интерактива reset
,
Интерактивный процесс обратного исправления описан здесь: https://git-scm.com/docs/git-add
ПРИМЕЧАНИЕ: приведенный выше скрипт предполагает, что переменная interactive.singleKey
является false
, Если вы настроили свой на true
удалить любой $'\n'
от echo
Команда сразу после предупреждения.
Gitx должен позволять вам фиксировать или игнорировать отдельные строки (вы, возможно, уже знаете это), но вам придется делать это каждый раз, когда вы фиксируете. Я думаю, что было бы лучше иметь конфигурационный файл для каждой цели развертывания (вы можете установить версию) и некоторый параметр времени выполнения для того, как вы запускаете сервер (например, ./myserver --config=whatever.js
).
Вот как вы можете сделать это с помощью фильтров git:
- Создать / открыть файл gitattributes:
- <корень проекта>/. gitattributes (будет передан в репо)
ИЛИ ЖЕ - <корень проекта>/.git/info/attribute (не будет передан в репо)
- <корень проекта>/. gitattributes (будет передан в репо)
- Добавьте строку, определяющую файлы для фильтрации:
*.rb filter=gitignore
, т.е. запустить фильтр с именемgitignore
на все*.rb
файлы
- Определите
gitignore
фильтр в вашемgitconfig
:$ git config --global filter.gitignore.clean "sed '/#gitignore$/'d"
удалить эти строки$ git config --global filter.gitignore.smudge cat
ничего не делать при извлечении файла из репо
Заметки:
Конечно, это для файлов ruby, применяемых, когда строка заканчивается #gitignore
применяется глобально в ~/.gitconfig
, Измените это так, как вам нужно для ваших целей.
Предупреждение!!
Это оставляет ваш рабочий файл отличным от репо (конечно). Любая проверка или перебазировка будет означать, что эти строки будут потеряны! Этот трюк может показаться бесполезным, поскольку эти строки многократно теряются при проверке, перебазировании или вытягивании, но у меня есть конкретный вариант использования, чтобы использовать его.
Просто git stash save "proj1-debug"
пока фильтр неактивен (просто временно отключите его в gitconfig
или что-то). Таким образом, мой код отладки всегда может быть git stash apply
в мой код в любое время, не опасаясь, что эти строки будут случайно зафиксированы.
У меня есть возможная идея для решения этих проблем, но я попробую реализовать ее в другой раз.
Спасибо Руди и jw013 за упоминание фильтров git и атрибутов gitatributes.
Я думаю, что никто не предоставил такой способ решения проблемы, поэтому вот мой метод. Я продолжаю регистрировать / отлаживать и т. Д. В одной ревизии (на самом деле, их может быть несколько) в частной ветке в моем локальном репо. Итак, когда я запускаю функциональную ветку и хочу иметь все мои вкусности (в
git checkout my-feature
git cherry-pick my-feature..my-goodies # assuming both started from the same main branch, say, my-goodies started a few (or many) revisions back
Теперь я начинаю работать над этой функцией. Когда я закончу, я переписываю историю ветки функций, чтобы эти изменения исчезли:
git rebase -i @{u} # set all the goodies revisions to skip, save, and go
Теперь моя ветка чиста от всех моих вкусностей, и я могу пихать куда угодно.
Драйвер фильтра содержимого не является хорошим решением. Вы можете скрыть эту строку от git status
/etc, но на самом деле это не игнорируется. Как только вы измените значение, ваш рабочий каталог будет помечен как грязный, даже если изменение может быть невидимым.
Если вы действительно хотите, чтобы эта строка вышла из-под контроля версий, единственным практическим средством может быть ее изменение на аргумент командной строки или помещение ее в игнорируемый файл включения или сборки.
Я предполагаю, что это может быть связано с более чем одной строкой вашего источника.
Я думаю, что было бы самым чистым иметь какой-то файл.userbuildconfig, который вы просто включили и отметили значения по умолчанию. Тогда вы можете использовать предложение Карлоса, чтобы пометить этот файл как предполагаемый неизменным. Таким образом, другие изменения в файле, где вы должны проверить настройки, не будут пропущены.
Это может позволить вам настроить макросы препроцессора локально (или для java что-то вроде этого /questions/36518181/ifdefifndef-v-java/36518201#36518201).
Нету. Вы можете игнорировать только отдельные файлы (и более), поскольку строки в.gitignore соответствуют именам файлов, а не их содержимому. Вы уже упоминали решение этой проблемы, то есть игнорируйте один файл, содержащий содержимое, которое вы хотите игнорировать.