How does `man git init` get the right man page

man

So it seems that typing man git init into a bash prompt on an Ubuntu 14.04 system does the same as man git-init, only I'm not quite sure how.

The man page for man (i.e. man man) doesn't seem to allow for this construct, unless git was a section of the manual, but the man page seems to come from section 1.

Is this an undocumented usage supported by man? Have I misunderstood the documentation of man? Is some other magic happening? Anyone care to explain?

Best Answer

Some implementations of man, including the one used by Ubuntu, replace spaces in its search terms with hyphens and attempt to find a manual page under that name. So man git init looks for the same thing as man git-init. Similarly, man run parts and man ntfs 3g work (if you have run-parts and ntfs-3g on your system).

It only does this with word pairs, though, so man git annex sync does not work (though man git-annex sync does, as that's again a word pair).

In fact, when you ask for two manual pages (e.g., man git bash to see both the git and bash manpages), man actually first tries to look for a git-bash manpage. You can see this in the debug output if you enable it with -d.

This man feature is called "subpages" you can read the source code implementing subpages in man-db (thanks, Stephen Kitt). Searching the man(1) manpage for "subpages" will also lead you to the description of this behavior under the --no-subpages option:

--no-subpages
      By default, man will try to interpret pairs of manual page
      names given on the command line as equivalent to a single
      manual page name containing a hyphen or an underscore.  This
      supports the common pattern of programs that implement a
      number of subcommands, allowing them to provide manual pages
      for each that can be accessed using similar syntax as would be
      used to invoke the subcommands themselves.  For example:

        $ man -aw git diff
        /usr/share/man/man1/git-diff.1.gz

      To disable this behaviour, use the --no-subpages option.

        $ man -aw --no-subpages git diff
        /usr/share/man/man1/git.1.gz
        /usr/share/man/man3/Git.3pm.gz
        /usr/share/man/man1/diff.1.gz
Related Question