I want to test if my present directory is part of a git/hg/etc. repository, as part of my shell prompt. Searching around a bit, I found this setup which has similar tests to what I want. And so I guess my question is: 开发者_如何学Gowhat are the fastest tests to see if I am in a git, hg, darcs, or svn repository? In particular, in the link I gave he uses git branch > /dev/null
and hg root > /dev/null
; are those the fastest?
If you really need performance, you could check for .git
or .hg
directories. But this of course is not going to be 100% reliable.
Testing for the existence of .git
, .hg
and so on is a very good approximation (definitely good enough for a prompt). But you can't just test in the current directory, you need to check parent directories as well. The following (untested) bash/ksh/zsh snippet sets vc
to the version control system the current directory appears to be under, or to the empty string if it can't find one.
vc=
if [ -d .svn ]; then
vc=svn
elif [ -d CVS ]; then
vc=cvs
else
d=..
while ! [ "$d" -ef / ]; do
if [ -d "$d/.bzr" ]; then
vc=bzr
elif [ -d "$d/_darcs" ]; then
vc=darcs
elif [ -d "$d/.git" ]; then
vc=git
elif [ -d "$d/.hg" ]; then
vc=hg
fi
if [ -n "$vc" ]; then break; fi
d=$d/..
done
fi
morning, I had this terrible piece, because I could not remember.
#!/bin/bash -
MYPATH=/home/user
fail() {
echo "$1"
exit 1
}
test -d $MYPATH || fail "Can't chdir to $MYPATH, exiting .."
for x in $(locate $MYPATH | egrep "\.svn|CVS|\.hg|\.git" | awk -F '/' '{print $4}' | sort -u); do
if [ -n "$x" ]; then
find $x -name "\.svn" -o -name "CVS" -o -name "\.hg" -o -name "\.git" -type d| \
awk -v v="$MYPATH" -F '/' '{print v,$1,$2,$3}'| \
egrep "\.svn|CVS|\.hg|\.git";
else
fail "Hm, no repositories found"
fi
done
gives:
/home/user src onioncat .svn
/home/user src sqlmap .svn
/home/user src airprobe .git
/home/user src nagios CVS
Might not be for you, as you want it in the prompt. (I hate overloading my prompt :)
If you look at what git does, it's probably the simplest (nothing to write), fastest (it's written in C) and surest way (you're using the official algorithm).
In short 'git branch 2>/dev/null' is the way to go.
From a git working directory:
$ cd /d/qneill/gcc
$ strace -e trace=access,chdir,stat git branch 2>&1 | egrep -v '/etc/|/lib/'
stat(".git", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
access(".git/objects", X_OK) = 0
access(".git/refs", X_OK) = 0
access("/home/qneill/.gitconfig", R_OK) = 0
stat(".git", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
access(".git/config", R_OK) = 0
access("/home/qneill/.gitconfig", R_OK) = 0
access(".git/config", R_OK) = 0
access("/home/qneill/.gitconfig", R_OK) = 0
access(".git/config", R_OK) = 0
stat(".git/refs/remotes", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
. . .
From a non-git directory:
$ mkdir -p /tmp/d1; cd /tmp/d1; pwd
/tmp/d1
$ strace -e trace=access,chdir,stat git branch 2>&1 | egrep -v '/etc/|/lib/'
stat(".git", 0x7fff32570650) = -1 ENOENT (No such file or directory)
access(".git/objects", X_OK) = -1 ENOENT (No such file or directory)
access("./objects", X_OK) = -1 ENOENT (No such file or directory)
chdir("..") = 0
stat(".git", 0x7fff32570650) = -1 ENOENT (No such file or directory)
. . .
fatal: Not a git repository (or any of the parent directories): .git
IMO git-show should provide a way to introspect about the given repository and working directory, because of how GIT_WORK_TREE and GIT_DIR work.
Don't know if it will be helpful for you but here is my PS1 for git repository:
$ egrep 'PS|RESET|PS1' ~/.bashrc
PS_AT='\[\033[1;30m\]'
PS_PWD='\[\033[1;34m\]'
RESET='\[\033[m\]'
export PS1='$(branch=$(git branch 2>/dev/null | grep "^*" | cut -d" " -f2-); [ -n "$branch" ] && (repo=$(git config --get remote.origin.url 2>/dev/null); ([ -n "$repo" ] && echo $repo || echo origin) | sed -r "s,/?.git$,," | awk -F"/" "{print \\$NF}" | xargs -r -I r echo -ne "\[\033[1;34m\][\[\033[0;34m\]r\[\033[1;34m\]:"; echo $branch | xargs -r -I r echo -e "\[\033[0;33m\]r\[\033[1;34m\]]\[\033[m\] "))'"\u${PS_AT}@${RESET}\h${PS_AT}:${PS_PWD}\W${PS_AT}\$${RESET} "
Yes, it's a bit crazy to call 'git branch' on every directory change but I've been living with that for ages without a problem. :-)
精彩评论