Skip to content

Instantly share code, notes, and snippets.

@0xdevalias
Created January 17, 2023 02:42
Show Gist options
  • Save 0xdevalias/1245fe66ac6953d490114b417a0075e3 to your computer and use it in GitHub Desktop.
Save 0xdevalias/1245fe66ac6953d490114b417a0075e3 to your computer and use it in GitHub Desktop.
Some tips/tricks/hacks for working with git diff --color-moved to simplify refactor code reviews

Originally posted at community/community#9632 (comment)


Omg yes, please! This is one of my biggest pet peeves/code review slowdowns when performing large refactors to cleanup a legacy codebase.

The following were some manual review notes/commands I added to a recent PR to assist others who were reviewing:

The following git diff command will make it easier to see what actually changed in the code here, as opposed to what just moved around without being changed; to make review/etc easier. Dimmed code in the diff has been moved, but not changed.

This will get all the changes made in this branch, using devalias/improve-first-use as the base:

git \
  -c color.diff.oldMoved="white dim" \
  -c color.diff.oldMovedAlternative="white dim" \
  -c color.diff.newMoved="white dim" \
  -c color.diff.newMovedAlternative="white dim" \
  -c color.diff.newMovedDimmed="white dim" \
  -c color.diff.newMovedAlternativeDimmed="white dim" \
  diff --color-moved=dimmed-zebra --color-moved-ws=ignore-all-space --minimal \
  devalias/improve-first-use HEAD

This will get all changes made for a specific commit hash (55a259f), as compared to the commit hash just before it (55a259f~):

git \
  -c color.diff.oldMoved="white dim" \
  -c color.diff.oldMovedAlternative="white dim" \
  -c color.diff.newMoved="white dim" \
  -c color.diff.newMovedAlternative="white dim" \
  -c color.diff.newMovedDimmed="white dim" \
  -c color.diff.newMovedAlternativeDimmed="white dim" \
  diff --color-moved=dimmed-zebra --color-moved-ws=ignore-all-space --minimal \
  55a259f~ 55a259f

This will get all changes made for a specific commit hash (55a259f), as compared to the commit hash just before it (55a259f~), only for the specific file/path specified:

git \
  -c color.diff.oldMoved="white dim" \
  -c color.diff.oldMovedAlternative="white dim" \
  -c color.diff.newMoved="white dim" \
  -c color.diff.newMovedAlternative="white dim" \
  -c color.diff.newMovedDimmed="white dim" \
  -c color.diff.newMovedAlternativeDimmed="white dim" \
  diff --color-moved=dimmed-zebra --color-moved-ws=ignore-all-space --minimal \
  55a259f~ 55a259f -- oauth/vendor/slack/index.js

You can simplify this for future use by adding it to your git aliases in your ~/.gitconfig, something like the following:

[alias]
  diff-refactor = \
    -c color.diff.oldMoved='white dim' \
    -c color.diff.oldMovedAlternative='white dim' \
    -c color.diff.newMoved='white dim' \
    -c color.diff.newMovedAlternative='white dim' \
    -c color.diff.newMovedDimmed='white dim' \
    -c color.diff.newMovedAlternativeDimmed='white dim' \
    diff --ignore-blank-lines --color-moved=dimmed-zebra --color-moved-ws=ignore-all-space --minimal

Which would then allow you to use it as just:

⇒ git diff-refactor

⇒ git diff-refactor devalias/improve-first-use HEAD

⇒ git diff-refactor 55a259f~ 55a259f

⇒ git diff-refactor 55a259f~ 55a259f -- oauth/vendor/slack/index.js

You could potentially add the following as well, though i'm not sure if they will do anything new/useful when combined with --color-moved:

--ignore-all-space --ignore-space-change --ignore-space-at-eol --ignore-cr-at-eol --ignore-blank-lines

I wonder how hard it would be to take the output from git diff --color-moved, parse it, and then render it in a GitHub comment/similar..?

Some potentially useful references:


Super hacky, but this uses sed to try and strip out parts of the diff based on the color codes:

git \
  -c color.diff.oldMoved='white dim' \
  -c color.diff.oldMovedAlternative='white dim' \
  -c color.diff.newMoved='white dim' \
  -c color.diff.newMovedAlternative='white dim' \
  -c color.diff.newMovedDimmed='white dim' \
  -c color.diff.newMovedAlternativeDimmed='white dim' \
  diff --ignore-blank-lines --color-moved=dimmed-zebra --color-moved-ws=ignore-all-space --minimal --color HEAD~1 HEAD | sed -r "s/\x1B\[2;37m\+(.*)\x1B\[m/\1/g" | sed -r "s/\x1B\[2m-(.*)\x1B\[m/\1/g" | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g"

Strip 'dim white' +:

sed -r "s/\x1B\[2;37m\+(.*)\x1B\[m/\1/g"

Strip 'dim' -, keeping the content between:

sed -r "s/\x1B\[2m-(.*)\x1B\[m/\1/g"

Strip all colour codes:

sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g"

If we then put that colour stripped output into a standard GitHub code block with diff formatting, it will only use the + and - lines to determine the colouring to show, and so will highlight the 'actual' changes in red/green.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment