My git Workflow
March 29, 2014I've settled into what I think is an effectively simple git workflow that I thought would be helpful to share.
Let's say I am working on a new feature. First thing I want to do is make sure my local copy of the codebase is up-to-date:
$ git pull master
I'll then create a new feature branch. In my experience, 99% of the time I am branching off of master:
$ git checkout -b an-awesome-new-feature
But it’s just as easy to branch off another branch:
$ git checkout -b an-awesome-new-feature some-other-branch
Within this new branch, I can spike on the new feature, and if things get hairy I can blow it away and start over. I'll commit often. Most of my commits during the spike or early phase of a feature will look like:
$ git commit -am "WIP specs"
If I am pairing, I will be more descriptive with the commit messages. But when I am coding alone, these pre-PR commits are for me, and are not meant to be used for any meaningful code review. When I am satisfied that I the work I've done will eventually become a PR, I'll push my branch to a remote:
$ git pushr
The pushr
command is a nice little shortcut from the dotfiles I use. It creates a remote branch with the same name as my local branch, in this case, an-awesome-new-feature
. After the initial git pushr
, I can just do git push
and it will push to the remote branch.
The "do some work, test, commit, push" loop happens until I am
satisfied that the feature is ready for a pull request. If a new feature
was merged into master
that will effect my feature, I'll
pull the changes in, and then do:
$ git rebase master
Recently I've gotten into the habit of rebasing my
feature branches whenever anything is merged into master
,
even if I don't think they will effect what I am doing. I've done this
mainly because, if there is a conflict, I'd rather be in merge hell in
the middle of working on a feature than at the end of a feature. It's dispiriting when you're about to open a shiny new PR and you realize it won't merge cleanly.
At this point I
will rebase
and squash all of my commits on the
an-awesome-new-feature
branch into one commit. This commit
message will be as informative (detailed) as possible, since it will become the
basis for the pull request message.
Once that's done, I'll force push to the branch with my new rebased history:
$ git push --force
I'll then open my pull request. I will push new commits to the branch after the PR is open, based on feedback. Once I get a :shipit:, I like to re-squash all post-PR commits back into the first PR commit.
There's
been some discussion on our team about the merits and demerits of this
approach. I like to have one commit per PR when it's possible. It seems
cleaner to me. But there's a good argument for not doing this, since
those post-PR commits were changes made based on feedback, and that
feedback history is important to have. Personally, I feel the comments
in the PR on GitHub are sufficient as far as history goes. Usually if I
want to dig deeper into what went into a new feature and why, I'll go back and re-read
the PR message and subsequent comments, as opposed to reading commit messages in git log
. But that's my
own preference. The other way is fine too, in my opinion.
In either case, once the PR is merged, the feature branch is deleted
locally and remotely. The master
is updated locally via
git pull
, and the cycle repeats.