My git workflow is heavily influenced by articles such as Rein’s or the topic branches workflow on the excellent ProGit book. The idea is simple:
From the master branch, run
git checkout -b feature_x
vi file.rb
git add -u
git add .
git status
git commit -m "Make changes"
There are many ways to do this. I like this method because it doesn’t require me to checkout or merge the master branch. Instead, just fetch the references from the remote and rebase it against your feature branch. Note that the reference we’re rebasing against is origin/master, so that we only bring in changes from that branch.
git fetch
git rebase origin/master
Once again we fetch changes from the remote, and then we do an interactive rebase against origin/master. This ensures that we don’t modify any changes that already found a home upstream.
git fetch
git rebase -i origin/master
We fetch and rebase again, just in case there have been changes since the last step, and then we merge it all into master and push it out if all tests pass.
git fetch
git rebase origin/master
git checkout master
git merge feature_x
rake
git push
I prefer not to delete the local or remote feature branches right away just in case. Instead, I’ll go on some cleanup missions every once in a while.
Working this way for a while, you start to identify repetitive keystrokes. You can cut down on these keystrokes with shell aliases or functions, or with git aliases. I like using git aliases because the commands themselves provide context: git related commands start with git.
Here are the aliases I use everyday that support this git workflow. Place these in your ~/.gitconfig.
[alias]
c = commit -m
a = add
aa= !git add -u && git add . && git status
cob = checkout -b
up = !git fetch origin && git rebase origin/master
ir = !git rebase -i origin/master
done = !git fetch && git rebase origin/master && git checkout master && git merge @{-1} && rake && git push
Having those in place, let’s see what the very same workflow looks like:
git cob feature_x
vi file.rb
git aa
git c "Make changes"
git up
git ir
git done
Now we’re talking. From the convention of how we work with git, we’ve augmented our tools to make it a whole lot easier, and reduce the risk of modifying upstream history by always ensuring we never change it.
But aliases can take you even further. For one, I use a shell alias for git: g=git, so now the commands above simply look like g aa, g c "Make changes", etc. There are also a few useful tidbits you can use. One that comes in handy often is when you want to commit changes as part of the prior commit, and want to keep the original commit message. Similar to creating a new commit and then squashing them.
ca = commit --amend -C HEAD
What about when you’re ready to delete feature branches. You want to remove the local and remote references. Try g rmb feature_x:
rmb = !sh -c 'git branch -D $1 && git push origin :$1' -
Or if you want to see who has contributed to a project, add this alias and just ask with g who
who = shortlog -n -s --no-merges
Finally, it’s a good idea to clean up your git repo every once in a while. This alias will remove remote branch references that no longer exist, cleanup unnecessary git files, remove untracked files from the working tree and clear out your stash - all with a simple g cleanup (hat tip to @qrush)
cleanup = !git remote prune origin && git gc && git clean -dfx && git stash clear
There are many more possibilities. How about you: What are your most useful git aliases?