git: change styling (whitespace) without changing ownership/blame?
Asked Answered
S

5

49

We have a massive, ancient codebase that needs a lot of cleanup. We have always had coding standards and everyone has always tried to follow them, but they were not enforced so over time a lot of violations have creeped in. Many of them are just whitespace issues, like using tabs instead of spaces, or spaces where there shouldn't be any, or missing spaces where they should be. We are going to start actively enforcing our coding standards to make sure more violations don't creep in, but it's difficult to enforce them in an automated way on only the changes, so it would be nice to clean up these old files.

There are tools that can automate fixing these issues, however if I do that then blame is going to show me as the owner of those lines, when in reality I may never have even seen them. I know there is a setting to make blame ignore whitespace changes, but I can't make everyone use blame the same way, including other visual tools and things like gitstats. In an ideal world there would be some way to rewrite history to look like the violations were never introduced, without covering up who introduced the actual code, but I can't find anything like that.

Salley answered 6/11, 2010 at 8:12 Comment(4)
Rewriting history is a bit awkward - once you change the commits, others are going to have to pick up those changes. Not part of an ideal workflow. You might want to look into enforcing your coding standards using hooks. You can use an update hook to do the final enforcement when pushing to a central repo, and you can give developers a pre-commit hook to do the same validation for them, and even automatically fix things if it's safe to do so. (If you want to fix what's already there, I'd just do it in a single commit - no need to go through the headache of rewriting the entire history.)Voltammeter
possible duplicate of Git commit that doesn't override original authors in git blameBanc
I don't think this is exactly a duplicate of that question. In my question I specifically stated that changing the flags on blame is not adequate, and the accepted answer to that question is exactly that.Salley
Related: How do I run a code formatter over my source without modifying git history?Stomatal
D
24

In an ideal world there would be some way to rewrite history to look like the violations were never introduced

git filter-branch does precisely that.

http://git-scm.com/docs/git-filter-branch

This has the same issues as all history rewriting commands do, as it essentially invalidates all cloned repositories.

Datura answered 6/11, 2010 at 8:17 Comment(4)
Thanks, looking into this now!Salley
Got it working! git filter-branch --tree-filter 'git diff-tree --name-only --diff-filter=AM -r --no-commit-id $GIT_COMMIT | php cleanup.php' HEADSalley
how does your cleanup.php look like?Esau
What if my whitespace cleanup can't be done by a script? (E.g. space indentation is used inconsistently.)Vanthe
R
42

If you are trying to get a Root Cause issue using blame, don't forget use the -w flag to ignore all the white-spaces or indentation changes. So you'll get the last real change to the code, instead just an indentation, or removing trailing spaces.

git blame -w app/to/file.rb

or you can just use, git slap command..

git config alias.slap "blame -w";
git slap app/path/to/file.rb

having same results :D

Remembrancer answered 22/11, 2010 at 19:47 Comment(2)
@ErikAllik I'm not sure what you mean, but one line before git slap is used, it's defined as an alias for git blame -w.Rowena
One of the downsides to the -w whitespace argument is that it does take into account refactoring the order of methods, removal of loose comments, and so many more things.Loxodromic
D
24

In an ideal world there would be some way to rewrite history to look like the violations were never introduced

git filter-branch does precisely that.

http://git-scm.com/docs/git-filter-branch

This has the same issues as all history rewriting commands do, as it essentially invalidates all cloned repositories.

Datura answered 6/11, 2010 at 8:17 Comment(4)
Thanks, looking into this now!Salley
Got it working! git filter-branch --tree-filter 'git diff-tree --name-only --diff-filter=AM -r --no-commit-id $GIT_COMMIT | php cleanup.php' HEADSalley
how does your cleanup.php look like?Esau
What if my whitespace cleanup can't be done by a script? (E.g. space indentation is used inconsistently.)Vanthe
R
15

Building on Mario's answer, I would suggest git shame as a global git-alias:

git config --global alias.shame 'blame -w -M'

...and use it instead of git-blame:

git shame path/to/file

To explain:

  • -w Ignores whitespace changes, so not to blame someone who re-indented the code
  • -M Detects lines that were moved or copied, and blames the original author

EDIT:

Some argue that the -M is misleading, blaming the wrong person
(i.e.: don't blame me if someone rearranged what I wrote).
If you feel the same, please use the original suggestion: git slap

Rotenone answered 29/6, 2017 at 14:3 Comment(0)
W
1

I did a pull request to the TextMate git Bundle, to set this "-w" parameter by default for the "Browse Annoted File (Blame)" command. Thanks Mario Zaizar, you made my day.

diff --git a/Support/lib/git.rb b/Support/lib/git.rb
index 5e8de13..5192953 100644
--- a/Support/lib/git.rb
+++ b/Support/lib/git.rb
@@ -307,6 +307,9 @@ module SCM
       file = make_local_path(file_path)
       args = [file]
       args << revision unless revision.nil? || revision.empty?
+      # Ignore whitespace when comparing the parent's version and
+      # the child's to find where the lines came from.
+      args << '-w'
       output = command("annotate", *args)
       if output.match(/^fatal:/)
         puts output 
Whine answered 17/12, 2010 at 13:1 Comment(0)
M
0

For those using the VCS annotations feature in JetBrains IDEs to see the git blame output, you can set the -w (ignore whitespace), -M (detect moved or copied lines within a file) and -C (detect moved or copied lines across files) flags as follows:

Configure annotation options

  • Right-click the annotations gutter and select Options from the context menu

Source: IntelliJ docs

Madrigalist answered 25/1, 2020 at 9:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.