空白以外の変更のみを追加する


343

ファイルの保存時に末尾の空白を自動的に削除するテキストエディターを使用していて、末尾の空白に重大な問題があるオープンソースプロジェクトに貢献しています。

パッチを送信しようとするたびに、まず空白のみの変更をすべて手動で無視して、関連情報のみを選択する必要があります。それだけでなく、私が実行するgit rebaseと、通常、そのためにいくつかの問題に遭遇します。

そのため、同様の方法で、空白以外の変更のみをインデックスに追加できるようにしたいのですgit add -pが、すべての変更を自分で選択する必要はありません。

誰でもこれを行う方法を知っていますか?

編集:プロジェクトの動作を変更することはできません。メーリングリストで議論した結果、これを無視することに決定しました。

回答:


395

@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は必須ではありませんが、色を常に設定しているため、使用する必要があります。とにかく、申し訳ありませんが安全です。


7
これは私にとってはうまくいきましたが、git apply --ignore-whitespaceそれ以外の場合はパッチを適用しなければ明らかな理由で使用できませんでした。
jupp0r

106
実際にgit addのオプションがあるはずgit add -wです。
Jarl 14

7
これは私に問題を与えます... patch does not applyそしてerror while searching for何かアイデアはありますか?
DTI-Matt

18
うまくいきませんでした。手に入れたpatch does not applyエラーを。
ジェリーサラビア

13
@bronsonが指摘しているように、コンテキスト内の空白が原因で「パッチが失敗しました」と表示された場合、次の修正されたコマンドが機能します(コンテキストのないパッチが生成されます)git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero。インデックスは既に可能な限り最新であるため、これは危険ではありません。したがって、パッチの信頼できるベースとなります。
void.pointer 2016年

36

これは私にとってはうまくいきます:

隠し場所を維持したい場合、これは機能します

git stash && git stash apply && git diff -w > foo.patch && git checkout . && git apply foo.patch && rm foo.patch

私はスタッシュ好きではないが、私はしているので、確かなものが、私は次のように設定し、少なくともREFLOGに行ったことを確認するために、私は変更を失うところのgit + cygwinの中にバグに遭遇します:

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を適用します。


1
+1。git stash少なくともそれがテストされるまで、変更のバックアップをとるために、チェックアウトの代わりに実行したい場合があります。
–PaŭloEbermann 2011

1
あなたはたくさんの隠し場所に行き着くでしょう、そして基本的にあなたは実際にこれのすべてをする必要はありません。動作しますが、少し厄介だと思います
Colin Hebert '22

3
私はコリンに同意します。スクリプトが機能する場合は、スタッシュを作成する必要はありません。stashを実行してからstash popを実行することを検討することをお勧めします。ポップされたスタッシュは必要に応じて回復できますが、そうでなければ多くのスタッシュが残ることはありません。これにより、余分なファイルが
残り

バイナリファイルをスキップするのはどうですか?上記のスニペットを適用しようとすると、完全なインデックス行がないとパッチを適用できないというエラーが発生します。最初にこれらのファイル/バイナリに触れさえしなかったのは私を打ったことです!
tver3305 2012

1
最初のコマンドの最後にある "git rm foo.patch"は "rm foo.patch"にすべきだと思います。それ以外の場合は非常に役立ちます。
Jack Casey

33

実際の変更のみ(空白の変更のみの行を除く)を含むパッチファイルを作成し、ワークスペースをクリーンアップして、そのパッチファイルを適用します。

git diff>バックアップ
git diff -w>変更
git reset --hard
patch <変更

その後addcommit通常どおり、残りの違いを確認します。

Mercurialと同等のことはこれを行うことです:

hg diff> backup
hg diff -w> changes
hg revert --all
hg import --no-commit changes


「保護された」質問とは何ですか?私も答えます。質問が薄い空気から引き出されたように見えるので、私もこれは私も答えの資格があるとは思いません...
jww

4
@jww元の投稿者の質問の中心は、「ソース管理への空白のみの変更のコミットを回避する方法」です。OPはたまたまGitを使用していますが、これは私が今まで使用したすべてのソース管理システムにも当てはまります。この答えは、誰かがたまたまMercurialを使用している場合の正しい手順を示しています。私はまた、などSublesion、使用している人々のためのソリューション貢献するかもしれない他の誰かを想像
スティーブ投手

1
@jwwと@ pagid:Mercurialの私のソリューションと同じアプローチを使用して、Gitに具体的に対処するために私の回答を編集しました。私の見解では、StackOverflowは単なるQ + Aフォーラムではなく、知識のリポジトリとしての役割もあります。元のポスター以外の人々は与えられた答えから利益を得るかもしれません、そして彼らの状況は異なります。そのため、特定の1つの状況のみを対象とするのではなく、一般原則を伝える回答が有効であると考えています。
スティーブピッチャーズ2015

@Steve- 「具体的にGitに対処するために自分の回答を編集しました...」 -Mercurialのコンテキストで新しい質問をして、新しい質問に独自の回答を追加しなかったのはなぜですか?
jww

