Добавить только изменения без пробелов

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

Каждый раз, когда я пытаюсь представить патч, я должен сначала игнорировать все изменения только пробелов вручную, чтобы выбрать только соответствующую информацию. Не только это, но когда я бегу 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) могут быть настроены для работы с конечными пробелами.

Другие вопросы по тегам