Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Let's take the git example:

$ git<TAB><TAB>
git                 git-import-dscs     git-shell
git-buildpackage    git-import-orig     git-upload-archive
git-dch             git-pbuilder        git-upload-pack
git-import-dsc      git-receive-pack    

Notice the after git:

$ git <tab><tab>
add                 fetch               push 
am                  filter-branch       rebase 
annotate            format-patch        reflog 
apply               fsck                relink 
archive             gc                  remote 
bisect              get-tar-commit-id   repack 
blame               grep                replace 
branch              help                request-pull 
buildpackage        imap-send           reset 
bundle              import-dsc          revert 
checkout            import-dscs         rm 
cherry              import-orig         shortlog 
cherry-pick         init                show 
clean               instaweb            show-branch 
clone               log                 stage 
column              merge               stash 
commit              mergetool           status 
config              mv                  submodule 
credential          name-rev            subtree 

Writing git re

$ git re<tab><tab>
rebase         relink         repack         request-pull   revert 
reflog         remote         replace        reset          

$ git remote <tab><tab>
add            remove         set-branches   set-url        update 
prune          rename         set-head       show           


$ command <tab> 

How can I get these actions programmatically? Is this possible via a shell/bash script?

share|improve this question

2 Answers 2

up vote 8 down vote accepted

This facility is being done by what's called Bash Completion. The files that back this are stored under /etc/bash_completion.d with each command having its own file. So in the git case:


If you look at this file you'll notice that it's overloading your environment with extra functions. One in particular is this guy:

$ __git_commands

When you run it you'll get the list of sub-commands.

$ __git_commands | head -5
  add                       merge-recursive
  add--interactive          merge-resolve
  am                        merge-subtree
  annotate                  merge-tree
  apply                     mergetool

Knowing that these are simply functions in your environment you can do this:

$ __git<tab><tab>
__git_aliased_command                __git_complete_remote_or_refspec     __git_diff_index_files               __git_index_files                    __git_refs
__git_aliases                        __git_complete_revlist               __git_diff_index_helper              __gitk_main                          __git_refs2
__git_commands                       __git_complete_revlist_file          __gitdir                             __git_list_all_commands              __git_refs_remotes
__gitcomp                            __git_complete_strategy              __git_find_on_cmdline                __git_list_merge_strategies          __git_remotes
__gitcompadd                         __gitcomp_nl                         __git_func_wrap                      __git_list_porcelain_commands        __git_tags
__gitcomp_file                       __git_compute_all_commands           __git_has_doubledash                 __git_ls_files_helper                __git_wrap__gitk_main
__git_complete                       __git_compute_merge_strategies       __git_heads                          __git_main                           __git_wrap__git_main
__git_complete_diff_index_file       __git_compute_porcelain_commands     __git_index_file_list_filter         __git_match_ctag                     
__git_complete_file                  __git_config_get_set_variables       __git_index_file_list_filter_bash    __git_pretty_aliases                 
__git_complete_index_file            __git_count_arguments                __git_index_file_list_filter_compat  __git_reassemble_comp_words_by_ref   

To get a list of all the Bash Completion functions which give various info about git the command.

share|improve this answer
Wow, that's really great! But your example doesn't work on my Ubuntu 14.04 Beta: I have only $ __git_ps1 completions: __git_ps1 __git_ps1_colorize_gitstring __git_ps1_show_upstream. Why? –  Ionică Bizău Apr 11 at 10:10
@IonicăBizău - I'm on Fedora 19. Can you confirm the existence of the file /usr/share/bash-completion/completions/git? I only have a 12.04 Ubuntu which has the files in the same location as my Fedora system. My 12.04 also has the same functions as I described above. –  slm Apr 11 at 10:13
vim /usr/share/bash-completion/completions/git opens the file that contains bash/zsh completion support for core Git.. How can I use this one? –  Ionică Bizău Apr 11 at 10:25
@IonicăBizău - that's the correct file. I have the same header as well. In a pinch you can source them: source <file>. But since you can do the git<tab><tab> it would seem to be already working. –  slm Apr 11 at 10:29
It works fine after running source <path>. Thanks! –  Ionică Bizău Apr 11 at 10:37

What you are looking at here is called programmable completion. On Debian/Ubunutu based systems, packages will often install a file to /usr/share/bash-completion/completions which provides the programmable completion for the command. On other distributions the /etc/bash_completion.d directory may be used (this location is deprecated on Debian/Ubuntu, but some packages still use it). For me the file containing the functions which generate the completions for git is /usr/share/bash-completion/completions/.

The basic process is that functions are defined which generate content for the COMPREPLY shell array, these are then registered to particular commands using the complete shell built-in.

If you want to alter the way the completion works, it is best not to change these files directly since any changes may be clobbered by system updates, but rather to create new versions of the necessary functions in a user specific location such as .bashrc in the home directory.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.