1

I want git log or git diff to clear the screen when I quit. I followed this instruction and added export LESS="FR" to my .bashrc, so that git does not add the X option to the less command (see pager config). It works as expected when I run git log or git log -10.

But as soon as I run git log -6 (or something lower) nothing is outputted anymore. The reason seems to be the quit-if-one-screen mode. But I do not understand why this happens.

stollr
  • 212

1 Answers1

1

tl;dr

I do not understand why this happens

less without X uses the alternate screen to display its output. If it quits immediately because of F, the alternate screen is displayed for very short time (if ever), effectively as if there was no output at all.


Relevant fragments of man 1 less

(in my Debian 9)

-F or --quit-if-one-screen
Causes less to automatically exit if the entire file can be displayed on the first screen.

-X or --no-init
Disables sending the termcap initialization and deinitialization strings to the terminal. This is sometimes desirable if the deinitialization string does something unnecessary, like clearing the screen.


Preliminary notes

  • The citation does not explicitly state that the behavior or "initialization and deinitialization strings" depend on TERM environment variable. In general it's good to assume any interaction beyond simple reading or echoing does depend on TERM. In case of less it does depend; e.g. with TERM=vt100 you would most likely see no difference between the X option and the lack of it, and your request to "clear the screen when you quit" would not be solved by "not adding the X option to the less command".
  • My tests were done with TERM=screen. I expect many other terminal types to behave similarly. I believe your issue is because your terminal behaves like mine and the rest of my answer applies.
  • When trying the below commands verbatim, you should make sure your terminal is neither too small nor to large. My tests were done in a terminal with 30 lines.

Case 1: neither F nor X

When I do

seq 1 2 | LESS= less

or

seq 1 100 | LESS= less

neither F nor X is specified. The tool uses alternate screen. This is from man 1 xterm:

In VTxxx mode, there are escape sequences to activate and deactivate an alternate screen buffer, which is the same size as the display area of the window. When activated, the current screen is saved and replaced with the alternate screen. Saving of lines scrolled off the top of the window is disabled until the normal screen is restored.

I need to press q to make less leave the alternate screen and exit. The act of going back from the alternate screen to my normal screen is responsible for hiding the output of less. It's simple: the output exists in the alternate screen buffer but not in the normal screen buffer.


Case 2: X only

When I do

seq 1 2 | LESS=X less
# equivalent to
seq 1 2 | LESS= less -X

or

seq 1 100 | LESS=X less
# equivalent to
seq 1 100 | LESS= less -X

the tool does not send "initialization and deinitialization strings to the terminal" that would normally switch buffers. All the output goes to the normal screen. Still I need to press q to exit.


Case 3: both options, F and X

When I do

seq 1 2 | LESS=FX less
# equivalent to
seq 1 2 | LESS= less -FX

or

seq 1 100 | LESS=FX less
# equivalent to
seq 1 100 | LESS= less -FX

the normal screen is used as well. If there are few enough lines, the tool will exit immediately as if I hit q immediately – this is how F works. After the tool exits its output is still visible because it's the normal screen I see all the time.

The answer you linked to states the default options used by Git are FRSX; the config you linked to reads FRX (it has changed after the answer had been published? or the answer was slightly wrong from the start). Anyway there is no doubt this is the case Git uses by default.


Case 4: F only

When I do

seq 1 2 | LESS=F less
# equivalent to
seq 1 2 | LESS= less -F

or

seq 1 100 | LESS=F less
# equivalent to
seq 1 100 | LESS= less -F

the alternate screen is used (like in the 1st case) but if there are few enough lines, less will exit immediately as if I hit q immediately (like in the 3rd case). In effect, if there are few enough lines, I won't see the output at all because the normal screen will be displayed right away. I won't notice the alternate screen; or maybe my terminal emulator or my video hardware won't even display it in the first place, I will see the normal screen on my monitor all the time. The output does not exist in the normal screen buffer. This is what you're experiencing.


Conclusion

You're right, F (or quit-if-one-screen) is crucial here. If you drop X, you should drop F as well. Note the linked answer does this: it goes from FRSX to R (S is responsible for line wrapping, irrelevant to the issue), i.e. it drops both. There's a comment that says "removing only X option is sufficient". My tests indicate the comment is wrong, it leads to the issue you experienced.