Добавить только изменения без пробелов
У меня есть текстовый редактор для автоматической обрезки конечных пробелов при сохранении файла, и я участвую в проекте с открытым исходным кодом, у которого есть серьезные проблемы с конечными пробелами.
Каждый раз, когда я пытаюсь представить патч, я должен сначала игнорировать все изменения только пробелов вручную, чтобы выбрать только соответствующую информацию. Не только это, но когда я бегу git rebase
Я обычно сталкиваюсь с несколькими проблемами из-за них.
Поэтому я хотел бы иметь возможность добавлять в индекс только непробельные изменения, аналогично git add -p
делает, но без необходимости выбирать все изменения самостоятельно.
Кто-нибудь знает как это сделать?
РЕДАКТИРОВАТЬ: Я не могу изменить способ работы проекта, и они решили, обсудив его в списке рассылки, игнорировать это.
12 ответов
Решение @Frew было не совсем тем, что мне было нужно, так что это псевдоним, который я сделал для той же проблемы:
alias.addnw=!sh -c 'git diff -U0 -w --no-color "$@" | git apply --cached --ignore-whitespace --unidiff-zero -'
Или вы можете просто запустить:
git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero -
Обновить
Добавлены опции -U0
, а также --unidiff-zero
в соответствии с решением проблем соответствия контекста, в соответствии с этим комментарием.
В основном это применяет патч, который будет применяться с add
без пробелов. Вы заметите, что после git addnw your/file
все еще будут неустановленные изменения, это оставленные пробелы.
--No-color не требуется, но так как у меня установлены цвета всегда, я должен его использовать. Во всяком случае, лучше, чем потом сожалеть.
Создайте файл исправления, содержащий только реальные изменения (исключая строки только с изменениями пробелов), затем очистите рабочее пространство и примените этот файл исправления:
git diff> резервное копирование
git diff -w > изменения
git reset --hard
патч <изменения
Просмотрите оставшиеся различия, затем add
а также commit
как обычно.
Эквивалентом Mercurial является следующее:
hg diff> резервное копирование
hg diff -w > изменения
HG Revert - Все
hg import --no-commit изменения
Это работает для меня:
Если вы хотите сохранить тайник вокруг, это работает
git stash && git stash apply && git diff -w > foo.patch && git checkout . && git apply foo.patch && rm foo.patch
Мне не нравятся тайники, но я столкнулся с ошибкой в git + cygwin, когда я теряю изменения, поэтому, чтобы убедиться, что все пошло в reflog, я настроил следующее:
git add . && git commit -am 'tmp' && git reset HEAD^ && git diff -w > foo.patch && git checkout . && git apply foo.patch && rm foo.patch
По сути, мы создаем diff, который не включает изменения пространства, отменяем все наши изменения и затем применяем diff.
Ответ, получивший наибольшее количество голосов, работает не во всех случаях, из-за пробелов в контексте патча, по словам пользователей в комментариях.
Я пересмотрел команду следующим образом:
$ git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero
Это создает патч без контекста. Не должно быть проблемой, так как патч недолговечный.
Соответствующий псевдоним, снова пересмотр того, что уже было предоставлено другими пользователями:
addw = !sh -c 'git diff -U0 -w --no-color "$@" | git apply --cached --ignore-whitespace --unidiff-zero' -
Добавьте следующее к вашему .gitconfig
:
anw = !git diff -U0 -w --no-color -- \"$@\" | git apply --cached --ignore-whitespace --unidiff-zero "#"
Спасибо ответу @Colin Herbert за вдохновение.
Синтаксис Объяснение
Финал #
должны быть указаны, чтобы это не рассматривалось как комментарий внутри .gitconfig
, но вместо этого проходит через и рассматривается как комментарий внутри оболочки - он вставляется между концом git apply
и предоставленные пользователем аргументы, которые git
автоматически ставится в конце командной строки. Эти аргументы здесь не нужны - мы не хотим git apply
потреблять их, следовательно, предыдущий символ комментария. Вы можете запустить эту команду как GIT_TRACE=1 git anw
чтобы увидеть это в действии.
--
сигнализирует конец аргументов и позволяет в случае, если у вас есть файл с именем -w
или что-то похожее на переключатель в git diff
,
Побег двойные кавычки вокруг $@
требуется сохранить любые предоставленные пользователем аргументы в кавычках. Если "
персонаж не избежал, он будет использован .gitconfig
парсер и не дошел до оболочки.
Замечания: .gitconfig
синтаксический анализ псевдонимов не распознает одинарные кавычки как нечто особенное - его только специальные символы "
, \
, \n
, а также ;
(вне "
строка в кавычках). Вот почему "
всегда должен быть экранирован, даже если он выглядит так, как будто он внутри строки в одинарных кавычках (о которой git совершенно не знает).
Это важно, например. если у вас есть удобный псевдоним для выполнения bash
команда в корне рабочего дерева. Неправильная формулировка:
sh = !bash -c '"$@"' -
Хотя правильным является:
sh = !bash -c '\"$@\"' -
Как насчет следующего:
git add `git diff -w --ignore-submodules |grep "^[+][+][+]" |cut -c7-`
Команда внутри обратных кавычек получает имена файлов, которые не имеют пробелов.
Аналогично ответу @void.pointer, но для исправления самой последней фиксации.
git reset --mixed head^
git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero -
Это оставляет изменения пробелов неустановленными, а остальные — подготовленными.
У меня есть текстовый редактор, который автоматически обрезает конечные пробелы при сохранении файла.
В вашем редакторе нет специальных настроек proj/dir? Можно просто отключить настройки пробелов для этого проекта. Вроде проще решить...
Это мой взлом.
git diff -w | grep "diff --git a/*" | sed -r 's#diff --git a/(.*) b(.*)#\1#g' | xargs git add
git diff -w показывает только файлы с изменениями без пробелов,
Меня устраивает :
git config apply.whitespace fix
Перед каждой фиксацией используйте команду:
git add -up .
Я нашел git pre-commit hook, который удаляет завершающие пробелы. Однако, если вы не можете заставить других использовать это, то это может быть недопустимым решением.
#!/bin/sh
if git-rev-parse --verify HEAD >/dev/null 2>&1 ; then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# Find files with trailing whitespace
for FILE in `exec git diff-index --check --cached $against -- | sed '/^[+-]/d' | sed -r 's/:[0-9]+:.*//' | uniq` ; do
# Fix them!
sed -i 's/[[:space:]]*$//' "$FILE"
done
exit
Сначала вы должны рассмотреть, является ли конечный пробел намеренным. Многие проекты, в том числе ядро Linux, Mozilla, Drupal и Kerberos (и многие другие на странице Википедии о стиле), запрещают использовать пробелы в конце. Из документации ядра Linux:
Получите достойный редактор и не оставляйте пробелы в конце строк.
В вашем случае проблема в другом: предыдущие коммиты (и, возможно, текущие) не следовали этому руководству.
Держу пари, что никому на самом деле не нужны конечные пробелы, и решение проблемы может быть долгожданным изменением. Другие пользователи также могут испытывать ту же проблему, что и вы. Также вероятно, что автор (ы), которые добавляют конечные пробелы, не знают, что они делают это.
Вместо того, чтобы пытаться перенастроить git, чтобы игнорировать проблему, или отключить другие желательные функции в вашем редакторе, я бы начал с публикации в списке рассылки проекта, объясняющего проблему. Многие редакторы (и сам git) могут быть настроены для работы с конечными пробелами.