使用Git diff检测代码移动+如何使用diff选项

Muh*_*man 24 git git-diff

考虑一个文件(1.c)包含作者M和J所做的三个函数和更改.如果有人运行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) }
Run Code Online (Sandbox Code Playgroud)

现在,如果作者A改变的位置multiplication()add()功能,并提交更改,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) }
Run Code Online (Sandbox Code Playgroud)

但是,如果我尝试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
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  1. 如何在获取diff输出时强制检测代码移动?它甚至可能吗?

  2. Git diff可以应用多种选项.例如--minimal,--patience.我如何在这里应用这些选项?我试过一个,但得到以下错误:

    $ git diff --minimal de24af8..e4672cf82 1.c
    usage: git diff <options> <rev>{0,2} -- <path>*
    
    Run Code Online (Sandbox Code Playgroud)

任何人都可以建议/举例说明如何正确添加这些选项?

vas*_*vas 33

Git 2.15开始,git diff现在支持使用该--color-moved选项检测移动的行.它甚至可以检测文件之间的移动

显然,它适用于彩色终端输出.据我所知,没有选项以纯文本补丁格式指示移动,但这是有道理的.

对于默认行为,请尝试

git diff --color-moved
Run Code Online (Sandbox Code Playgroud)

该命令还需要选择,目前是no,default,plain,zebradimmed_zebra(使用git help diff以获得最新的选项及其说明).例如:

git diff --color-moved=zebra
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!对于任何想知道的人,命令可以是:`git config diff.colorMoved true --global` (4认同)
  • _GitHub_是否有类似内容? (2认同)
  • @davidschumann 更正: `git config --global diff.colorMoved true` (--global 位于选项名称之前) (2认同)

kay*_*243 21

你在这里遇到的是Git很大程度上不像这样的高级差异.Git允许配置外部差异和合并工具是有原因的:如果没有他们的帮助,你会疯了.作为一个例子,Beyond Compare和Araxis Merge都会抓住这一运动.

您要解决的一般问题类是"结构化合并":两个java源文件的结构差异

你可能有更多的运气git-format-patchgit-diff在这种情况下,因为前者提供了更多的承诺信息,包括作者和提交信息,并生成一个补丁文件在指定范围内的每个提交.来源:'git format-patch和'git diff'有什么区别?

如果您正在寻找有关检测代码移动的技巧,那么有趣的是,检测代码移动显然不是全能镐的目标.看到这个有趣的交流: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;
 }'
Run Code Online (Sandbox Code Playgroud)

您正在寻找的是什么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).
Run Code Online (Sandbox Code Playgroud)

  • 这个答案非常有帮助。一个后续问题是为什么 git*hub* 不使用更高级的差异工具。对那些 PR 只是移动大量代码的人进行 PR 对审阅者来说看起来很繁重,而实际上代码可能变化很小。 (2认同)