Teach bash about git-repo-config.
[git/gitweb.git] / contrib / completion / git-completion.bash
blob73c67691c928bcb7fa0b72e0179f74df11a087c2
2 # bash completion support for core Git.
4 # Copyright (C) 2006 Shawn Pearce
5 # Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).
7 # The contained completion routines provide support for completing:
9 # *) local and remote branch names
10 # *) local and remote tag names
11 # *) .git/remotes file names
12 # *) git 'subcommands'
13 # *) tree paths within 'ref:path/to/file' expressions
15 # To use these routines:
17 # 1) Copy this file to somewhere (e.g. ~/.git-completion.sh).
18 # 2) Added the following line to your .bashrc:
19 # source ~/.git-completion.sh
21 # 3) Consider changing your PS1 to also show the current branch:
22 # PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
24 # The argument to __git_ps1 will be displayed only if you
25 # are currently in a git repository. The %s token will be
26 # the name of the current branch.
29 __gitdir ()
31 echo "${__git_dir:-$(git rev-parse --git-dir 2>/dev/null)}"
34 __git_ps1 ()
36 local b="$(git symbolic-ref HEAD 2>/dev/null)"
37 if [ -n "$b" ]; then
38 if [ -n "$1" ]; then
39 printf "$1" "${b##refs/heads/}"
40 else
41 printf " (%s)" "${b##refs/heads/}"
46 __git_heads ()
48 local cmd i is_hash=y dir="${1:-$(__gitdir)}"
49 if [ -d "$dir" ]; then
50 for i in $(git --git-dir="$dir" \
51 for-each-ref --format='%(refname)' \
52 refs/heads ); do
53 echo "${i#refs/heads/}"
54 done
55 return
57 for i in $(git-ls-remote "$dir" 2>/dev/null); do
58 case "$is_hash,$i" in
59 y,*) is_hash=n ;;
60 n,*^{}) is_hash=y ;;
61 n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;;
62 n,*) is_hash=y; echo "$i" ;;
63 esac
64 done
67 __git_refs ()
69 local cmd i is_hash=y dir="${1:-$(__gitdir)}"
70 if [ -d "$dir" ]; then
71 if [ -e "$dir/HEAD" ]; then echo HEAD; fi
72 for i in $(git --git-dir="$dir" \
73 for-each-ref --format='%(refname)' \
74 refs/tags refs/heads refs/remotes); do
75 case "$i" in
76 refs/tags/*) echo "${i#refs/tags/}" ;;
77 refs/heads/*) echo "${i#refs/heads/}" ;;
78 refs/remotes/*) echo "${i#refs/remotes/}" ;;
79 *) echo "$i" ;;
80 esac
81 done
82 return
84 for i in $(git-ls-remote "$dir" 2>/dev/null); do
85 case "$is_hash,$i" in
86 y,*) is_hash=n ;;
87 n,*^{}) is_hash=y ;;
88 n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}" ;;
89 n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}" ;;
90 n,refs/remotes/*) is_hash=y; echo "${i#refs/remotes/}" ;;
91 n,*) is_hash=y; echo "$i" ;;
92 esac
93 done
96 __git_refs2 ()
98 local cmd i is_hash=y dir="${1:-$(__gitdir)}"
99 if [ -d "$dir" ]; then
100 cmd=git-peek-remote
101 else
102 cmd=git-ls-remote
104 for i in $($cmd "$dir" 2>/dev/null); do
105 case "$is_hash,$i" in
106 y,*) is_hash=n ;;
107 n,*^{}) is_hash=y ;;
108 n,refs/tags/*) is_hash=y; echo "${i#refs/tags/}:${i#refs/tags/}" ;;
109 n,refs/heads/*) is_hash=y; echo "${i#refs/heads/}:${i#refs/heads/}" ;;
110 n,*) is_hash=y; echo "$i:$i" ;;
111 esac
112 done
115 __git_refs_remotes ()
117 local cmd i is_hash=y
118 for i in $(git-ls-remote "$1" 2>/dev/null); do
119 case "$is_hash,$i" in
120 n,refs/heads/*)
121 is_hash=y
122 echo "$i:refs/remotes/$1/${i#refs/heads/}"
124 y,*) is_hash=n ;;
125 n,*^{}) is_hash=y ;;
126 n,refs/tags/*) is_hash=y;;
127 n,*) is_hash=y; ;;
128 esac
129 done
132 __git_remotes ()
134 local i ngoff IFS=$'\n' d="$(__gitdir)"
135 shopt -q nullglob || ngoff=1
136 shopt -s nullglob
137 for i in "$d/remotes"/*; do
138 echo ${i#$d/remotes/}
139 done
140 [ "$ngoff" ] && shopt -u nullglob
141 for i in $(git --git-dir="$d" repo-config --list); do
142 case "$i" in
143 remote.*.url=*)
144 i="${i#remote.}"
145 echo "${i/.url=*/}"
147 esac
148 done
151 __git_merge_strategies ()
153 sed -n "/^all_strategies='/{
154 s/^all_strategies='//
155 s/'//
158 }" "$(git --exec-path)/git-merge"
161 __git_complete_file ()
163 local pfx ls ref cur="${COMP_WORDS[COMP_CWORD]}"
164 case "$cur" in
165 ?*:*)
166 ref="${cur%%:*}"
167 cur="${cur#*:}"
168 case "$cur" in
169 ?*/*)
170 pfx="${cur%/*}"
171 cur="${cur##*/}"
172 ls="$ref:$pfx"
173 pfx="$pfx/"
176 ls="$ref"
178 esac
179 COMPREPLY=($(compgen -P "$pfx" \
180 -W "$(git --git-dir="$(__gitdir)" ls-tree "$ls" \
181 | sed '/^100... blob /s,^.* ,,
182 /^040000 tree /{
183 s,^.* ,,
184 s,$,/,
186 s/^.* //')" \
187 -- "$cur"))
190 COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
192 esac
195 __git_complete_revlist ()
197 local pfx cur="${COMP_WORDS[COMP_CWORD]}"
198 case "$cur" in
199 *...*)
200 pfx="${cur%...*}..."
201 cur="${cur#*...}"
202 COMPREPLY=($(compgen -P "$pfx" -W "$(__git_refs)" -- "$cur"))
204 *..*)
205 pfx="${cur%..*}.."
206 cur="${cur#*..}"
207 COMPREPLY=($(compgen -P "$pfx" -W "$(__git_refs)" -- "$cur"))
210 COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
212 esac
215 __git_commands ()
217 local i IFS=" "$'\n'
218 for i in $(git help -a|egrep '^ ')
220 case $i in
221 check-ref-format) : plumbing;;
222 commit-tree) : plumbing;;
223 convert-objects) : plumbing;;
224 cvsserver) : daemon;;
225 daemon) : daemon;;
226 fetch-pack) : plumbing;;
227 hash-object) : plumbing;;
228 http-*) : transport;;
229 index-pack) : plumbing;;
230 local-fetch) : plumbing;;
231 mailinfo) : plumbing;;
232 mailsplit) : plumbing;;
233 merge-*) : plumbing;;
234 mktree) : plumbing;;
235 mktag) : plumbing;;
236 pack-objects) : plumbing;;
237 pack-redundant) : plumbing;;
238 pack-refs) : plumbing;;
239 parse-remote) : plumbing;;
240 patch-id) : plumbing;;
241 peek-remote) : plumbing;;
242 read-tree) : plumbing;;
243 receive-pack) : plumbing;;
244 rerere) : plumbing;;
245 rev-list) : plumbing;;
246 rev-parse) : plumbing;;
247 runstatus) : plumbing;;
248 sh-setup) : internal;;
249 shell) : daemon;;
250 send-pack) : plumbing;;
251 show-index) : plumbing;;
252 ssh-*) : transport;;
253 stripspace) : plumbing;;
254 symbolic-ref) : plumbing;;
255 unpack-file) : plumbing;;
256 unpack-objects) : plumbing;;
257 update-ref) : plumbing;;
258 update-server-info) : daemon;;
259 upload-archive) : plumbing;;
260 upload-pack) : plumbing;;
261 write-tree) : plumbing;;
262 *) echo $i;;
263 esac
264 done
267 __git_aliases ()
269 local i IFS=$'\n'
270 for i in $(git --git-dir="$(__gitdir)" repo-config --list); do
271 case "$i" in
272 alias.*)
273 i="${i#alias.}"
274 echo "${i/=*/}"
276 esac
277 done
280 __git_aliased_command ()
282 local word cmdline=$(git --git-dir="$(__gitdir)" \
283 repo-config --get "alias.$1")
284 for word in $cmdline; do
285 if [ "${word##-*}" ]; then
286 echo $word
287 return
289 done
292 _git_branch ()
294 local cur="${COMP_WORDS[COMP_CWORD]}"
295 COMPREPLY=($(compgen -W "-l -f -d -D $(__git_refs)" -- "$cur"))
298 _git_cat_file ()
300 local cur="${COMP_WORDS[COMP_CWORD]}"
301 case "${COMP_WORDS[0]},$COMP_CWORD" in
302 git-cat-file*,1)
303 COMPREPLY=($(compgen -W "-p -t blob tree commit tag" -- "$cur"))
305 git,2)
306 COMPREPLY=($(compgen -W "-p -t blob tree commit tag" -- "$cur"))
309 __git_complete_file
311 esac
314 _git_checkout ()
316 local cur="${COMP_WORDS[COMP_CWORD]}"
317 COMPREPLY=($(compgen -W "-l -b $(__git_refs)" -- "$cur"))
320 _git_cherry_pick ()
322 local cur="${COMP_WORDS[COMP_CWORD]}"
323 case "$cur" in
324 --*)
325 COMPREPLY=($(compgen -W "
326 --edit --no-commit
327 " -- "$cur"))
330 COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
332 esac
335 _git_diff ()
337 __git_complete_file
340 _git_diff_tree ()
342 local cur="${COMP_WORDS[COMP_CWORD]}"
343 COMPREPLY=($(compgen -W "-r -p -M $(__git_refs)" -- "$cur"))
346 _git_fetch ()
348 local cur="${COMP_WORDS[COMP_CWORD]}"
350 case "${COMP_WORDS[0]},$COMP_CWORD" in
351 git-fetch*,1)
352 COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
354 git,2)
355 COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
358 case "$cur" in
359 *:*)
360 cur="${cur#*:}"
361 COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
364 local remote
365 case "${COMP_WORDS[0]}" in
366 git-fetch) remote="${COMP_WORDS[1]}" ;;
367 git) remote="${COMP_WORDS[2]}" ;;
368 esac
369 COMPREPLY=($(compgen -W "$(__git_refs2 "$remote")" -- "$cur"))
371 esac
373 esac
376 _git_format_patch ()
378 local cur="${COMP_WORDS[COMP_CWORD]}"
379 case "$cur" in
380 --*)
381 COMPREPLY=($(compgen -W "
382 --stdout --attach --thread
383 --output-directory
384 --numbered --start-number
385 --keep-subject
386 --signoff
387 --in-reply-to=
388 --full-index --binary
389 " -- "$cur"))
390 return
392 esac
393 __git_complete_revlist
396 _git_ls_remote ()
398 local cur="${COMP_WORDS[COMP_CWORD]}"
399 COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
402 _git_ls_tree ()
404 __git_complete_file
407 _git_log ()
409 local cur="${COMP_WORDS[COMP_CWORD]}"
410 case "$cur" in
411 --pretty=*)
412 COMPREPLY=($(compgen -W "
413 oneline short medium full fuller email raw
414 " -- "${cur##--pretty=}"))
415 return
417 --*)
418 COMPREPLY=($(compgen -W "
419 --max-count= --max-age= --since= --after=
420 --min-age= --before= --until=
421 --root --not --topo-order --date-order
422 --no-merges
423 --abbrev-commit --abbrev=
424 --relative-date
425 --author= --committer= --grep=
426 --all-match
427 --pretty= --name-status --name-only
428 " -- "$cur"))
429 return
431 esac
432 __git_complete_revlist
435 _git_merge ()
437 local cur="${COMP_WORDS[COMP_CWORD]}"
438 case "$cur" in
439 --*)
440 COMPREPLY=($(compgen -W "
441 --no-commit --no-summary --squash --strategy
442 " -- "$cur"))
443 return
444 esac
445 case "${COMP_WORDS[COMP_CWORD-1]}" in
446 -s|--strategy)
447 COMPREPLY=($(compgen -W "$(__git_merge_strategies)" -- "$cur"))
448 return
449 esac
450 COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
453 _git_merge_base ()
455 local cur="${COMP_WORDS[COMP_CWORD]}"
456 COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
459 _git_name_rev ()
461 local cur="${COMP_WORDS[COMP_CWORD]}"
462 COMPREPLY=($(compgen -W "--tags --all --stdin" -- "$cur"))
465 _git_pull ()
467 local cur="${COMP_WORDS[COMP_CWORD]}"
469 case "${COMP_WORDS[0]},$COMP_CWORD" in
470 git-pull*,1)
471 COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
473 git,2)
474 COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
477 local remote
478 case "${COMP_WORDS[0]}" in
479 git-pull) remote="${COMP_WORDS[1]}" ;;
480 git) remote="${COMP_WORDS[2]}" ;;
481 esac
482 COMPREPLY=($(compgen -W "$(__git_refs "$remote")" -- "$cur"))
484 esac
487 _git_push ()
489 local cur="${COMP_WORDS[COMP_CWORD]}"
491 case "${COMP_WORDS[0]},$COMP_CWORD" in
492 git-push*,1)
493 COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
495 git,2)
496 COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
499 case "$cur" in
500 *:*)
501 local remote
502 case "${COMP_WORDS[0]}" in
503 git-push) remote="${COMP_WORDS[1]}" ;;
504 git) remote="${COMP_WORDS[2]}" ;;
505 esac
506 cur="${cur#*:}"
507 COMPREPLY=($(compgen -W "$(__git_refs "$remote")" -- "$cur"))
510 COMPREPLY=($(compgen -W "$(__git_refs2)" -- "$cur"))
512 esac
514 esac
517 _git_rebase ()
519 local cur="${COMP_WORDS[COMP_CWORD]}"
520 if [ -d .dotest ]; then
521 COMPREPLY=($(compgen -W "
522 --continue --skip --abort
523 " -- "$cur"))
524 return
526 case "$cur" in
527 --*)
528 COMPREPLY=($(compgen -W "
529 --onto --merge --strategy
530 " -- "$cur"))
531 return
532 esac
533 case "${COMP_WORDS[COMP_CWORD-1]}" in
534 -s|--strategy)
535 COMPREPLY=($(compgen -W "$(__git_merge_strategies)" -- "$cur"))
536 return
537 esac
538 COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
541 _git_repo_config ()
543 local cur="${COMP_WORDS[COMP_CWORD]}"
544 local prv="${COMP_WORDS[COMP_CWORD-1]}"
545 case "$prv" in
546 branch.*.remote)
547 COMPREPLY=($(compgen -W "$(__git_remotes)" -- "$cur"))
548 return
550 branch.*.merge)
551 COMPREPLY=($(compgen -W "$(__git_refs)" -- "$cur"))
552 return
554 remote.*.fetch)
555 local remote="${prv#remote.}"
556 remote="${remote%.fetch}"
557 COMPREPLY=($(compgen -W "$(__git_refs_remotes "$remote")" \
558 -- "$cur"))
559 return
561 remote.*.push)
562 local remote="${prv#remote.}"
563 remote="${remote%.push}"
564 COMPREPLY=($(compgen -W "$(git --git-dir="$(__gitdir)" \
565 for-each-ref --format='%(refname):%(refname)' \
566 refs/heads)" -- "$cur"))
567 return
569 *.*)
570 COMPREPLY=()
571 return
573 esac
574 case "$cur" in
575 --*)
576 COMPREPLY=($(compgen -W "
577 --global --list --replace-all
578 --get --get-all --get-regexp
579 --unset --unset-all
580 " -- "$cur"))
581 return
583 branch.*.*)
584 local pfx="${cur%.*}."
585 cur="${cur##*.}"
586 COMPREPLY=($(compgen -P "$pfx" -W "remote merge" -- "$cur"))
587 return
589 branch.*)
590 local pfx="${cur%.*}."
591 cur="${cur#*.}"
592 COMPREPLY=($(compgen -P "$pfx" -S . \
593 -W "$(__git_heads)" -- "$cur"))
594 return
596 remote.*.*)
597 local pfx="${cur%.*}."
598 cur="${cur##*.}"
599 COMPREPLY=($(compgen -P "$pfx" -W "url fetch push" -- "$cur"))
600 return
602 remote.*)
603 local pfx="${cur%.*}."
604 cur="${cur#*.}"
605 COMPREPLY=($(compgen -P "$pfx" -S . \
606 -W "$(__git_remotes)" -- "$cur"))
607 return
609 esac
610 COMPREPLY=($(compgen -W "
611 apply.whitespace
612 core.fileMode
613 core.gitProxy
614 core.ignoreStat
615 core.preferSymlinkRefs
616 core.logAllRefUpdates
617 core.repositoryFormatVersion
618 core.sharedRepository
619 core.warnAmbiguousRefs
620 core.compression
621 core.legacyHeaders
622 i18n.commitEncoding
623 diff.color
624 diff.renameLimit
625 diff.renames
626 pager.color
627 status.color
628 log.showroot
629 show.difftree
630 showbranch.default
631 whatchanged.difftree
632 http.sslVerify
633 http.sslCert
634 http.sslKey
635 http.sslCAInfo
636 http.sslCAPath
637 http.maxRequests
638 http.lowSpeedLimit http.lowSpeedTime
639 http.noEPSV
640 pack.window
641 repack.useDeltaBaseOffset
642 pull.octopus pull.twohead
643 merge.summary
644 receive.unpackLimit
645 receive.denyNonFastForwards
646 user.name user.email
647 tar.umask
648 gitcvs.enabled
649 gitcvs.logfile
650 branch. remote.
651 " -- "$cur"))
654 _git_reset ()
656 local cur="${COMP_WORDS[COMP_CWORD]}"
657 local opt="--mixed --hard --soft"
658 COMPREPLY=($(compgen -W "$opt $(__git_refs)" -- "$cur"))
661 _git ()
663 local i c=1 command __git_dir
665 while [ $c -lt $COMP_CWORD ]; do
666 i="${COMP_WORDS[c]}"
667 case "$i" in
668 --git-dir=*) __git_dir="${i#--git-dir=}" ;;
669 --bare) __git_dir="." ;;
670 --version|--help|-p|--paginate) ;;
671 *) command="$i"; break ;;
672 esac
673 c=$((++c))
674 done
676 if [ $c -eq $COMP_CWORD -a -z "$command" ]; then
677 COMPREPLY=($(compgen -W "
678 --git-dir= --version --exec-path
679 $(__git_commands)
680 $(__git_aliases)
681 " -- "${COMP_WORDS[COMP_CWORD]}"))
682 return;
685 local expansion=$(__git_aliased_command "$command")
686 [ "$expansion" ] && command="$expansion"
688 case "$command" in
689 branch) _git_branch ;;
690 cat-file) _git_cat_file ;;
691 checkout) _git_checkout ;;
692 cherry-pick) _git_cherry_pick ;;
693 diff) _git_diff ;;
694 diff-tree) _git_diff_tree ;;
695 fetch) _git_fetch ;;
696 format-patch) _git_format_patch ;;
697 log) _git_log ;;
698 ls-remote) _git_ls_remote ;;
699 ls-tree) _git_ls_tree ;;
700 merge) _git_merge;;
701 merge-base) _git_merge_base ;;
702 name-rev) _git_name_rev ;;
703 pull) _git_pull ;;
704 push) _git_push ;;
705 rebase) _git_rebase ;;
706 repo-config) _git_repo_config ;;
707 reset) _git_reset ;;
708 show) _git_log ;;
709 show-branch) _git_log ;;
710 whatchanged) _git_log ;;
711 *) COMPREPLY=() ;;
712 esac
715 _gitk ()
717 local cur="${COMP_WORDS[COMP_CWORD]}"
718 COMPREPLY=($(compgen -W "--all $(__git_refs)" -- "$cur"))
721 complete -o default -o nospace -F _git git
722 complete -o default -F _gitk gitk
723 complete -o default -F _git_branch git-branch
724 complete -o default -o nospace -F _git_cat_file git-cat-file
725 complete -o default -F _git_checkout git-checkout
726 complete -o default -F _git_cherry_pick git-cherry-pick
727 complete -o default -o nospace -F _git_diff git-diff
728 complete -o default -F _git_diff_tree git-diff-tree
729 complete -o default -o nospace -F _git_fetch git-fetch
730 complete -o default -o nospace -F _git_format_patch git-format-patch
731 complete -o default -o nospace -F _git_log git-log
732 complete -o default -F _git_ls_remote git-ls-remote
733 complete -o default -o nospace -F _git_ls_tree git-ls-tree
734 complete -o default -F _git_merge git-merge
735 complete -o default -F _git_merge_base git-merge-base
736 complete -o default -F _git_name_rev git-name-rev
737 complete -o default -o nospace -F _git_pull git-pull
738 complete -o default -o nospace -F _git_push git-push
739 complete -o default -F _git_rebase git-rebase
740 complete -o default -F _git_repo_config git-repo-config
741 complete -o default -F _git_reset git-reset
742 complete -o default -F _git_log git-show
743 complete -o default -o nospace -F _git_log git-show-branch
744 complete -o default -o nospace -F _git_log git-whatchanged
746 # The following are necessary only for Cygwin, and only are needed
747 # when the user has tab-completed the executable name and consequently
748 # included the '.exe' suffix.
750 if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then
751 complete -o default -o nospace -F _git git.exe
752 complete -o default -F _git_branch git-branch.exe
753 complete -o default -o nospace -F _git_cat_file git-cat-file.exe
754 complete -o default -o nospace -F _git_diff git-diff.exe
755 complete -o default -o nospace -F _git_diff_tree git-diff-tree.exe
756 complete -o default -o nospace -F _git_format_patch git-format-patch.exe
757 complete -o default -o nospace -F _git_log git-log.exe
758 complete -o default -o nospace -F _git_ls_tree git-ls-tree.exe
759 complete -o default -F _git_merge_base git-merge-base.exe
760 complete -o default -F _git_name_rev git-name-rev.exe
761 complete -o default -o nospace -F _git_push git-push.exe
762 complete -o default -F _git_repo_config git-repo-config
763 complete -o default -o nospace -F _git_log git-show.exe
764 complete -o default -o nospace -F _git_log git-show-branch.exe
765 complete -o default -o nospace -F _git_log git-whatchanged.exe