4

I know I can specify external diff command to be used for git diff:

[diff]
    external = 

But then when I am logged in console (without X) this fails because my visual diff cannot open display (obviously)

How can I tell git to only use visual diff only when logged in GUI/X ?

Martin Vegter
  • 358
  • 75
  • 236
  • 411
  • 2
    See https://stackoverflow.com/questions/14754762/can-gitconfig-options-be-set-conditionally for info on doing conditional configuration. – B Layer Nov 25 '17 at 10:07

2 Answers2

3

There are several simpleminded ways to accomplish this... to do it "outside" git, you can set your difftool program (you probably want difftool instead of diff for launching a visual diff) to a wrapper script which figures out whether you're in a graphical environment or not and launches the appropriate program; or "inside" git, you can do some environment-specific conditional include (includeIf).

2

You asked for an answer drawing from credible and/or official sources so I'm going to cite some official documentation in this answer.

First, we need to find a way to determine if we're running inside X session. We could do that for example by checking if $DISPLAY variable is set. As it's described in man X:

DISPLAY

This is the only mandatory environment variable. It must point to an X server. See section "Display Names" above.

However, it might not be a good idea because someone could just set DISPLAY to a fake value even outside of X. A better way is suggested in this answer:

if xhost >& /dev/null ; then echo "Display exists"
else echo "Display invalid" ; fi

You should have a program named xhost already installed on your machine, make sure you have it:

$ type -a xhost
xhost is /usr/bin/xhost

Now, we could just set diff.external to point to a wrapper that would call an external diff if we're inside X and run the default git diff mechanism if we're not inside X. Unfortunately I'm not able to come up with a simple way to run a default git diff in diff.external so let's instead create an alias for git that would set diff.external temporarily using -c. As described in man git:

-c < name>=< value>

Pass a configuration parameter to the command. The value given will override values from configuration files. The is expected in the same format as listed by git config (subkeys separated by dots).

Note that omitting the = in git -c foo.bar ... is allowed and sets foo.bar to the boolean true value (just like [foo]bar would in a config file). Including the equals but with an empty value (like git -c foo.bar= ...) sets foo.bar to the empty string.

It would be something like:

$ git -c diff.external=diff-wrapper.sh ...

To sum up:

  • Create a script called ~/git-wrapper.sh and replace <YOUR_DIFF_WRAPPER> with whatever you wish:

    #!/usr/bin/env sh
    
    if xhost >/dev/null 2>&1
    then
        git -c diff.external=<YOUR_DIFF_WRAPPER>  "$@"
    else
        git "$@"
    fi
    
  • Set an executable bit:

     $ chmod +x ~/git-wrapper.sh
    
  • Set alias in your shell startup file, for example ~/.bashrc and reload shell:

     alias git=~/git-wrapper.sh
    
  • Use git normally:

     $ git diff
    

    It will use <YOUR_DIFF_WRAPPER> if you're inside X and will use default git-diff outside of X.