Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Git rename matching ignore whitespace changes?

Tags:

git

When I rename a file and do whitespace changes (such as changing the indentation), Git cannot recognize the rename. And I can't find any combination of git diff flags to get it to ignore whitespace while looking for renames. This makes reviewing otherwise simple refactorings difficult.

For example...

$ git init
$ ruby -e '100.times { puts "Basset hounds got long ears" }' > file
$ git add file
$ git commit -m 'first commit'
$ git mv file file2

Everything is fine at this point.

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    file -> file2

Now if I indent the lines in the file Git no longer recognizes the rename.

$ ruby -i -pe 'gsub(/^/, "  ")' file2
$ git add .
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    deleted:    file
    new file:   file2

After I commit git diff -w HEAD^ still shows a delete and a new file. I can't find any git diff options which will recognize the rename.

Is there a set of options which allow Git to ignore whitespace when detecting copies and renames?

like image 528
Schwern Avatar asked Oct 10 '18 20:10

Schwern


People also ask

Does git ignore whitespace?

We use the git diff -w command to ignore all whitespace differences. It will ignore spaces at the beginning, middle, and end of lines. We use the git diff --ignore-space-at-eol command to ignore whitespace changes at the end of our lines.

How do I get rid of whitespace changes in git?

Right click on base branch in the Git tab, and do reset. It will undo the commit and stage non-whitespaces changes for commit. Now commit and push -f (I always force push via command line). That's it, you are done!

What happens when you rename a file in Git?

Git keeps track of changes to files in the working directory of a repository by their name. When you move or rename a file, Git doesn't see that a file was moved; it sees that there's a file with a new filename, and the file with the old filename was deleted (even if the contents remain the same).

How does git rename detection work?

So to detect renames is a matter of comparing hashes. To detect small changes to a renamed file, Git uses certain algorithms and a threshold limit to see if this is a rename. For example, have a look at the -M flag for git diff . There are also configuration values such as merge.


1 Answers

Git cannot do this by default.

However, if you have the know-how, you can make it do so by changing the similarity index computation. The relevant code can be found here in diffcore-delta.c (which is well documented) and here in diffcore-rename.c.

Be aware that there are some starting checks and balances involved before Git even checks to see if a file can be considered as renamed (internally). This check will pass with a "yes" answer to the following question:

Is it a regular non-zero sized file that has not significantly changed in file size?

One approach therefore is to add your conditional check before that point so that if there are only differences in whitespace then the similarity index computes to 100% otherwise Git should do what it normally does.

That said, what you experienced is why it often recommended that you rename the file first before changing its contents but names aren't that easy to get right the first time.

like image 184
Fake Code Monkey Rashid Avatar answered Sep 21 '22 10:09

Fake Code Monkey Rashid