Может ли git игнорировать определенную строку?

Я использую git для синхронизации с телефонной связью во время тестирования в родном браузере телефона. Таким образом, у меня есть следующая строка:

var isPhoneGap = false;

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

Я использую Gitx и терминал на OSX 10.6.

Ответ 1

Если ваш файл имеет определенный тип, вы можете объявить фильтр фильтра содержимого, который вы можете объявить в файле .gitattributes (как показано в разделе "Расширение ключевого слова" Git Атрибуты "):

http://git-scm.com/figures/18333fig0702-tn.png

*.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.

Ответ 2

Вы можете использовать

git update-index --assume-unchanged [file]

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

Когда файл имеет важные изменения, вы должны сделать это:

git update-index --no-assume-unchanged [file]

Также см. Git doc update-index для параметра --[no-]assume-unchanged.

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

Ответ 3

Gitx должен позволять вам фиксировать или игнорировать отдельные строки (возможно, вы это уже знаете), но вам придется делать это каждый раз, когда вы совершаете. Я думаю, что было бы лучше иметь конфигурационный файл для каждого целевого объекта развертывания (вы можете его изменить) и некоторый параметр времени выполнения для запуска сервера (например, ./myserver --config=whatever.js).

Ответ 4

Продолжая fooobar.com/questions/57343/..., @Mike, предлагается создать крюк pre-commit, который будет grep в поэтапных файлах для строк, которые можно игнорировать. Крюк проверяет, были ли эти строки поставлены. Если да, то echo предупреждение и exit с кодом 1, поэтому процесс фиксации не будет продолжаться.

Вдохновленный ответом @Mike, я обнаружил, что использовал, возможно, улучшенную версию своего крючка, который автоматически reset (с помощью -p) конкретную строку, которую мы хотим игнорировать.

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

#!/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 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#git-add-patch


ПРИМЕЧАНИЕ. Вышеупомянутый script, предполагающий, что переменная interactive.singleKey равна false. Если вы настроили свой адрес на true, удалите все $'\n' из команды echo сразу после предупреждения.

Ответ 5

Вот как вы можете сделать это с помощью git filters:

  • Создать/Открыть файл gitattributes:
    • < проект root > /. gitattributes (будет передан в репо)
      ИЛИ
    • < project root > /. git/info/attributes (не будет передано в репо)
  • Добавить строку, определяющую файлы для фильтрации:
    • *.rb filter=gitignore, т.е. запустить фильтр с именем gitignore во всех *.rb файлах
  • Определите фильтр gitignore в gitconfig:
    • $ git config --global filter.gitignore.clean "sed '/#gitignore$/'d", т.е. удалите эти строки
    • $ git config --global filter.gitignore.smudge cat, т.е. ничего не делать при извлечении файла из репо

Примечания:
Конечно, это для рубиновых файлов, применяемых, когда линия заканчивается на #gitignore, применяется глобально в ~/.gitconfig. Измените это, как вам нужно для ваших целей.

Внимание!!
Это оставляет ваш рабочий файл отличным от репо (конечно). Любая проверка или перезагрузка будет означать, что эти линии будут потеряны! Этот трюк может показаться бесполезным, поскольку эти строки неоднократно теряются при проверке, переустановке или вытягивании, но у меня есть конкретный вариант использования, чтобы использовать его.

Просто git stash save "proj1-debug", пока фильтр неактивен (просто временно отключите его в gitconfig или что-то в этом роде). Таким образом, мой код отладки всегда может быть git stash apply 'd для моего кода в любое время, не опасаясь, что эти строки будут случайно совершены.

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

Благодаря Rudi и jw013 для упоминания git фильтров и gitattributes.

Ответ 6

Драйвер фильтра содержимого не является хорошим решением. Вы можете скрыть эту строку от git status/etc, но это не игнорируется. Как только вы измените значение, ваш рабочий каталог будет отмечен грязным, хотя изменение может быть не видно.

Если вы действительно хотите, чтобы эта строка не принадлежала системе управления версиями, это может быть единственное практическое средство. Изменение ее в аргументе командной строки или размещение ее в игнорируемом файле include или build.

Ответ 7

Я предполагаю, что это может быть что-то, что появляется в нескольких строках вашего источника.

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

Это может позволить вам настроить макросы препроцессора локально (или для java что-то вроде этого fooobar.com/questions/59574/...).

Ответ 8

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