Может ли git игнорировать конкретную строку? - PullRequest
86 голосов
/ 02 июля 2011

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

var isPhoneGap = false;

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

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

Ответы [ 8 ]

81 голосов
/ 04 марта 2014

Если ваш файл имеет определенный тип, вы можете объявить драйвер фильтра содержимого , который вы можете объявить в файле .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.

35 голосов
/ 11 июля 2012

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

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

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

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

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

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

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

6 голосов
/ 02 июля 2011

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

4 голосов
/ 05 сентября 2017

Продолжение https://stackoverflow.com/a/20574486/4935114, @ Майк предложил создать pre-commit хук, который будет grep в промежуточных файлах для строк, которые можно игнорировать.Хук проверяет, были ли эти строки поставлены.Если это так, то это echo предупреждение и exit с кодом 1, поэтому процесс фиксации не будет продолжаться.

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

Я не уверен в этомhook будет работать для ситуации, когда у вас есть много файлов с этой строкой, которые нужно игнорировать, но эта 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 # git-add-patch


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

3 голосов
/ 27 апреля 2013

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

  1. Создать / открыть файл атрибутов gitattributes:
    • /.gitattributes (будет совершено в репо)
      ИЛИ
    • /.git/info/attributes (не будет передан в репо)
  2. Добавить строку, определяющую файлы для фильтрации:
    • *.rb filter=gitignore, т.е. выполнитьфильтр с именем gitignore для всех *.rb файлов
  3. Определите фильтр 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 для моего кода в любое время, не опасаясь, что эти строки будут случайно зафиксированы.

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

Спасибо Rudi и jw013 за упоминание фильтров git и атрибутов gitatributes.

2 голосов
/ 28 мая 2014

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

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

1 голос
/ 07 марта 2014

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

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

Это может позволить вам настроить макросы препроцессора локально (или для java что-то вроде этого https://stackoverflow.com/a/1813873/1270965).

0 голосов
/ 03 июля 2011

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

...