git diff名前が変更されたファイル


105

ファイルがありますa.txt

cat a.txt
> hello

の内容a.txtは「こんにちは」です。

コミットします。

git add a.txt
git commit -m "first commit"

次にa.txttestdirに移動します。

mkdir test
mv a.txt test

次に、2回目のコミットを行います。

git add -A
git commit -m "second commit"

最後に、a.txt代わりに「さようなら」と言うように編集します。

cat a.txt
> goodbye

最後にコミットします。

git add a.txt
git commit -m "final commit"

これが私の質問です:

a.txt最後のコミットと最初のコミットの内容をどのように比較しますか?

私が試した:git diff HEAD^^..HEAD -M a.txt、それはうまくいきませ んでした。 git log --follow a.txtは名前の変更を適切に検出しますが、に相当するものが見つかりませんgit diff。ありますか?


「git mv a.txt test」を実行した場合も同じだと思いますか?IEは、ファイルをサブディレクトリに移動するのではなく、名前を変更しただけです。
マックスウォーターマン

回答:


107

違いの問題HEAD^^とは、HEADあなたが持っているということですa.txtので、ちょうど(diffが何をするかである)これら二つのコミットを考慮すると、両方のコミットでは、何の名前の変更はありません、コピーおよび変更があります。

コピーを検出するには、以下を使用できます-C

git diff -C HEAD^^ HEAD

結果:

index ce01362..dd7e1c6 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1 @@
-hello
+goodbye
diff --git a/a.txt b/test/a.txt
similarity index 100%
copy from a.txt
copy to test/a.txt

ちなみに、diffを1つのパスのみに制限する場合(git diff HEAD^^ HEAD a.txt単一のパスと名前の変更またはコピーを除いてすべてを除外しているため、名前の変更またはコピーが表示されることはありません)-定義により-パス。


2
コミットに複数のファイル変更が含まれているとしましょう。どうすれば単一のファイルの差分に絞り込むことができますか?
平川健

3
@KenHirakawa使用-- <old-path> <new-path>...私の回答を参照してください。
Nolan Amy

私の場合、ファイルの名前が変更されたコミットの詳細を表示したかったのですが、ファイルが削除されてファイルが追加されたことが示されていました... git show -C [commit]実行すると、ファイルの名前変更が認識され、ファイル間の差分。完璧です。
ジェイソン

83

特定のファイルの名前変更を比較するには、-M -- <old-path> <new-path>-Cも機能します)を使用します。

したがって、最後のコミットでファイルの名前変更変更の両方を行った場合、次のようにして変更を確認できます。

git diff HEAD^ HEAD -M -- a.txt test/a.txt

これにより、以下が生成されます。

diff --git a/a.txt b/test/a.txt
similarity index 55%
rename from a.txt
rename to test/a.txt
index 3f855b5..949dd15 100644
--- a/a.txt
+++ b/test/a.txt
@@ -1,3 +1,3 @@
 // a.txt

-hello
+goodbye

// a.txtgitが名前変更を検出するのを助けるために追加された行)


gitが名前変更を検出しない場合は、類似性の低いしきい値を-M[=n]、たとえば1%で指定できます。

git diff HEAD^ HEAD -M01 -- a.txt test/a.txt

以下からのgit diffのドキュメント

-M [<n>] --find-renames [= <n>]

名前の変更を検出します。nが指定されている場合、それは類似性インデックスのしきい値です(つまり、ファイルのサイズと比較した追加/削除の量)。たとえば-M90%、ファイルの90%以上が変更されていない場合、Gitは削除/追加ペアを名前の変更と見なす必要があることを意味します。%符号なしの場合、数値は小数部として読み取られ、その前に小数点が付きます。-M5つまり、0.5 になるため、と同じになり-M50%ます。同様に、-M05と同じ-M5%です。検出を正確な名前の変更に制限するには、を使用します-M100%。デフォルトの類似性インデックスは50%です。


...もちろん、変更および名前の変更は、元の例のように別々のコミットしているときにも動作します:git diff HEAD^^ HEAD -M -- a.txt test/a.txt
ノーランエイミー

1
ファイルの内容が、diffが類似性インデックスを作成するのに十分近い場合のみ。両方のオプション(-Mと-C)を使用すると、名前が変更され、完全に変更された(インデントを含む)ファイルの/ dev / nullからの/ dev / nullへの差分が表示されます。空白。
DavidG 2013

37

次のこともできます:

git diff rev1:file1 rev2:file2

あなたの例では、これは

git diff HEAD^^:./a.txt HEAD:./test/a.txt

明示的であることに注意してください。./この形式では、パスがレポのルートからの相対パスであると想定しています。(リポジトリのルートにいる場合は、もちろん省略できます。)

ユーザーは何を比較するかを正確に明示しているため、名前の変更の検出にはまったく依存しません。(したがって、git-svn環境で異なるsvnブランチ間でファイルを比較するなど、他のいくつかの状況でも役立ちます。)


1
おお、これはいいです!
ノーランエイミー

マージによってもたらされた追加のファイル変更を伴う名前変更の場合、これが私にとってうまくいった唯一の答えです。ありがとう!
Lane Rettig

1

名前変更コミットがステージングされているがまだコミットされていない場合は、以下を使用できます。

git diff --cached -M -- file.txt renamed_file.txt
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.