Tools I use: Git
Git is a DVCS or a distributed version control system. Its very similar to SVN in essence. As many others have said better, keeping your software version control is important for collaboration, maintaining a sense of history over time, and protection from data loss. Git in particular has a novel approach to this in that it doesn't rely on a central repository from which all syncs happen.
Why I like it
Minimal setup on the server
Git requires minimal setup achieve maximum benefit. When trying to setup a working git server, there's no complicated daemons to run, copious amounts of server configs or anything of the sort. Due to the fact that every git clone is a full mirror of the git repository, you just initialize a git repository (a bare version, as you probably don't want/need a working copy) and you're done. If you want to access this new repository remotely, you can do so via SSH. If you're looking to collaborate with others, you can communicate via built-in support for mailing patches back and forth, or you can run your own git server which I did before a mass simplification of my hosting setup.
Community
The community that has sprung up around git is an interesting one. While it started as a neckbeard-y, linux kernel developer group, it has gained in popularity with the ruby community which has given it an interesting focus towards usability and nifty tools. Probably the best artifact of the ruby influence is github. This has made git a pretty clear winner in the DVCS realm, though git's lack of historic windows support has given an edge to Mercurial for that crowd.
Very reasonable command layout and extension points
While it seems to be a source of frustration for newcomers, I've now become accustomed to the command structure and conventions for git. One of the best points of this is running git foo
is the same as having a git-foo
executable somewhere on your path. This is dead simple from an extension point.
Founded on interesting concepts
The internals of git intrigue me. I'm told that its modeled after file systems, which seems plausible given the original authors. The concept of traversing graphs to a tree of objects which can construct the state of a repository is of geeky interest to me. I've long been interested in implementing something on top of git as a datastore, but haven't yet gotten around to it.
How I configure it
Git's config files are structured like INI files. In addition to the configuration in this file, I tend to alias g
to git which allows for some nice savings for typing on commands when combined with some of the aliases I have below.
Setup a global git ignore file which contains various things I never want in my repositories such as the OS X .DSSTORE files, compilation artifacts, etc. Also, highlight a large class of errors related to whitespace so hopefully I don't check in code with trailing whitespace and such (though Emacs makes this more or less an impossibility).
[core] excludesfile = ~/.gitignore whitespace=fix,-indent-with-non-tab,trailing-space,cr-at-eol
General information about me for recording commits.
[user] name = Justin Lilly email =
Setup a bunch of nice coloring for the various colored outputs that exist. This particular theme allocates sane colors for things, such as marking bad things red (like merge conflicts, trailing white space) and more benign things in less overloaded colors like magenta or yellow.
[color] ui = auto diff = auto status = auto branch = auto interactive = auto pager = true [color "branch"] current = yellow reverse local = yellow remote = green [color "diff"] meta = yellow bold frag = magenta bold old = red bold new = green bold whitespace = red reverse [color "status"] added = yellow changed = green untracked = cyan
This is another handy extension point for git. When building a simple alias from one command to another, you don't have to create a git-foo script, but can instead include those below. The most commonly used aliases I have below are a
, ci
, and st
, which make sense given their purpose in general git workflow. The lg
command will show one line commit messages, but lays them out in a nice ascii graph of commits. The serve
command will export the current git repository via http for ad-hoc sharing. prune-all
will find all the branches that you're tracking that are stale (aren't around anymore) and removes them.
[alias] a = add lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset' --abbrev-commit --date=relative ci = commit --verbose chekcout = checkout pick = cherry-pick --sign-off sb = status --short --branch st = status --short --branch log1 = log --pretty=oneline --abbrev-commit serve = daemon --reuseaddr --base-path=. --export-all --verbose top-commits = shortlog --summary --numbered --no-merges gdiff = difftool --gui --no-prompt prune-all = !git remote | xargs -n 1 git remote prune
When pushing, push the current branch by default.
[push] default = current
Enable rerere, which is a nifty tool which will remember the merge chunks that fail and if they happen again, it'll auto resolve them for you.
[rerere] enabled = true
My github username which helps to power a few nice tools the github guys have put out. The best of them is hub, which allows you to do nice things like hub clone user/repo
and forget about memorizing the path to the git repository.
[github] user = justinlilly
When doing merge conflicts or diffs that are particularly hairy, I look to kdiff3. While not pretty, its a fairly functional merging and diffing utility. I'd like to eventually move to meld for diffing which supports loading all of your diffs at once, rather than viewing them one at a time in kdiff3, but I use a GUI so infrequently that it tends not to matter.
[mergetool] tool = kdiff3 [diff] guitool = kdiff3
Other nifty scripts
I tend to leave random comments scattered across my source code in the format of "@@@ Null Check?" or "FIXME: fill in documentation" which is intended to be filled in prior to getting a code review. This script piggybacks on git grep to find them.
#!/bin/bash git grep -C2 -E "(@@@|FIXME)"
I also use git-wtf, which is a bit large to paste here. It will show you how your current branch relates to various other branches, including remote branches. I also keep a copy of the author's git-rank-contributor script which, as it's name suggests, will stack rank contributors to a repository by commit.
This command, which I keep around as git-status-home will look for any git repositories under my home directory, and run a git status in their directory. This is helpful to find any repositories who have uncommited changes laying around the working copy. It will also give a general guideline of if there are changes in my repository that aren't referenced in the default tracked origin repository, meaning I should push.
#!/bin/bash # TODO: # - Figure out how to make -prune work so I don't have to use grep -v # - add the sed command to -exec param # - do better filtering of git status. Might require moving this out # of bash and using something like dulwich if [ -n $1 ]; then DIR=$1 else DIR=$HOME fi cd $DIR echo "Searching for git repositories.." for dir in `find . -name ".git" -type d 2>/dev/null | grep -v "env" | grep -v ".virtualenv" | sed 's/\/.git//g'` do echo "=== $dir ===" pushd $dir git status -sb popd done
References
- git config reference