Reviewing Git feature branches when you don’t have pull requests

I’m not always using Git in an environment that supports pull requests. My preferred Git workflow, even within a team of co-workers who sit together, is to have features developed and tested within a feature branch, then reviewed and merged via pull request. I took a page from Vincent Driessen‘s playbook, A successful Git branching model, which gives a step-by-step explanation.

But easy-to-review pull requests are a feature of GitHub and BitBucket, not Git itself. (git request-pull doesn’t cut it.) Here’s my current workflow to review a feature’s worth of changes.

I’m using posh-git within Console2 (with Scott Hanselman’s customizations because I’m a subtle badass) for issuing commands, and SourceTree for visualizing what’s going on.

The Goal: Get a list of all files changed for this feature and compare each one’s initial state against its final state, without any noise from merges from master.

The Approach: Pretend I’m going to merge the feature into master but don’t commit it. Diff the pending changes and send my recommendations. Then throw away the changes and clean everything up.

git checkout master
git merge ‑‑no‑ff ‑‑no‑commit name_of_their_feature_branch

First I check out master as the branch I want to merge into. Then I run a merge with two important options. No-fast-forward (‑‑no‑ff) makes the feature join into master with a single, explicit merge commit. This tells git, even if it could perform a fast-forward merge, where it applies each of the feature-branch commits as if they had been committed straight to master, please don’t. With the ‑‑no‑ff option, you’ll have the single, show-me-everything commit you wanted to review. The second, ‑‑no‑commit, is even more important: Stage them but don’t commit them. (Although, as long as you don’t push to a remote, even that is reversible. This choose-your-own-adventure git guide reassuringly walks you through revising history.)

Because you are taking a trial-run at merging the feature to master, you may need to resolve some merge conflicts. Go ahead and do so, since that will give you a realistic picture of the finished feature.

After the Review: You’ve finished with your review and are ready to clean up your working directory. Here are the commands to discard the changes.

This throws away your work, but you were just pretend-merging anyway, right?

git reset ‑‑hard
git clean ‑fd

reset sets the current branch back to the most recent commit, and ‑‑hard says to discard changes to tracked files. This does not clean up new files that the feature branch added. That’s what clean takes care of. The ‑f option is for “force,” since Git can be configured to not execute a clean unless you expressly specify force—a little safety net since clean is so destructive. The ‑d option instructs Git to also remove newly created directories. (Some folks include ‑x, to throw away even files that would have been ignored by your .gitignore, such as dlls in your bin folder. This is a little too thorough for me, so I don’t use it.)

So there you go. To review what will be changed by a feature branch, pretend to merge it and see what changed.

Related Articles:

About Sharon Cichelli

I am a Headspring Senior Consultant, developing custom enterprise software for our clients and leading training classes on the latest Microsoft technologies. I blog about .NET development, best practices in agile software development, and my nerdy hobbies.
This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Martin

    Or you could git difftool –dir-diff integrationbranch featurebranch
    No need to dirty working dir. And with beyond compare gives you directory overview.

  • http://szelpe.hu Peter Szel

    Nice article!
    I’d recommend using a self-hosted alternative to github or bitbucket like Gitlab, Gitorious or Atlassian Stash so that you will have the pull-request feature on hands.

  • Tof

    The “rerere” git option is useful here, if you don’t want to manage conflicts twice !