Чи може Git ігнорувати певний рядок?


114

Я використовую git для синхронізації з фонегапом під час тестування у рідному браузері телефону. Як такий у мене є такий рядок:

var isPhoneGap = false;

Очевидно, що я змінюю це під час побудови, але чи є спосіб встановити git, щоб ігнорувати цей один рядок або мені потрібно перейти і вкласти його у свій власний файл та ігнорувати його таким чином?

Я використовую Gitx і термінал на OSX 10.6.


@ User494461: Git фільтри це спосіб зробити це: stackoverflow.com/a/16244970/520162
Екес

1
Ви не можете виявити навколишнє середовище та використовувати файл конфігурації eniroment?
exussum

Коротше кажучи: Ні. Але я написав препроцесорний скрипт, який шукає певний коментований код і видаляє його перед публікацією до git. Перевірте це тут: github.com/franklinchou/ahk_config/blob/master/preprocess.sh
франклін

Відповіді:


103

Якщо ваш файл певного типу, ви можете оголосити драйвер фільтра вмісту , який ви можете оголосити у .gitattributesфайлі (як це представлено у розділі "Розширення ключових слів" у " Git Attributes "):

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.


1
Дякую за це спрацював. Чи знаєте ви, як зробити git diff or статус git`, ігноруйте фільтри? Тож я все ще бачу, що відрізняється? Мій випадок використання - це журнали налагодження ... які в кінцевому підсумку я хочу видалити ... @jthill @VonC
timh

1
@timh, якщо фільтр працює, статус git або git diff нічого не повинен показувати.
VonC

1
Шкода, що немає більш простого способу в GIT. git ignore <ім'я файлу> <лінійний номер> було б дуже зручно!
kiedysktos

22
@kiedysktos linenumber? Що робити, якщо номер рядка зміниться?
VonC

Це спрацювало чудово, але користувачі Windows будьте обережні, gitconfig дуже прискіпливий до того, які символи він хоче вмістити, тому при спробі деяких напівекзотичних регулярних виразів ви можете зіткнутися з проблемою. Я в кінцевому підсумку помістив свої sed-дзвінки в окремий файл helper.sh, який я зателефонував зі свого gitconfig, sh ".git/helper.sh"переконуючись, що через будь-які параметри sed потрібно перейти "$@"(я припускаю, що просто пройшов шлях файлу ).
ohaal

43

Можна використовувати

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

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

Коли у файлі є важливі зміни, ви повинні зробити це:

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

Також дивіться параметр оновлення Git doc для --[no-]assume-unchangedпараметра.

Коли вказані ці прапори, імена об'єктів, записані для шляхів, не оновлюються. Натомість ці параметри встановлюють та скасовують біт "припустити незмінний" для шляхів. Коли біт "припустити незмінний" увімкнено, git припиняє перевірку файлів робочого дерева на наявність можливих модифікацій, тому вам потрібно вручну зняти біт, щоб повідомити git при зміні файла робочого дерева.


2
Чи все одно я отримаю нову версію, коли я виконую git pull?
Саад Рехман Шах

1
@Caffeine, коли ви затягуєте git, ви отримуєте останню версію, яку було зафіксовано, це буде останньою, перш ніж ви перейдете на файл "--umeume-unchanged".
Карлос

1
Я вважаю --skip-worktree, що це кращий варіант для більшості цілей. stackoverflow.com/a/39583010/4233593
Джефф Пукетт


3
це ігнорує оновлення до всього файлу, а не конкретного рядка
nikoss

6

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


5

Продовжуючи https://stackoverflow.com/a/20574486/4935114 , @Mike запропонував створити pre-commitгачок, який буде grepу поступових файлах для рядків, які можна захотіти ігнорувати. Гачок перевіряє, чи були виконані ці лінії. Якщо це так, воно echoпопереджає і це exitз кодом, 1тому процес фіксації не триватиме.

Натхненний відповіддю @ Майка , я опинився, використовуючи, можливо, вдосконалену версію його гака, яка автоматично 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#git-add-patch


ПРИМІТКА. Наведений вище сценарій, припускаючи, що змінна interactive.singleKeyє false. Якщо ви налаштували своє true, видаліть будь-яку $'\n'з echoкоманди відразу після попередження.


3

Ось як це можна зробити з фільтрами git :

  1. Створити / відкрити файл gitattributes:
    • <root root> /. gitattributes (буде здійснено в репо)
      АБО
    • <корінь проекту / /. git / info / атрибути (не буде введено в репо)
  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"d" до мого коду в будь-який час, не побоюючись, що ці рядки будуть випадково скоєні.

У мене є можлива ідея для вирішення цих проблем, але я спробую втілити її в інший раз.

Дякуємо Rudi та jw013 за те, що вони згадували фільтри git та gitattributes.


2

Драйвер фільтру вмісту - не гарне рішення. Ви можете приховати цей рядок від git status/ etc, але він насправді не ігнорується. Як тільки ви зміните значення, ваш робочий каталог буде позначений брудним, навіть якщо зміна може бути не видно.

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


"Щойно ви зміните значення, ваш робочий каталог буде позначений брудним, навіть якщо зміна може бути не видно": це не повинно, якщо чистий скрипт все-таки відновить файл у його початковому вмісті.
VonC

Ось що я думав. Я використовую GitExtensions, і він покаже файл як змінений навіть через те, що роздільна панель порожня. Можливо тому, що чистий фільтр не запускається до реєстрації файлів. Можливо тому, що це msysgit, а не git-git. ІДК, YMMV
patricktokeeffe

1

Я здогадуюсь, що це може бути щось, що з’являється у кількох рядках вашого джерела.

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

Це може дозволити локальну настройку макросів препроцесора (або для Java щось подібне https://stackoverflow.com/a/1813873/1270965 ).


-1

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


Я погоджуюся, в моєму випадку було достатньо і можна було просто включити цей вміст із ігнорованого файлу. Тож переміщення всіх невідомих налаштувань. там. Крім того, я створив копію цього ігнорованого файлу і додав його до індексу як посилання, тому інформація про те, що має бути у цьому файлі, не буде втрачена.
Urs
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.