8
これは実際に、私が見たアプローチの中で最もクリーンで、最も理解しやすく、最も壊れにくいものです。
Kzqai 2016年

12

コメントでのユーザーによると、パッチコンテキストに空白があるため、トップ投票の回答がすべてのケースで機能するわけではありません。

コマンドを次のように修正しました。

$ 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' -

インデントの変更のみを無視するには、の--ignore-space-change代わりに使用する必要がありました-wgit diff -U0 --ignore-space-change --no-color | git apply --cached --unidiff-zero
アンディ

この素敵なコンテキストなしのトリックを--ignore-blank-lines他の方法で使用しないように警告すると、無視しようとしている「空白」の変更の一部が空の行の削除/追加である場合、diffチャンクが誤ったオフセットでパッチされます。
elbeardmorez 2018

12

次のものをに追加します.gitconfig

anw = !git diff -U0 -w --no-color -- \"$@\" | git apply --cached --ignore-whitespace --unidiff-zero "#"

インスピレーションを得るための@Colin Herbertの回答に感謝します。

構文の説明

final #は引用符で囲む必要があるため、内ではコメントとして扱われません.gitconfigが、代わりに渡され、シェル内でコメントとして扱われます-の末尾git applyとユーザー指定の引数の間に挿入され、git自動的にコマンドラインの終わり。これらの引数はここでは必要ありません- git applyそれらを消費したくないので、前のコメント文字です。このコマンドを実行して、このGIT_TRACE=1 git anw動作を確認してください。

--信号は、引数の終わりとあなたが名前のファイルがあること場合することができます-wかにスイッチのように見える何かをgit diff

エスケープされた二重引用符$@は、ユーザー指定の引用符付き引数を保持するために必要です。"文字がエスケープされていない場合、.gitconfigパーサーによって消費され、シェルに到達しません。

注:.gitconfig別名解析が何か特別なとして単一引用符を認識しない-その唯一の特殊文字は"\\n、および;(外"-quoted文字列)。これが"、単一引用符で囲まれた文字列の内部にあるように見えても(gitが完全に不可知論である)、常にエスケープする必要がある理由です。

これは重要です。bash作業ツリーのルートでコマンドを実行するための便利なエイリアスがある場合。不適切な定式化は次のとおりです。

sh = !bash -c '"$@"' -

正しいものは:

sh = !bash -c '\"$@\"' -

優秀な。これにより、一度に1つのファイルを追加できました。引数にルートディレクトリを追加する以外に、これを 'git add -A'のように機能させる方法はありますか?
チャッキー

7

次はどうですか:

git add `git diff -w --ignore-submodules |grep "^[+][+][+]" |cut -c7-`

バッククォート内のコマンドは、空白以外の変更があったファイルの名前を取得します。


2
またはgit add `git diff -w |grep '^+++' |cut -c7-`サブモジュールが使用されていない場合
karmakaze

-1

末尾の空白が意図的なものかどうかを最初に検討する必要があります。Linuxカーネル、Mozilla、Drupal、およびKerberos(スタイルに関するWikipediaのページからいくつか例を挙げます)を含む多くのプロジェクトでは、末尾の空白を禁止しています。Linuxカーネルのドキュメントから:

まともなエディタを入手し、行末に空白を残さないでください。

あなたの場合、問題は逆です:以前のコミット(そしておそらく現在のコミット)はこのガイドラインに従っていませんでした。

末尾の空白を本当に必要としている人はいないと思います。問題の修正は歓迎すべき変更かもしれません。他のユーザーも同じ問題を経験している可能性があります。また、末尾の空白を追加している寄稿者がそうしていることに気づいていない可能性もあります。

問題を無視するようにgitを再構成したり、エディターのその他の望ましい機能を無効にしたりするのではなく、問題を説明するプロジェクトメーリングリストへの投稿から始めます。多くのエディター(およびgit自体)は、末尾の空白を処理するように構成できます。


16
それは意図的なものではありませんが、プロジェクトに貢献した100人以上の人々の考え方を変えることはできません。彼らはそれを気にせず、末尾の空白のみを処理する1000以上の変更があるパッチを受け入れません。彼らは問題について知っていて、それを無視することにしました。この議論はすでにリストで行われており、終了しました。この場合、それらに適応する必要があるのは私です。
Edu Felipe

19
次に、このプロジェクトのコードで作業するときに末尾の空白を削除しないようにエディターを構成します。
jamessan 2010

-2

末尾の空白を削除するgit pre-commitフックを見つけました。ただし、他のユーザーにこれを使用してもらうことができない場合は、有効なソリューションではない可能性があります。

  #!/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

4
この質問は、末尾の空白を保持する方法を尋ねています。
ダグラス

@ダグラス:おそらくこの答えを使用して一時的なブランチにコミットを作成し、そこに実際のパッチをコミットして、どういうわけか作業ブランチにのみ差分をチェリーピックすることができます...
Tobias Kienzler
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.