1

I run git grep for the first time on a large tree (the Linux kernel).

This takes a long time to run. If I cancel with ctrl+C before it finishes, often it immediately shows a line it found.

Why did git grep not show the line immediately, when it found it?


$ rpm -q git
git-2.17.2-1.fc28.x86_64
2
  • 1
    Yeah, I think it defaults sending the output to less if I am not wrong. Oct 23 '18 at 9:31
  • 1
    By default the output is piped to $GIT_PAGER, or the value of the core.pager config, or $PAGER, or a value chosen at compile time (usually less). Oct 23 '18 at 10:36
4

git grep output is buffered by less. (In most cases. It can be changed using various configuration options, if you need to).

The reason I did not notice this, is that git grep does not show the less pager footer when there is less than one screen of output. However, the output is still buffered. (I can see that less is running, by opening another terminal and running ps -ax).

1
2

In reality, checking sources, git output is not buffered by less all the time.

Checking pager.c, it shows git output is buffered by the program pointed to the PAGER shell variable; if it is not defined, less will be used by omission.

More interestingly yet, while the less output is being paged, it sets the shell GIT_PAGER_IN_USE variable to true. When invoking the pager, it checks for that variable.

As an oddity, it seems it does not like cat as a pager, if it detects it, it blanks it out.

#ifndef DEFAULT_PAGER
#define DEFAULT_PAGER "less"
#endif
....

void setup_pager(void)
{
    const char *pager = git_pager(isatty(1));

    if (!pager)
        return;

    /*
     * After we redirect standard output, we won't be able to use an ioctl
     * to get the terminal size. Let's grab it now, and then set $COLUMNS
     * to communicate it to any sub-processes.
     */
    {
        char buf[64];
        xsnprintf(buf, sizeof(buf), "%d", term_columns());
        setenv("COLUMNS", buf, 0);
    }

    setenv("GIT_PAGER_IN_USE", "true", 1);

    /* spawn the pager */
    prepare_pager_args(&pager_process, pager);
    pager_process.in = -1;
    argv_array_push(&pager_process.env_array, "GIT_PAGER_IN_USE");
    if (start_command(&pager_process))
        return;

    /* original process continues, but writes to the pipe */
    dup2(pager_process.in, 1);
    if (isatty(2))
        dup2(pager_process.in, 2);
    close(pager_process.in);

    /* this makes sure that the parent terminates after the pager */
    sigchain_push_common(wait_for_pager_signal);
    atexit(wait_for_pager_atexit);
}

This site is temporarily in read only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .