203

I like the output formatting of git diff. The color and the +/- representation of changes between lines is easier to read than GNU diff.

I can run git diff using --no-index flag outside of a Git repository, and it works fine. However, it appears to be missing the --exclude option for excluding files or subdirectories from a recursive diff.

Is there a way to get the best of both worlds? (color options and +/- format of git diff and --exclude option of GNU diff).

I've experimented with colordiff, but I still prefer the output format of git diff.

3
  • 1
    To make the blue for additions green, change newtext in /etc/colordiff. I think git uses green? Commented Mar 8, 2015 at 19:45
  • 1
    I had never heard of the --no-index flag until now. I've just used it to compare the output from git show to the diff of two files - thanks for that! Commented Feb 3, 2020 at 14:13
  • Does git diff --no-index still respect Git's "ignore" entries? If so, you could make a wrapper script that temporarily creates a .gitignore file, or maybe there's a way to pass ignore entries on the command-line as inline config or something like that. Commented Feb 24, 2024 at 0:28

15 Answers 15

264

This will do the +/- rather than < and >.

diff -u file1 file2

Since GNU diffutils 3.4 the flag --color has been added. Combining both makes the following:

diff --color -u file1 file2

The flag --color also takes an argument, valid options are never, always, or auto. Useful when you want to be more explicit on what needs to be done.

Sign up to request clarification or add additional context in comments.

9 Comments

Cool, this combined with colordiff gets me close enough to what I want. Guess I need to scroll further down the man page next time... Thanks!
A simple way to get colorization with diff -u, is also to pipe the output to tig, the commandline git repo viewer: diff -u file1 file2 | tig.
Install colordiff from your apt/yum/pacman repository and use it.
Needed to enable Extra Packages for Enterprise Linux (EPEL) on Amazon Linux to install colordiff: docs.aws.amazon.com/AWSEC2/latest/UserGuide/…
Besides colordiff, you can also get color with vim by defining cdiff() { diff -u $@ | vim -R -; }.
|
118

You can also use git diff --no-index -- A B (via the man page).

4 Comments

+1, but sadly this doesn't work if one of the files is a symlink.
+1 This is very useful as it shows how to make git report where two tracked files A and B differ in comparison with each other instead of where each file has been modified relative to their last respective revision.
@EmilLundberg: works for me with symlinks in git 1.9.1 on Linux. I do not know whether earlier versions are broken.
git diff --no-index is great, but as the OP pointed out, it lacks the --exclude flag, so it's often of very limited usefulness.
28
  1. Install colordiff.

  2. Update your ~/.colordiffrc file (copying /etc/colordiffrc first, if necessary):

    # Be more Git-like:
    plain=off
    newtext=darkgreen
    oldtext=darkred
    diffstuff=darkcyan
    
  3. Use colordiff -u file1 file2 for two files or colordiff -ruN path1 path2 for recursively comparing paths.

It's not exactly the same, but it's very close.

1 Comment

As of Ubuntu Jammy, /etc/colordiffrc includes that setup by default.
22

This is what I suggest and it's pretty close

diff -u FILE1 FILE2 | colordiff | less -R
  • colordiff: You'll have to install this
  • -R: this tells Less to show colors instead of the raw codes.

I ultimately used -w because I didn't want to see whitespace diffs.

diff -w -u FILE1 FILE2 | colordiff | less -R

Edit: As suggested by @Ciprian Tomoiaga in the comment, you can make this a function and put it in your ~/.bashrc file too.

function gdiff () { diff -u $@ | colordiff | less -R; }

1 Comment

To have a single bash function for this add to the .bashrc: function gdiff () { diff -u $@ | colordiff | less -R; }
7

GNU diff has a --color option since version 3.4 in late 2016 according to this answer on the Unix SE. That alongside -u should be enough to mimic the output of git diff:

diff -u --color=always file1 file2 | less -r

--color must be always when used in a pipe, auto will turn off color in pipes.

I've only tried this with Git Bash on Windows, where less -R would only color the first line of a hunk. less -r fixed it for me in that case.

Comments

5

Place this in your rc file, most commonly it would be either .bashrc or .zshrc :

diff() { git diff --no-index "$1" "$2" | colordiff; }

requirements : git and colordiff should have been installed.

usage : diff file1 file2

Comments

4

Using only bash, diff, tput, and less, we can closely approximate the output of git diff. There will be some notable differences, though, due to the short-sightedness of the diff programmers.

Put the following Bash function definition in some file that gets sourced automatically by your user account, and you'll be able to access the function from the command line:

function gdiff()
{
    local REG=`tput op`
    local GRP=`tput setaf 6`
    local ADD=`tput setaf 2`
    local REM=`tput setaf 1`

    local NL=$'\n'
    local GRP_LABEL="${GRP}@@ %df,%dn +%dF,%dN @@${REG}"

    local UNCH_GRP_FMT=''

    [[ "${1}" == '@full' ]] && {

        UNCH_GRP_FMT="${GRP_LABEL}${NL}%="
        shift
    }

    diff \
        --new-line-format="${ADD}+%L${REG}" \
        --old-line-format="${REM}-%L${REG}" \
        --unchanged-line-format=" %L${REG}" \
        --new-group-format="${GRP_LABEL}${NL}%>" \
        --old-group-format="${GRP_LABEL}${NL}%<" \
        --changed-group-format="${GRP_LABEL}${NL}%<%>" \
        --unchanged-group-format="${UNCH_GRP_FMT}" \
            "${@}" | less -FXR
}

This function works as follows:

  1. Ultimately, diff gets invoked with various formatting options to specify how changes within the files will be displayed.
  2. tput is used to insert ANSI color codes into those formatting options. Note that when using non-ANSI terminals, you may have to replace tput setaf with tput setf.
  3. The output of diff is piped into less. -R allows ANSI colors to be preserved. -X prevents less from clearing the screen upon exiting. -F prevents less from operating as a pager if the output fits within one screen.
  4. If the first parameter is @full, the function will display all unchanged lines in addition to added and removed lines.

Note the following differences between this approach and git diff:

  1. git diff reports three lines of context surrounding each change. Unfortunately, diff seems to complain and exit if you want to specify the number of context lines while also simultaneously specifying formatting options. (At least it does in Mac OS X Yosemite). Thanks diff programmers. Therefore, you can either request no lines of context surrounding each change, which is the default behavior, or you can request that all unchanged lines within the file are also reported, by specifying @full as the first parameter.
  2. Because the lines of context are different from git diff, the line numbers reported by this function will also vary from those reported by git diff.
  3. You may see the presence of single-line changes reported, which is the correct behavior, but annoying when your changed file contains the insertion of single empty lines. I think git diff deals with this better, via its lines of context. You could try passing different options to diff to better deal with whitespace, if you prefer.

1 Comment

This is a great answer, thanks for sharing. One thing I noticed, is that by piping to less, the return status code from diff is not maintained. Not a big deal, for my use I just removed that bit.
3

Since bat has nice colorizing, I've tested if that works with diff too and surprisingly it worked really well out of the box.

$ diff file1 file2 | bat or $ diff -u file1 file2 | bat

So I suppose you could make a function like this below to be more efficient:

function bdiff () { diff -u $@ | bat;}

Comments

2

You are looking for colordiff:

sudo apt-get install colordiff

Comments

1

If you don't have colordiff or git diff, you can get color by vim.

cdiff() { diff -u $@ | vim -R -; }

or simply

cdiff() { diff -u $@ | view -; }

1 Comment

This may be the best answer for those not using Linux (or GNU utilities)...
1

Tested in debian 9 diff -u --color=always file1 file2

Comments

0

Use colordiff:

Installation:

sudo apt-get install colordiff

Usage:

colordiff -u file_one file_two

Gives exactly same difference as shown by git diff.

Comments

0

add

alias diff="git diff --no-index --"

to ~/.zshrc or ~/.bashrc

This uses git diff to do ordinary diff between two files

Comments

0

The other option is to do it from outside the repository, so Git knows to diff between files. For example, a shell function something like:

gdiff() {
    (
        dir=`pwd`
        cd ./$(git rev-parse --show-cdup)/..
        git diff  $dir/$1 $dir/$2
    )
}

Comments

-3

I think the configuration setting

[color]
     ui = true

combined with "diff" command's --relative=<path> option would do what you wanted. Try it.

1 Comment

This is for the diff in git. He was asking for the diff program options

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.