As a recovering CVS user turned svn master, and now an aspiring git ninja, I am sharing some of the tips and tricks to make my git environment as enjoyable and effective as possible. First a little tough love: if you are not using the git command line, then just move along… these aren’t the droids you’re looking for. But seriously, if you want to learn how to use git better you MUST MUST MUST use the command line. But if you are going to use a GUI, then PLEASE do us all a favor and avoid Github for Mac and instead get a tool like Tower.
So if you are still reading you are in the right place!
Tip #1: If you are not using bash-completion, start now! Seriously! Stop reading this post and go install bash-completion immediately! This is the single biggest time saver; period. It provides completions via a deep knowledge of common tools such as git, ssh, jar, java, man, etc. For example:
- cd <your favorite git project>
- git checkout origin/<TAB><TAB>
- You will see all of the branches from the remote repo appear like magic!
- The git bash-completion knows about git commands, tags, branches, repositories, etc. So cool!
- Now try: git log –<TAB><TAB>
- It shows you all of the command line options for git log. With each git command having a wealth of options, this is a huge sanity saver.
Tip #2: Now that you have bash completing your git commands for you, how about we add some color to the results of git commands? Yes, seeing the output of a “git diff” colorized with additions in green and subtractions in red is, well after you get used to it, simply required.
Edit your ~/.gitconfig and add the following section:
[color] diff = auto status = auto branch = auto interactive = auto ui = auto
And while you are in there add this section to automatically run garbage collection for you!
[gc] auto = 1
Tip #3: Tired of typing “git status” to figure out if your branch is clean or dirty? Or if you need to push or pull to get caught up with a remote repo? The next git trick will really knock your socks off! Via the bash prompt, it displays the git branch you are currently on. If the branch is dirty the name of the branch is displayed in red. If the branch is clean the name is displayed in green. For example:
…clean…
[develop] /Develop/k2/rsmart/nakamura
…dirty…
[develop] /Develop/k2/rsmart/nakamura
…ahead…
[develop↑] /Develop/k2/rsmart/nakamura
…behind…
[develop↓] /Develop/k2/rsmart/nakamura
…branches have diverged…
[develop↕] /Develop/k2/rsmart/nakamura
Curious yet? Here are the arcane .bash_profile incantations to make this a reality:
c_cyan=`tput setaf 6`
c_red=`tput setaf 1`
c_green=`tput setaf 2`
c_sgr0=`tput sgr0`
parse_git_branch ()
{
if git rev-parse --git-dir >/dev/null 2>&1
then
git_status="$(git status 2> /dev/null)"
branch_pattern="^# On branch ([^${IFS}]*)"
remote_pattern="# Your branch is (.*) of"
diverge_pattern="# Your branch and (.*) have diverged"
# add an else if or two here if you want to get more specific
if [[ ${git_status} =~ ${remote_pattern} ]]; then
if [[ ${BASH_REMATCH[1]} == "ahead" ]]; then
remote="↑"
elif [ ${BASH_REMATCH[1]} == "behind" ]]; then
remote="↓"
fi
fi
if [[ ${git_status} =~ ${diverge_pattern} ]]; then
remote="↕"
fi
if [[ ${git_status} =~ ${branch_pattern} ]]; then
branch=${BASH_REMATCH[1]}
echo "${branch}${remote}"
fi
else
return 0
fi
}
branch_color ()
{
if git rev-parse --git-dir >/dev/null 2>&1
then
git_status="$(git status 2> /dev/null)"
color=""
if [[ ${git_status} =~ "working directory clean" ]]; then
color="${c_green}"
else
color=${c_red}
fi
else
return 0
fi
echo -ne $color
}
export PS1='[\[$(branch_color)\]$(parse_git_branch)\[${c_sgr0}\]] \w\[${c_sgr0}\]$ '
With this information in hand, you should be well on your way to leveling-up your git ninja (ginja?) skills…
I switched to zsh a while back. You can get all these goodies by installing Oh My Zsh.
You should check out prezto if you like oh-my-zsh (which I loved), but prezto is way better IMHO.
https://github.com/lancespeelmon/prezto
Thanks for tip 3 – that’s very useful.
How to I change it so that it only shows me the folder I am in – currently is shows this:
/usr/local/etc/httpd/sitename.com
I would like it just show /sitename.com
Possible?
Thanks
I am sure, google around for “bash prompt ps1″, here is an example:
http://www.thegeekstuff.com/2008/09/bash-shell-ps1…
I modified your script to use the more script friendly git commands. (Newer versions of git status wording has changed, which breaks your bash_profile PS1).
c_cyan=`tput setaf 6`
c_red=`tput setaf 1`
c_green=`tput setaf 2`
c_sgr0=`tput sgr0`
c_pink=`tput setaf 5`
parse_git_branch ()
{
git rev-parse –git-dir >/dev/null 2>&1
if [ $? -eq 0 ]; then
remote=”"
git_status=”$(git status 2> /dev/null)”
if [ $? -eq 128 ]; then
echo ” (!GIT_DIR!)”
else
branch=`git rev-parse –abbrev-ref HEAD`
git config –get branch.$branch.remote >/dev/null 2>&1
if [ $? -eq 0 ]; then
#its a tracking branch
behind=`git log ..@{u} –pretty=oneline | wc -l | sed -e ‘s/[ \t]*//g’`
ahead=`git log @{u}.. –pretty=oneline | wc -l | sed -e ‘s/[ \t]*//g’`
diverged=`git log @{u}… –pretty=oneline | wc -l | sed -e ‘s/[ \t]*//g’`
if [ $diverged -ne 0 ]; then
if [ "$behind" == "$diverged" ]; then
#remote=” [$behind]↓”
remote=”↓”
elif [ "$ahead" == "$diverged" ]; then
#remote=” [$ahead]
remote=”↑”
else
remote=”↕”
#remote=” [$behind]↓ [$ahead]↑”
fi
fi
fi
echo ” (${branch}${remote})”
fi
else
return 0
fi
}
branch_color ()
{
color=”"
git rev-parse –git-dir >/dev/null 2>&1
if [ $? -eq 0 ]; then
git status –untracked-files=no –porcelain >/dev/null 2>&1
if [ $? -eq 128 ]; then
color=${c_pink}
elif [ -z "$(git status --untracked-files=no --porcelain)" ]; then
color=”${c_green}”
else
color=${c_red}
fi
else
return 0
fi
echo -ne $color
}
export PS1=’\[33[1;32m\]\u\[33[0m\]@\[33[1;36m\]\h\[33[0m\] \W\[$(branch_color)\]$(parse_git_branch)\[33[0m\] \$ ‘
Very nice! FYI – I have switched to zsh with prezto and I am not looking back!
https://github.com/lancespeelmon/prezto