移動/名前変更されたファイルでgit diffを行う方法は?


128

を使用してファイルを移動しましたgit mv。次に、新しいファイルを比較して、古いファイル(古い、現在は存在しない名前)と比較します。

どうすればよいですか?


4
間もなく(Git 2.9、June 2016)、シンプルgit diff -- yourRenamedFileで十分です。以下の私の回答を
VonC

回答:


145

差分をとるときにgitに移動したファイルを自動検出させるには-Mを使う必要があります。git diffknittlと同じように使用しても機能しません。

だから単純に:git diff -Mそれを行うべきです。

このスイッチのドキュメントは次のとおりです。

-M[<n>], --find-renames[=<n>]
       Detect renames. If n is specified, it is a threshold on the similarity index 
       (i.e. amount of addition/deletions compared to the file’s size). For example, 
       -M90% means git should consider a delete/add pair to be a rename if more than
       90% of the file hasn’t changed.

7
命の恩人!私のgit diffはとても良くなりました。1)常にこのオプションを使用しても安全ですか?2)このオプションをデフォルトの動作として自分に追加できます~/.gitconfigか?
kevinarpe 2015年

5
名前の変更の検出は、で処理されるファイルのコレクションに古いファイルと新しいファイルの両方が表示されている場合にのみ機能することに注意してくださいgit diff。実行git diff -Mシングル(改称)ファイルには、名前変更を報告しません。
レオン

1
これは私にはgit log --follow -- file_after_move.txtうまくいきませんが、うまくいきます。移動前を含む、すべての履歴が表示されます。何か案は?私は走っていgit version 2.11.0.windows.1ます。
bouvierr

1
-Cコピーを検出するためのオプションは便利で似ています。私-Mは、1つのファイルを2つにリファクタリングした差分を見るためにそれを使用しました(どちらの名前も元のファイルと一致していません)。
cp.engr

85

knittlが書いたものに加えて、いつでも使用できます。

git diff HEAD:./oldfilename newfilename

ここHEAD:./oldfilenameで、現在のディレクトリを基準にした、最後のコミット(HEAD内)のoldfilenameを意味します。

十分に新しいgitがない場合は、代わりに使用する必要があります。

git diff HEAD:path/to/oldfilename newfilename

8
これをありがとう。ヘッドの代わりに特定のコミットを指定することもできます。例git diff 39fa7c77e85c51d43ea0cf30d33aec8721812e9e:./oldfilename newfilename
Chris Bloom

8
:ケースで、それはあなたには、また、ブランチ名またはその他の参照、指定することができ、不明だgit diff branch:old/filen.name newfilename
jricher

最初のフォームcdは、ディレクトリ--に移動し、commit:pathペアの前に追加しない場合、私にとっては機能します。Gitは構文が非常にうるさいようです。
dhardy

1
@dhardy <commit-ish>:<pathname>構文はオブジェクト識別子であり、Git風のものです。--Gitがファイル名のみを期待した後。
JakubNarębski、2016年

18

git 2.9(2016年6月)では、追加する必要はあり-Mません。git diff使用する-Mデフォルトでします。

Matthieu Moy()によるcommit 5404c11commit 9501d19commit a9276a6commit f07fc9ecommit 62df1e6(2016年2月25日)を参照してください。(による合併Junio C浜野- -5d2a30dコミット、2016年4月3日)moy
gitster

diffdiff.renamesデフォルトでアクティブ化

名前の変更の検出は非常に便利な機能であり、新しいユーザーがドキュメントを掘り下げる必要はありません。

名前の変更の検出をアクティブにすることに対する潜在的な異論は、失敗することもあり、遅いこともあります。ただし、「git status」や「git merge」などのいくつかのケースでは、名前の変更の検出がデフォルトですでにアクティブになっているため、アクティブにdiff.renamesしても状況は根本的に変わりません。名前の変更の検出が失敗すると、「git diff」と「git status」の間で一貫して失敗するようになりました。

この設定は配管コマンドには影響しないため、適切に記述されたスクリプトは影響を受けません。

この機能の新しいテストはこちらです。


1

git diff -M他の人が言ったように名前変更検出をアクティブにします(そして@VonCが指摘したように、それはgit 2.9からデフォルトでアクティブになります)。ただし、大きな変更セットがある場合は、不正確な名前変更の検出が再びオフになる可能性があります。Gitは次のような警告を表示します。これは、表示している差分の中で見逃しがちです。

warning: inexact rename detection was skipped due to too many files.
warning: you may want to set your diff.renameLimit variable to at least 450 and retry the command.

その場合は、たとえばgitの提案に従って構成オプションを設定します。

git config diff.renamelimit 450

そして、diffコマンドを再実行します。


0

何らかの理由でHEAD:./oldfilename(または絶対パス)を使用してもHEAD:oldfilenameうまくいきませんでしたが(ありがとうcmn):

git diff HEAD:oldfilename newfilename
git diff 2a80f45:oldfilename f65f3b3:newfilename

HTH


おそらくあなたのgitは古すぎて理解できHEAD:./oldfilenameませんか?
JakubNarębski、2012年

-4

単に実行git diff引数なし、またはgit diff -- newfilename。gitは適切なファイル/コンテンツ(つまり、名前を変更する前の元のコンテンツと名前を変更した後の変更されたコンテンツ)を比較するのに十分スマートです


2
ほとんどの場合、gitはまったく賢くありません。git mv単一のファイルを単純に処理してから、ステージングされた状態を別の同じブランチと比較すると、「-M使用されない限り、すべてが削除され、再作成された」という差分が生成されます。
Reinderien
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.