Search code examples
gitbashless-unix

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?


Solution

  • Here's a 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.