Re: command prompt script for current branch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



"Stephen Sinclair" <radarsat1@xxxxxxxxx> writes:

> Attached is a script I quickly wrote up yesterday.  Sometimes I've
> found I started working only to realize I was on the wrong branch.
> (Now that I'm accustomed to working with git, I make many small
> branches, so it happens.)

First, it is much better to put such script inline, in the body of
your email.  This makes commenting about script body much easier.
And if you have to attach it, for example because your mailer mangles
whitespace (which is not the case here), make sure that attachement
uses "text/plain", and if possible "inline" disposition, to better
_view_ the code without need to save it to temporary file.

I would take an exeption and comment on your code, even though you
make it hard to do so.


Second, there are numerous examples on how to create git-aware
prompt.  Those include code in contrib/completion/git-completion.bash
in git sources:

#    4) Consider changing your PS1 to also show the current branch:
#        PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
#
#       The argument to __git_ps1 will be displayed only if you
#       are currently in a git repository.  The %s token will be
#       the name of the current branch.

and the _git_ps1 file in sources of "Git In Nutshell", with git
repository at http://git.jonas.iki.fi/git_guides.git; this code
by yours truly is heavily commented to make it easier to understand.
I'm not sure if it is included in "Git In Nutshell" 
(http://jonas.iki.fi/git_guides).

I have put the _git_ps1 code at the end of this post.

> So I made this small script to simply write the name of the currently
> checked out branch, as well as information on how many commits it
> differs from the remote tracking branch, if any.
> It also appends an exclamation mark if I have uncommitted changes.  I
> stuck it in my PS1 environment variable, so that it would be part of
> my command prompt.

Third, the information on how many commits it differes from coupled
remote tracking branch is not that fast to get; additionally you don't
always _have_ coupled remote tracking branch.  For me the number of
commits current branch differs from origin repo, and "dirtiness" of
branch are not important, while working with detached HEAD and marking
branches which are StGit controlled is.

> -- >8 --
> #!/bin/bash
>
> # exit if not a git repo
> if ! (git branch >/dev/null 2>&1); then
>     exit
> fi

There are much better ways to do this; it is usually much better to
use plumbing (engine) commands in scripts, not porcelain, which is
meant for user interaction. See code in _git_ps1

Besides, why do you run git-branch _twice_?
 
> BRANCH=$(git branch | grep \* | sed s,\*\ ,, )

There is much better way to do this with plumbing.

> REMOTE=$(git config --list | grep branch.$BRANCH.remote 2>/dev/null | cut -f2 -d=)
> MERGE=$(git config --list | grep branch.$BRANCH.merge 2>/dev/null | sed s,^.*=refs/heads/,,)

Why do you use "git config --list" then grep for key, instead of
asking git-config to return results for given key with 
"git config --get" or "git config --get-all"?

By the way, when you use grep you should quote '.', as '.' means any
character in regular expression. You do not need put regular
expression (parameter to grep) in double quotes _only_ because
refnames (and branchnames) cannot contain spaces.

Your code wouldn't be able to deal with being on detached HEAD.

> # exit if no branch found
> if [ "${BRANCH}"x == x ]; then
>     exit
> fi

This is mixture of coding for portability with bash-isms; either use
'test' instead of '[', or use '-z' operator.

> echo -n ' '[$BRANCH
>
> # dirty state
> if [ "$(git-diff-index --name-only HEAD)"x != x ]; then
>     echo -n \!
> fi

Err... if you want to check if there are differences, it would be
better to use '--quiet' (which implies '--exit-code') and check for
exit code instead of checking if there was any output.

BTW. there is slight inconsistency in using dashed (git-diff-index)
and dashless (git branch) of diff commands.  In "external" script
which does not source git shell script "library", it is better to use
dashless form.
 
> # exit if no remote tracking branch found
> if [ ${REMOTE}x == x -a ${MERGE}x == x ]; then
>     echo ]
>     exit
> fi
> 
> # Uncomment this line to ignore remote tracking branches
> # echo ]; exit
> 
> # calc number of revs between remote and local
> FWDREVS=$(git rev-list $REMOTE/$MERGE..$BRANCH 2>/dev/null 2>&1 | wc -l)
> 
> # and the other way, in case it is not up to date
> BACKREVS=$(git rev-list $BRANCH..$REMOTE/$MERGE 2>/dev/null 2>&1 | wc -l)
> 
> echo -n ' '-\> $REMOTE/$MERGE
> 
> if [ $FWDREVS -gt 0 ]; then
>     echo -n +$FWDREVS
> fi
> 
> if [ $BACKREVS -gt 0 ]; then
>     echo -n -$BACKREVS
> fi
> 
> echo ]

Why do you use sequence of "echo -n", instead of setting variables,
perhaps with the help of some more advanced constructs like in example
below, then using one "echo" to output it all?

-- >8 --
function _git_ps1()
{
	# 'git_dir' is absolute path to git repository
	# 'rel' is path relative to top dir in repository
	# 'br' is current branch name, or 'HEAD' if we are on detached HEAD
	local git_dir rel br

	# first call to git-rev-parse also checks if we are inside git
	# repository; if we are not in git repository, use default prompt,
	# provided as an argument
	rel=$(git rev-parse --show-prefix 2>/dev/null) || \
		{ echo "$@" ; return; }
	rel=${rel%\/}

	# get branch name, strip 'refs/heads/' prefix,
	# and use 'HEAD' for detached HEAD (no branch name)
	br=$(git symbolic-ref HEAD 2>/dev/null)
	br=${br#refs/heads/}
	br=${br:-HEAD}

	# path to top dir of git repository
	loc=${PWD%/$rel}

	# the following code is important only if you use StGit,
	# to note if you are on StGit controlled branch;
	# use second part of conditional if you don't use StGit
	git_dir=$(git rev-parse --git-dir)
	if [ "$br" -a -e "$git_dir/patches/$br" ]; then
		echo "$br:${loc/*\/}${rel:+/$rel}# "
	else 
		echo "$br:${loc/*\/}${rel:+/$rel}> "
	fi
}

## bash:
## set PS1 only if we are in interactive shell (PS1 is set)
#    [ "$PS1" ] && PS1='$(_git_ps1 "\u@\h:\w> ")'

## zsh:
#	function precmd() {
#		PS1=`_git_ps1 '%m:%~%# '`
#	}
# vim:filetype=sh

 
-- 
Jakub Narebski
Poland
ShadeHawk on #git
-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux