32

ファイル(1.c)には、作成者MとJによって行われた3つの関数と変更が含まれていると考えてください。誰かが実行git blame 1.cすると、次の出力が得られます。

^869c699 (M 2012-09-25 14:05:31 -0600  1) 
de24af82 (J 2012-09-25 14:23:52 -0600  2) 
de24af82 (J 2012-09-25 14:23:52 -0600  3) 
de24af82 (J 2012-09-25 14:23:52 -0600  4) public int add(int x, int y)  {
de24af82 (J 2012-09-25 14:23:52 -0600  5)    int z = x+y;
de24af82 (J 2012-09-25 14:23:52 -0600  6)    return z;
de24af82 (J 2012-09-25 14:23:52 -0600  7) }  
de24af82 (J 2012-09-25 14:23:52 -0600  8) 
^869c699 (M 2012-09-25 14:05:31 -0600  9) public int multiplication(int y, int z){
^869c699 (M 2012-09-25 14:05:31 -0600 10)    int result = y*z;
^869c699 (M 2012-09-25 14:05:31 -0600 11)    return temp;
^869c699 (M 2012-09-25 14:05:31 -0600 12) }
^869c699 (M 2012-09-25 14:05:31 -0600 13) 
^869c699 (M 2012-09-25 14:05:31 -0600 14) public void main(){
de24af82 (J 2012-09-25 14:23:52 -0600 15)    //this is a comment
de24af82 (J 2012-09-25 14:23:52 -0600 16) }

これで、作成者Aがmultiplication()andadd()関数の位置を変更して変更をコミットするとgit blame、コードの動きを検出できます。次の出力を参照してください。

$ git blame  -C -M e4672cf82 1.c
^869c699 (M 2012-09-25 14:05:31 -0600  1) 
de24af82 (J 2012-09-25 14:23:52 -0600  2) 
de24af82 (J 2012-09-25 14:23:52 -0600  3) 
e4672cf8 (M 2012-09-25 14:26:39 -0600  4) 
de24af82 (J 2012-09-25 14:23:52 -0600  5) 
^869c699 (M 2012-09-25 14:05:31 -0600  6) public int multiplication(int y, int z){
^869c699 (M 2012-09-25 14:05:31 -0600  7)    int result = y*z;
^869c699 (M 2012-09-25 14:05:31 -0600  8)    return temp;
^869c699 (M 2012-09-25 14:05:31 -0600  9) }
^869c699 (M 2012-09-25 14:05:31 -0600 10) 
^869c699 (M 2012-09-25 14:05:31 -0600 11) public void main(){
de24af82 (J 2012-09-25 14:23:52 -0600 12)    //this is a comment
e4672cf8 (M 2012-09-25 14:26:39 -0600 13) }
de24af82 (J 2012-09-25 14:23:52 -0600 14) public int add(int x, int y){
de24af82 (J 2012-09-25 14:23:52 -0600 15)    int z = x+y;
de24af82 (J 2012-09-25 14:23:52 -0600 16)    return z;
e4672cf8 (M 2012-09-25 14:26:39 -0600 17) }

ただし、これら2つのリビジョン間で実行しようとするgit diffと、関数がその場所を変更したことを検出できず、次の出力が得られます。

$ git diff -C -M de24af8..e4672cf82 1.c

diff --git a/1.c b/1.c
index 5b1fcba..56b4430 100644
--- a/1.c
+++ b/1.c
@@ -1,10 +1,7 @@



-public int add(int x, int y){
-       int z = x+y;
-       return z;
-}      
+

public int multiplication(int y, int z){
    int result = y*z;
@@ -13,4 +10,8 @@ public int multiplication(int y, int z){

 public void main(){
    //this is a comment
-}
\ No newline at end of file
+}
+public int add(int x, int y){
+       int z = x+y;
+       return z;
+}      
\ No newline at end of file

私の質問は次のとおりです。

  1. 差分出力を取得する際にコードの動きを検出するように強制するにはどうすればよいですか?それも可能ですか?

  2. Git diffは、いくつかのオプションで適用できます。たとえば--minimal--patience。ここでこれらのオプションを適用するにはどうすればよいですか?1つで試しましたが、次のエラーが発生します。

    $ git diff --minimal de24af8..e4672cf82 1.c
    usage: git diff <options> <rev>{0,2} -- <path>*
    

誰かがこれらのオプションを正しく追加する方法のサンプル例を提案/与えることができますか?

4

3 に答える 3

51

Git 2.15以降git diff--color-moved、オプションで移動した線の検出をサポートするようになりました。ファイル間の移動も検出します。

明らかに、カラー化された端末出力に対して機能します。私の知る限り、プレーンテキストのパッチ形式で移動を示すオプションはありませんが、それは理にかなっています。

デフォルトの動作については、

git diff --color-moved

このコマンドはno、現在default、、、、および(最新のオプションとその説明を取得するために使用)のplainオプションも取ります。例えば:zebradimmed_zebragit help diff

git diff --color-moved=zebra
于 2017-11-09T02:24:54.207 に答える
24

これは、それが書かれた時点での最良の答えでしたが、もはや正確ではありません。2017年、Git2.15diffは移動検出を行うようにアップグレードしました。現在投票数の多い回答で説明されているようにgit diff --color-moved

元の答え:

ここであなたが直面しているのは、Gitがこのような高度なdiffからほとんど離れているということです。Gitが外部の差分ツールとマージツールの構成を許可するのには理由があります。彼らの助けがなければ狂気に陥るでしょう。例として、BeyondCompareとAraxisMergeはどちらもこの動きを捉えます。

解決しようとしている問題の一般的なクラスは、「構造化マージ」です。2つのJavaソースファイルの構造差分

前者は作成者とコミットメッセージを含むより多くのコミット情報を提供し、指定した範囲で各コミットのパッチファイルを生成するため、この場合git-format-patchよりも少し運が良いかもしれません。git-diff出典:「gitformat-patch」と「gitdiff」の違いは何ですか?

一般的にコードの動きを検出するためのヒントを探している場合、コードの動きの検出は明らかに強力なつるはしの目標ではないことに注意してください。この興味深い交換を参照してください:http://gitster.livejournal.com/35628.html

誰が注文を交換したかを検出したい場合、唯一の選択肢は次のようなことをすることだと思われます。

 git log -S'public int multiplication(int y, int z){
    int result = y*z;
    return temp;
 }

 public void main(){
    //this is a comment
 }
 public int add(int x, int y)  {
    int z = x+y;
    return z;
 }'

あなたが探しているのはgit blame -M<num> -n、あなたが求めているものと非常によく似た何かをすることです:

-M|<num>|
       Detect moved or copied lines within a file. When a commit moves or
       copies a block of lines (e.g. the original file has A and then B,
       and the commit changes it to B and then A), the traditional blame
       algorithm notices only half of the movement and typically blames
       the lines that were moved up (i.e. B) to the parent and assigns
       blame to the lines that were moved down (i.e. A) to the child
       commit. With this option, both groups of lines are blamed on the
       parent by running extra passes of inspection.

       <num> is optional but it is the lower bound on the number of
       alphanumeric characters that git must detect as moving/copying
       within a file for it to associate those lines with the parent
       commit. The default value is 20.

-n, --show-number
       Show the line number in the original commit (Default: off).
于 2012-10-09T17:38:02.823 に答える
2

git diffこの特定のケースでは、コードの動きを検出することについては心配していません。むしろ、古いファイルを新しいファイルに変換するために適用できるパッチを作成するだけです。これは、git diff出力がはっきりと示していることです。関数は、ある場所から削除され、別の場所に挿入されています。コードをある場所から別の場所に移動する一連の編集コマンドを出力するためのより簡潔な方法はおそらくありますが、gitここでは移植性の面で誤りがあると思います-エンドユーザーの傷が常にgit applyまたはを使用するという保証はないgit amので、パッチはプレーンでも使えるフォーマットで制作patch

于 2012-10-09T19:01:10.770 に答える