Search code examples
gitshellcopyshgitk

How to add better copy detection to gitk?


In command line Git, the show, diff and log commands have got an option to --find-copies-harder.

Is there a way I can tell (or patch) gitk to use this, too? I need this from time to time, and my projects are small enough such that I don't care about the reduced performance.

(I don't want to craft the history to force copy detection any more.)

I noticed that the --find-copies-harder appears within the gitk code, but I don't understand why. So I have tried the command line gitk --all --find-copies-harder, but it didn't work: In a commit with a new file copied from another versioned file, gitk still did not display the fact that this file was copied.

Update: Editing the view by entering --find-copies-harder into the field Additional arguments to git log: also has no effect: A copied (and slightly modified) file is still not shown as copied, while in the command line git show --find-copies-harder it is.


Solution

  • The necessary change is:

    diff --git a/gitk-git/gitk b/gitk-git/gitk
    index 23d9dd1fe0..a98a115080 100755
    --- a/gitk-git/gitk
    +++ b/gitk-git/gitk
    @@ -7909,7 +7909,7 @@ proc diffcmd {ids flags} {
             if {$log_showroot} {
                 lappend flags --root
             }
    -        set cmd [concat | git diff-tree -r $flags $ids]
    +        set cmd [concat | git diff-tree --find-copies-harder -r $flags $ids]
         }
         return $cmd
     }
    

    With this, gitk displays the copy in the second commit of the following test repository

    git init
    echo "a file" > a
    git add a
    git commit -m "a file"
    cp a b
    git add b
    git commit -m "a copy"
    

    as desired:

    -------------------------------------- b --------------------------------------
    similarity index 100%
    copy from a
    copy to b
    

    But note that there might be unintended side effects, since the modified procedure 'diffcmd' is called in several places. I did not systematically test all these code paths.

    (I have also sent a generalized version of this patch to the Git mailing list.)