Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to get a clear git diff when replacing a function entirely?

Tags:

c++

git

diff

So, I've run into this problem a few times. During a round of changes, I remove functionA() and add functionB() in the same place. When I run a diff, I end up with a hideous muddled set of changes where it tries matching the two functions up on their common braces rather than showing all of functionA as a removal and all of functionB as an addition. For a simplified example:

int functionA(int a, bool b)
{
    int c;
    bool d;
    if (a == b)
    {
        //do stuff
    }
    //do more stuff
}

replaced with

void functionB()
{
    // do different stuff
    for (int x=0; x<10; x++)
    {
        //do more different stuff
    }
    //do even more different stuff
}

the diff might yield

-int functionA(int a, bool b)
+void functionB()
 {
-    int c;
-    bool d;
-    if (a == b)
+    // do different stuff
+    for (int x=0; x<10; x++)
     {
-        //do stuff
+        //do more different stuff
     }
-    //do more stuff
+    //do even more different stuff
 }

Which is useless and difficult to read, since there's really no commonality besides the braces. It will even skip braces that don't align until it finds ones that do, which is common enough. And in one case I'm looking at now, I removed 7 consecutive functions and added 3, which do roughly the same thing a much more easily readable/maintainable manner. The diff algorithm disburses the additions in a scattered way through all 7 removed functions, making an unreadable and confusing mess.

Is there any way to tweak git diff to ignore cases where the only commonality is a brace?

If it matters, my system currently has git 1.9.0 and diff (GNU difftools) 2.8.1 I tagged C++ because the system I work on is (mostly C-style) C++, but this should apply to a number of other languages.

While looking for existing questions, the nearest I could find was What is git diff --patience for? However, this had very little impact on my diff. (It is different, but not visibly clearer)

I also see in the git diff man page the --break-rewrites option, which does what I want, but only at the file level, not the function level.

If nothing else, I guess I can try making a habit in the future of putting new logic in a completely different part of the file from any removals in cases where I want the diff to show the addition in one block, but I'd prefer to keep related logic together.

like image 594
Bryon Avatar asked Jun 07 '16 17:06

Bryon


People also ask

What does ++ mean in git diff?

When viewing a combined diff, if the two files you're comparing have a line that's different from what they were merged into, you will see the ++ to represent: one line that was added does not appear in either file1 or file2.

How do I terminate git diff?

To exit this you can use: :q for exit; :h for help; Note: if you don't want to read the output in pager you can use an ENV variable GIT_PAGER to cat or you need to set core.

When might git diff HEAD yield no results?

There is no output to git diff because Git doesn't see any changes inside your repository, only files outside the repository, which it considers 'untracked' and so ignores when generating a diff.

What is the difference between git diff and git diff -- staged?

git diff --staged will only show changes to files in the "staged" area. git diff HEAD will show all changes to tracked files. If you have all changes staged for commit, then both commands will output the same.


1 Answers

Git currently1 offers four diff algorithms, known as myers (the default), minimal, patience, and histogram. The last one is a slight tweak to patience. These were all in Git version 1.9.0, though. If none of them does what you want, you can tell Git to use an external diff. See the "Generating diff text" section of the gitattributes documentation (which refers back to the main git documentation) for details. It's a bit complicated, but to summarize, you use gitattributes to force Git to run the external diff program, and you define the external diff program by writing a script (usually sh/bash) and configuring it in your global or per-repository settings.


1As of version 2.8.x anyway; 2.9 is almost out and does not have any new ones.

like image 82
torek Avatar answered Oct 05 '22 12:10

torek