Thursday, March 4, 2010

Example git/git-sh config

I've been using git, git-svn, and git-sh while working on Bizo's internal projects and really enjoying it. Per requests from some other devs, here is my git/git-sh config.

First, you should start with git-sh. It adds some bash shell customizations like a nice `PS1` prompt, tab completion, and incredibly short git-specific aliases. I'll cover some of the aliases later, but this is the thing that started me down the "how cool can I get my git environment" path.

I've included commented versions of my .gitconfig and .gitshrc below, but you can find raw versions here and here. I also cross-posted this on my personal blog if you're so inclined as to read it twice.

Example Shell Session

A lot of my customizations are around aliases, so this is a quick overview, and then the aliases are defined/explained below.

Here is a made up example bash session with some of the commands:

# show we're in a basic java/whatever project
$ ls
src/ tests/

# start git-sh to get into a git-specific bash environment
$ git sh

# change some things
$ echo "file1" > src/package1/file1
$ echo "file2" > src/package2/file2
$ echo "file3" > src/package3/file2

# see all of our changes
$ d
# runs: git diff

# see only the changes in package1
$ dg package1
# runs: git diff src/package1/file1

# stage any path with 'package' in it
$ ag package
# runs: git add src/package1/file1 src/package2/file2 src/package3/file3

# we only wanted package1, reset package2 and package3
$ rsg package2
# runs: git reset src/package2/file2
$ rsg package3
# runs: git reset src/package3/file3

# see what we have staged now (only package1)
$ p
# runs: git diff --cached

# commit it
$ commit -m "Changed stuff in package1"
# runs: git commit -m "..."

That is the basic idea.

Most of the magic is from the [alias] section of .gitconfig, along with my .gitshrc allowing the git prefix to be dropped.


The .gitconfig file is in your home directory and is for user-wide settings.

Here is my current .gitconfig with comments:

name = Stephen Haberman
email =
# 'add all' stages all new+changed+deleted files
aa = !git ls-files -d | xargs -r git rm && git ls-files -m -o --exclude-standard | xargs -r git add

# 'add grep' stages all new+changed that match $1
ag = "!sh -c 'git ls-files -m -o --exclude-standard | grep $1 | xargs -r git add' -"

# 'checkout grep' checkouts any files that match $1
cg = "!sh -c 'git ls-files -m | grep $1 | xargs -r git checkout' -"

# 'diff grep' diffs any files that match $1
dg = "!sh -c 'git ls-files -m | grep $1 | xargs -r git diff' -"

# 'patch grep' diff --cached any files that match $1
pg = "!sh -c 'git ls-files -m | grep $1 | xargs -r git diff --cached' -"

# 'remove grep' remove any files that match $1
rmg = "!sh -c 'git ls-files -d | grep $1 | xargs -r git rm' -"

# 'reset grep' reset any files that match $1
rsg = "!sh -c 'git ls-files -c | grep $1 | xargs -r git reset' -"

# nice log output
lg = log --graph --pretty=oneline --abbrev-commit --decorate

# rerun svn show-ignore -> exclude
si = !git svn show-ignore > .git/info/exclude

# start git-sh
sh = !git-sh
# turn on color
diff = auto
status = auto
branch = auto
interactive = auto
ui = auto
[color "branch"]
# good looking colors i copy/pasted from somewhere
current = green bold
local = green
remote = red bold
[color "diff"]
# good looking colors i copy/pasted from somewhere
meta = yellow bold
frag = magenta bold
old = red bold
new = green bold
[color "status"]
# good looking colors i copy/pasted from somewhere
added = green bold
changed = yellow bold
untracked = red
[color "sh"]
branch = yellow
excludesfile = /home/stephen/.gitignore
# two-space tabs
pager = less -FXRS -x2
# 'git push' should only do the current branch, not all
default = current
# always setup 'git pull' to rebase instead of merge
autosetuprebase = always
renames = copies
mnemonicprefix = true
# push empty directory removals back to svn at directory deletes
rmdir = true


This is my .gitshrc file, heavily based off Ryan Tomayko's original.

Ryan's original comments are prefixed with #, I'll prefix my additions with ###, most of which are aliases to my [alias] entries above and some git-svn aliases.

# rtomayko's ~/.gitshrc file
### With additions from stephenh

# git commit
gitalias commit='git commit --verbose'
gitalias amend='git commit --verbose --amend'
gitalias ci='git commit --verbose'
gitalias ca='git commit --verbose --all'
gitalias n='git commit --verbose --amend'

# git branch and remote
gitalias b='git branch -av' ### Added -av parameter
gitalias rv='git remote -v'

# git add
gitalias a='git add'
gitalias au='git add --update'
gitalias ap='git add --patch'
### Added entries for my .gitconfig aliases
alias aa='git aa' # add all updated/new/deleted
alias ag='git ag' # add with grep
alias agp='git agp' # add with grep -p
alias cg='git cg' # checkout with grep
alias dg='git dg' # diff with grep
alias pg='git pg' # patch with grep
alias rsg='git rsg' # reset with grep
alias rmg='git rmg' # remove with grep

# git checkout
gitalias c='git checkout'

# git fetch
gitalias f='git fetch'

# basic interactive rebase of last 10 commits
gitalias r='git rebase --interactive HEAD~10'
alias cont='git rebase --continue'

# git diff
gitalias d='git diff'
gitalias p='git diff --cached' # mnemonic: "patch"

# git ls-files
### Added o to list other files that aren't ignored
gitalias o='git ls-files -o --exclude-standard' # "other"

# git status
alias s='git status'

# git log
gitalias L='git log'
# gitalias l='git log --graph --pretty=oneline --abbrev-commit --decorate'
gitalias l="git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset' --abbrev-commit --date=relative"
gitalias ll='git log --pretty=oneline --abbrev-commit --max-count=15'

# misc
gitalias pick='git cherry-pick'

# experimental
gitalias mirror='git reset --hard'
gitalias stage='git add'
gitalias unstage='git reset HEAD'
gitalias pop='git reset --soft HEAD^'
gitalias review='git log -p --max-count=1'

### Added git svn asliases
gitalias si='git si' # update svn ignore > exclude
gitalias sr='git svn rebase'
gitalias sp='git svn dcommit'
gitalias sf='git svn fetch'

### Added call to git-wtf tool
gitalias wtf='git-wtf'

Since I defined most of the interesting aliases in the .gitconfig [alias] section, it means they're all usable via git xxx, e.g. git ag foo, but listing alias ag='git ag' in .gitshrc means you can also just use ag foo, assuming you've started the git-sh environment.

It results in some duplication, but means they're usable from both inside and outside of git-sh, which I think is useful.

No comments: