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?
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.
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!
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).
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With