Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Don't automatically terminate git diff if changes are on one page

If I run git diff, and my changes are less than one page, the command will automatically exit. This is undesired because this is in a script and I immediately call git commit afterwards. This causes single page changelogs to be missed.

My first thought would be to pipe the differences into less, but this causes no differences changelogs to display an empty screen (which requires a q press to exit). Here is the command I'm using: git diff --color=always | less.

Is there some better way to do this?

like image 962
Chris Smith Avatar asked Feb 07 '23 03:02

Chris Smith


2 Answers

Here's a bash script to do the job:

#!/bin/bash

num_lines=$(git diff | wc -l)

if [ $num_lines -eq 0 ]
then
  echo "No changes"
else
  git diff --color=always | less --raw-control-chars
fi

Or, here's a one-liner originally based on @Phillip's comment, with some fixes thanks to @tripleee:

git diff --color=always | (IFS=$'\n' read -r A; if [ -n "$A" ]; then (printf '%s\n' "$A"; cat) | less --raw-control-chars; else echo "No changes"; fi)

The one-liner has the advantage of only running git diff once for better performance.

Some explanation per @tripleee's comment:

You should properly use read -r to not unintentionally mangle the first line. This will still mangle leading or trailing whitespace. You can fix that with IFS=$'\n' before read -r. echo might throw an error or behave strangely if the first line starts with a dash (which looks to echo like an option argument) -- use printf '%s\n' "$A" instead to avoid that.

In both cases, the --raw-control-chars option (short version -r) passed to less will cause the colors to show up correctly.

like image 196
Scott Weldon Avatar answered Feb 09 '23 10:02

Scott Weldon


What you are seeing is less being invoked with the -F option by git. Normally, less uses any options stored in the environment variable LESS. If that variable is not set, git automatically sets it to FRX before running less. (That is, without a value for LESS, git effectively is running less -FRX.)

One way to override this is to add the following to your .gitconfig file:

[core]
    pager = less -+F

If LESS is not set, then the preceding configuration causes less to be called as

LESS=FRX less -+F

meaning the -F option is first enabled via the environment in which less runs, then immediately disabled from the command line.

(In my comment to your question, I indicated that less should not be exiting early. I observed that because I in fact have LESS=X in my environment, so I did not have -F added automatically.)

like image 24
chepner Avatar answered Feb 09 '23 12:02

chepner