Tuesday, September 15, 2009

Everyday Git Workflow

I use git each day both as an svn client and in git-only environments. Here's my standard workflow for each environment.

Init
If this is a new project, merely create a directory to work in and run git init.

Clone
git clone user@host:repo.git
or
git svn clone -s https://host/path/to/svn/repo (the -s says this uses trunk, branches, and tags directories)

This leaves you with a git repository that is in sync with your upstream.

If you've gone the svn route and need git to understand your svn:ignore props, run this:
git-svn show-ignore > .gitignore (Beware, it takes a while.)

Feature Branches
I generally create a new "feature branch" for each feature I want to work on. This allows me to switch cleanly between features as I see fit.
git checkout -b feature

When moving from branch to branch after I've made changes, I use git stash to save those changes. Git will move your pending changes in your working copy and index with you when you checkout a different branch (handy when you start editing in the wrong branch).
git stash (by itself will create a new stash of your working copy and index)
git stash list (shows all stashes)
git stash pop [] (Removes the named, or first, stash and applies it to your working copy/index)

Beginning of Day
I generally start by checking out the master branch (git checkout master) and updating from upstream.
git pull
or
git svn rebase

If there were changes in there that I need in one of my feature branches, I'll check it out and merge.
git checkout feature
git merge master
If there were any conflicts, fix them as part of the merge.

Working
Once I'm in a feature branch, I typically code there unless an interruption causes me to switch to another. That simply looks like this:
*Code, code, etc*
git add
git commit -m "Here's a short explanation of what I changed. Don't skimp on this part."

git diff can also be useful during the add/commit process to see exactly what you changed. git add --patch can also be used to "stage" (the process of adding changes to the index) individual hunks from each file instead of the entire file.

Sharing Branches
If your sysadmin has given you access to a remote git repository (I recommend using gitosis), you can share your feature branches with other devs without committing to your master/svn repo.

Note that in the following instructions I'm using "origin" as my remote. If you're working with a remote git repo already instead of svn you'll need to use a different name here.

git remote add origin user@host:repo.git
git checkout feature
git push origin feature

Now your coworker can run:
git remote add origin user@host:repo.git
git fetch
git branch -a (lists all branches including remote branches)
git checkout -b feature origin/feature (where "feature" is the local branch name and "origin/feature" is the remote branch name)

After you've done your initial push or checkout, you can just run git push to update the remote branch or git pull to fetch and merge from that remote branch (with the above caveat about already using origin). In this way, you can continue to distribute changes to one another.

Committing Upstream
Once you're done with your feature, it's time to commit to master/svn. Do one last pull or svn rebase on master (as described above). Then it's time to run the process in reverse with one important change.
Assuming your working copy is already on your feature branch.
git merge master (to sync with your upstream in your feature branch)
Fix any conflicts and commit the merge.
git checkout master
git merge --squash feature (The --squash flag will combine all your changes into one complete changeset. This will also leave everything uncommitted in the index so you can have a look.)
git commit -m "Here's a great summary of everything I did in my feature branch that will be visible upstream,"

git push
or
git svn dcommit

Props
I got my start with git-svn after reading a post by the viget guys.

No comments: