1515# Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
1616# ZSH: PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
1717# the optional argument will be used as format string.
18- # 3b) Alternatively, if you are using bash, __git_ps1 can be
19- # used for PROMPT_COMMAND with two parameters, <pre> and
20- # < post>, which are strings you would put in $PS1 before
21- # and after the status string generated by the git-prompt
22- # machinery. e.g.
18+ # 3b) Alternatively, for a slighly faster prompt, if you are
19+ # using bash, __git_ps1 can be used for PROMPT_COMMAND
20+ # with two parameters, <pre> and < post>, which are strings
21+ # you would put in $PS1 before and after the status string
22+ # generated by the git-prompt machinery. e.g.
2323# Bash: PROMPT_COMMAND='__git_ps1 "\u@\h:\w" "\\\$ "'
2424# ZSH: precmd () { __git_ps1 "%n" ":%~$ " "|%s" }
2525# will show username, at-sign, host, colon, cwd, then
8080# GIT_PS1_SHOWCOLORHINTS to a nonempty value. The colors are based on
8181# the colored output of "git status -sb".
8282
83- # __gitdir accepts 0 or 1 arguments (i.e., location)
84- # returns location of .git repo
85- __gitdir ()
86- {
87- # Note: this function is duplicated in git-completion.bash
88- # When updating it, make sure you update the other one to match.
89- if [ -z " ${1-} " ]; then
90- if [ -n " ${__git_dir-} " ]; then
91- echo " $__git_dir "
92- elif [ -n " ${GIT_DIR-} " ]; then
93- test -d " ${GIT_DIR-} " || return 1
94- echo " $GIT_DIR "
95- elif [ -d .git ]; then
96- echo .git
97- else
98- git rev-parse --git-dir 2> /dev/null
99- fi
100- elif [ -d " $1 /.git" ]; then
101- echo " $1 /.git"
102- else
103- echo " $1 "
104- fi
105- }
106-
10783# stores the divergence from upstream in $p
10884# used by GIT_PS1_SHOWUPSTREAM
10985__git_ps1_show_upstream ()
@@ -335,50 +311,83 @@ __git_ps1 ()
335311 ;;
336312 esac
337313
338- local g=" $( __gitdir) "
339- if [ -z " $g " ]; then
314+ local repo_info rev_parse_exit_code
315+ repo_info=" $( git rev-parse --git-dir --is-inside-git-dir \
316+ --is-bare-repository --is-inside-work-tree \
317+ --short HEAD 2> /dev/null) "
318+ rev_parse_exit_code=" $? "
319+
320+ if [ -z " $repo_info " ]; then
340321 if [ $pcmode = yes ]; then
341322 # In PC mode PS1 always needs to be set
342323 PS1=" $ps1pc_start$ps1pc_end "
343324 fi
325+ return
326+ fi
327+
328+ local short_sha
329+ if [ " $rev_parse_exit_code " = " 0" ]; then
330+ short_sha=" ${repo_info##* $' \n ' } "
331+ repo_info=" ${repo_info% $' \n ' * } "
332+ fi
333+ local inside_worktree=" ${repo_info##* $' \n ' } "
334+ repo_info=" ${repo_info% $' \n ' * } "
335+ local bare_repo=" ${repo_info##* $' \n ' } "
336+ repo_info=" ${repo_info% $' \n ' * } "
337+ local inside_gitdir=" ${repo_info##* $' \n ' } "
338+ local g=" ${repo_info% $' \n ' * } "
339+
340+ local r=" "
341+ local b=" "
342+ local step=" "
343+ local total=" "
344+ if [ -d " $g /rebase-merge" ]; then
345+ read b 2> /dev/null < " $g /rebase-merge/head-name"
346+ read step 2> /dev/null < " $g /rebase-merge/msgnum"
347+ read total 2> /dev/null < " $g /rebase-merge/end"
348+ if [ -f " $g /rebase-merge/interactive" ]; then
349+ r=" |REBASE-i"
350+ else
351+ r=" |REBASE-m"
352+ fi
344353 else
345- local r=" "
346- local b=" "
347- local step=" "
348- local total=" "
349- if [ -d " $g /rebase-merge" ]; then
350- b=" $( cat " $g /rebase-merge/head-name" 2> /dev/null) "
351- step=$( cat " $g /rebase-merge/msgnum" 2> /dev/null)
352- total=$( cat " $g /rebase-merge/end" 2> /dev/null)
353- if [ -f " $g /rebase-merge/interactive" ]; then
354- r=" |REBASE-i"
354+ if [ -d " $g /rebase-apply" ]; then
355+ read step 2> /dev/null < " $g /rebase-apply/next"
356+ read total 2> /dev/null < " $g /rebase-apply/last"
357+ if [ -f " $g /rebase-apply/rebasing" ]; then
358+ read b 2> /dev/null < " $g /rebase-apply/head-name"
359+ r=" |REBASE"
360+ elif [ -f " $g /rebase-apply/applying" ]; then
361+ r=" |AM"
355362 else
356- r=" |REBASE-m "
363+ r=" |AM/ REBASE"
357364 fi
365+ elif [ -f " $g /MERGE_HEAD" ]; then
366+ r=" |MERGING"
367+ elif [ -f " $g /CHERRY_PICK_HEAD" ]; then
368+ r=" |CHERRY-PICKING"
369+ elif [ -f " $g /REVERT_HEAD" ]; then
370+ r=" |REVERTING"
371+ elif [ -f " $g /BISECT_LOG" ]; then
372+ r=" |BISECTING"
373+ fi
374+
375+ if [ -n " $b " ]; then
376+ :
377+ elif [ -h " $g /HEAD" ]; then
378+ # symlink symbolic ref
379+ b=" $( git symbolic-ref HEAD 2> /dev/null) "
358380 else
359- if [ -d " $g /rebase-apply" ]; then
360- step=$( cat " $g /rebase-apply/next" 2> /dev/null)
361- total=$( cat " $g /rebase-apply/last" 2> /dev/null)
362- if [ -f " $g /rebase-apply/rebasing" ]; then
363- b=" $( cat " $g /rebase-apply/head-name" 2> /dev/null) "
364- r=" |REBASE"
365- elif [ -f " $g /rebase-apply/applying" ]; then
366- r=" |AM"
367- else
368- r=" |AM/REBASE"
381+ local head=" "
382+ if ! read head 2> /dev/null < " $g /HEAD" ; then
383+ if [ $pcmode = yes ]; then
384+ PS1=" $ps1pc_start$ps1pc_end "
369385 fi
370- elif [ -f " $g /MERGE_HEAD" ]; then
371- r=" |MERGING"
372- elif [ -f " $g /CHERRY_PICK_HEAD" ]; then
373- r=" |CHERRY-PICKING"
374- elif [ -f " $g /REVERT_HEAD" ]; then
375- r=" |REVERTING"
376- elif [ -f " $g /BISECT_LOG" ]; then
377- r=" |BISECTING"
386+ return
378387 fi
379-
380- test -n " $b " ||
381- b= " $( git symbolic-ref HEAD 2> /dev/null ) " || {
388+ # is it a symbolic ref?
389+ b= " ${head # ref : } "
390+ if [ " $head " = " $b " ] ; then
382391 detached=yes
383392 b=" $(
384393 case " ${GIT_PS1_DESCRIBE_STYLE-} " in
@@ -392,70 +401,74 @@ __git_ps1 ()
392401 git describe --tags --exact-match HEAD ;;
393402 esac 2> /dev/null) " ||
394403
395- b=" $( cut -c1-7 " $g /HEAD" 2> /dev/null) ..." ||
396- b=" unknown"
404+ b=" $short_sha ..."
397405 b=" ($b )"
398- }
406+ fi
399407 fi
408+ fi
400409
401- if [ -n " $step " ] && [ -n " $total " ]; then
402- r=" $r $step /$total "
403- fi
410+ if [ -n " $step " ] && [ -n " $total " ]; then
411+ r=" $r $step /$total "
412+ fi
404413
405- local w=" "
406- local i=" "
407- local s=" "
408- local u=" "
409- local c=" "
410- local p=" "
414+ local w=" "
415+ local i=" "
416+ local s=" "
417+ local u=" "
418+ local c=" "
419+ local p=" "
411420
412- if [ " true" = " $( git rev-parse --is-inside-git-dir 2> /dev/null) " ]; then
413- if [ " true" = " $( git rev-parse --is-bare-repository 2> /dev/null) " ]; then
414- c=" BARE:"
421+ if [ " true" = " $inside_gitdir " ]; then
422+ if [ " true" = " $bare_repo " ]; then
423+ c=" BARE:"
424+ else
425+ b=" GIT_DIR!"
426+ fi
427+ elif [ " true" = " $inside_worktree " ]; then
428+ if [ -n " ${GIT_PS1_SHOWDIRTYSTATE-} " ] &&
429+ [ " $( git config --bool bash.showDirtyState) " != " false" ]
430+ then
431+ git diff --no-ext-diff --quiet --exit-code || w=" *"
432+ if [ -n " $short_sha " ]; then
433+ git diff-index --cached --quiet HEAD -- || i=" +"
415434 else
416- b=" GIT_DIR!"
417- fi
418- elif [ " true" = " $( git rev-parse --is-inside-work-tree 2> /dev/null) " ]; then
419- if [ -n " ${GIT_PS1_SHOWDIRTYSTATE-} " ] &&
420- [ " $( git config --bool bash.showDirtyState) " != " false" ]
421- then
422- git diff --no-ext-diff --quiet --exit-code || w=" *"
423- if git rev-parse --quiet --verify HEAD > /dev/null; then
424- git diff-index --cached --quiet HEAD -- || i=" +"
425- else
426- i=" #"
427- fi
428- fi
429- if [ -n " ${GIT_PS1_SHOWSTASHSTATE-} " ]; then
430- git rev-parse --verify refs/stash > /dev/null 2>&1 && s=" $"
435+ i=" #"
431436 fi
437+ fi
438+ if [ -n " ${GIT_PS1_SHOWSTASHSTATE-} " ] &&
439+ [ -r " $g /refs/stash" ]; then
440+ s=" $"
441+ fi
432442
433- if [ -n " ${GIT_PS1_SHOWUNTRACKEDFILES-} " ] &&
434- [ " $( git config --bool bash.showUntrackedFiles) " != " false" ] &&
435- [ -n " $( git ls-files --others --exclude-standard) " ]
436- then
437- u=" %${ZSH_VERSION+% } "
438- fi
443+ if [ -n " ${GIT_PS1_SHOWUNTRACKEDFILES-} " ] &&
444+ [ " $( git config --bool bash.showUntrackedFiles) " != " false" ] &&
445+ git ls-files --others --exclude-standard --error-unmatch -- ' * ' > /dev/null 2> /dev/null
446+ then
447+ u=" %${ZSH_VERSION+% } "
448+ fi
439449
440- if [ -n " ${GIT_PS1_SHOWUPSTREAM-} " ]; then
441- __git_ps1_show_upstream
442- fi
450+ if [ -n " ${GIT_PS1_SHOWUPSTREAM-} " ]; then
451+ __git_ps1_show_upstream
443452 fi
453+ fi
444454
445- local z=" ${GIT_PS1_STATESEPARATOR-" " } "
446- local f=" $w$i$s$u "
447- if [ $pcmode = yes ]; then
448- local gitstring=
449- if [ -n " ${GIT_PS1_SHOWCOLORHINTS-} " ]; then
450- __git_ps1_colorize_gitstring
451- else
452- gitstring=" $c ${b## refs/ heads/ }${f: +$z$f } $r$p "
453- fi
455+ local z=" ${GIT_PS1_STATESEPARATOR-" " } "
456+ local f=" $w$i$s$u "
457+ if [ $pcmode = yes ]; then
458+ local gitstring=
459+ if [ -n " ${GIT_PS1_SHOWCOLORHINTS-} " ]; then
460+ __git_ps1_colorize_gitstring
461+ else
462+ gitstring=" $c ${b## refs/ heads/ }${f: +$z$f } $r$p "
463+ fi
464+ if [[ -n ${ZSH_VERSION-} ]]; then
454465 gitstring=$( printf -- " $printf_format " " $gitstring " )
455- PS1=" $ps1pc_start$gitstring$ps1pc_end "
456466 else
457- # NO color option unless in PROMPT_COMMAND mode
458- printf -- " $printf_format " " $c ${b## refs/ heads/ }${f: +$z$f } $r$p "
467+ printf -v gitstring -- " $printf_format " " $gitstring "
459468 fi
469+ PS1=" $ps1pc_start$gitstring$ps1pc_end "
470+ else
471+ # NO color option unless in PROMPT_COMMAND mode
472+ printf -- " $printf_format " " $c ${b## refs/ heads/ }${f: +$z$f } $r$p "
460473 fi
461474}
0 commit comments