Git инструмент для удаления строк из этапа, если они состоят только из изменений в пробеле

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

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

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

Также бонус должен был бы изменить поэтапную линию, чтобы удалить удаленные пробелы для строк с изменениями кода.

Кроме того, бонус должен был бы не делать этого для файлов Markdown (поскольку в трейлинг-пространстве есть значение в Markdown).

Я прошу здесь, поскольку я полностью намерен написать этот инструмент, если он еще не существует.

Ответ 1

Ниже вы получите следующее:

$ clean=`git diff --cached -b`; \
  git apply --cached <(git diff --cached -R); \
  echo "$clean" | git apply --cached -; \
  clean=

Для выпусков git до 1.7.0 он терпит неудачу, если один или несколько файлов имеют все пробелы. Например

$ git diff --cached -b
diff --git a/file1 b/file1
index b2bd1a5..3b18e51 100644
diff --git a/file2 b/file2
new file mode 100644
index 0000000..092bfb9
--- /dev/null
+++ b/file2
[...]

Пустая дельта (выше file1, которая действительно должна быть подавлена) делает git-apply несчастным:

fatal: patch with only garbage at line 3

ОБНОВЛЕНИЕ: Версия 1.7.0 git устраняет эту проблему.

Скажем, наш репозиторий находится в следующем состоянии:

$ git diff --cached
diff --git a/foo b/foo
index 3b18e51..a75018e 100644
--- a/foo
+++ b/foo
@@ -1 +1,2 @@
-hello world
+hello  world
+howdy also

Затем мы могли бы выполнить приведенные выше команды, чтобы развернуть индекс и дерево работы:

$ git diff --cached
diff --git a/foo b/foo
index 3b18e51..1715a9b 100644
--- a/foo
+++ b/foo
@@ -1 +1,2 @@
 hello world
+howdy also

$ git diff 
diff --git a/foo b/foo
index 1715a9b..a75018e 100644
--- a/foo
+++ b/foo
@@ -1,2 +1,2 @@
-hello world
+hello  world
 howdy also

Если все изменения имеют только пробелы, вы увидите

error: No changes

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

Ответ 2

Мое решение в git 1.7.2.5 было следующим (начиная без), если все изменения были поставлены):

git diff -w > temp.patch
git stash
git apply --ignore-space-change --ignore-whitespace temp.patch
# tidy up:
rm temp.patch
git stash drop

Это приведет к возврату вашего репо в исходное состояние с удалением любых пробелов.

Затем вы можете выполнить свои изменения, как обычно.

Ответ 3

Я использовал script на основе @GregBacon answer в течение многих лет, но в какой-то момент git изменил вывод git diff -b так, чтобы переменные пробелов не отображаются, поскольку изменения были включены в строки контекста патча в состоянии after, а не в состоянии before.

Я обнаружил, что если бы я изменил чистый diff и соответствующий применил, script снова работал.

Итак, мой полный script выглядел так:

#!/bin/bash

clean=`git diff --cached -b`
git apply --cached <(git diff --cached -R)
echo "$clean" | git apply --cached -
clean=

Теперь выглядит:

#!/bin/bash

clean=`git diff --cached -b -R`
git apply --cached <(git diff --cached -R)
echo "$clean" | git apply --cached -R -
clean=

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

git apply --cached -R <(git diff --cached -w)