giant robots smashing into other giant robots

Written by thoughtbot

cpytel

Introducing Trajectory GitHub Integration

Today I’m pleased to announce the availability of one of our most requested Trajectory features, GitHub integration.

We’ve never really used the GitHub integration in any of the previous tracking/planning software we used because it’s so hard to use it consistently and well. When we set out to implement GitHub integration we set the bar high by insisting that it be something we would actually use. I believe we have done that with a new feature that I don’t believe has ever been done before for GitHub integration.

Now, when you start a story, Trajectory will indicate an auto-generated feature branch name (you can change the branch name, if you want). Any commits against this branch in GitHub will automatically be associated with the story. There is no need to include the story URL in the commit message, unless you are issuing a command to Trajectory (such as to Finish the story).

This functionality solves a real problem with the integration with GitHub while embracing the way many of you are probably already working with feature branches in your repos.

In addition to the feature branch integration, you can also include a link to stories in individual commit messages. When you do this, Trajectory will associate the commit to the story. Finally, you can issue commands to Finish a story in Trajectory from your commit.

You can read more specifics about this new functionality on our support site. If you’re already using Trajectory, go ahead and give it a try. If you’re not using Trajectory, sign up for a free trial and give it a try. You can even get started quickly by importing your Pivotal Tracker projects.

gabebw

Push the current git branch, even if you’ve never pushed it before

The first time you push a git branch to a remote, you have to be explicit the first time:

git push origin my-branch-name

Every time after that, a simple git push will work fine. But there’s a ~/.gitconfig setting that will let you just git push without needing that initial explicitness:

[push]
# Push current branch even if you've never pushed it before
default = current

You might want to take a look at my gitconfig for more tips.

dancroak

Keeping a GitHub fork updated

I forked a GitHub repo thoughtbot/dotfiles to croaky/dotfiles and want to keep the fork updated.

Track

After I forked the repo to your Github account, I did this one time:

git clone git@github.com:croaky/dotfiles.git
cd dotfiles
git remote add upstream git@github.com:thoughtbot/dotfiles.git

Update

Each time I want to update, from my local master branch:

git fetch upstream
git rebase upstream/master

The goal of the rebase is to have a cleaner history if I have local changes or commits on the repo. It’s the difference between the the left and the right in the image below.

image

Commit rights upstream?

If I also have commit rights to the upstream repo, I can create a local upstream branch and do work that will go upstream there.

git checkout -b upstream upstream/master

Written by .

hgimenez

Streamline your git workflow with aliases

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:

1. Start a story with a new branch.

From the master branch, run

git checkout -b feature_x

2. Hack and commit often in that branch

vi file.rb
git add -u
git add .
git status
git commit -m "Make changes"

3. Pull in upstream changes as often as possible

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

4. Clean up the history by squashing commits

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

5. Merge into master, run all tests and push upstream

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:

1. Start a story with a new branch

git cob feature_x

2. Hack and commit often in that branch

vi file.rb
git aa
git c "Make changes"

3. Pull in upstream changes as often as possible

git up

4. Clean up the history by squashing commits

git ir

5. Merge into master, run all tests and push upstream

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?

dancroak

Feature branch code reviews

“Code review.” My knee-jerk reaction to that phrase? Nap time.

Sleepy Parliament

I’ll be honest, I never really felt engaged during “code review” meetings at the end of an iteration. It always took too long to get and discuss the code. The room would get warmer. We’d discover things we’d want to change. Many of those changes would never be made.

Since today is Boycott a Meeting Day, I thought I’d offer an alternative we’ve used lately.

Here’s the flow. Read Josh Susser’s post for the git commands.

  1. Start a user story.
  2. Code the feature.
  3. Push the feature to a branch.
  4. A Github hook starts a CI build.
  5. A Github Campfire hook posts your work to Campfire.
  6. Click the link that’s in Campfire.
  7. Click the Github “Pull Request” button.
  8. It will smartly select all commits in your branch that are not in master.
  9. Create the pull request.
  10. Ask your team in Campfire for a review of the pull request.
  11. The team comments in-line, right on the code.
  12. Make the suggested changes.
  13. Merge into master.
  14. Push to master.
  15. CI runs again.
  16. Deploy to staging.

Many teams use this “feature branch” pattern. The “code review” part is the Github pull request flow stuck right before the code goes into master.

Here’s what a pull request looks like:

Pull Request

Notice the jm-cm-client-sets-up-recurring-payment branch is compared to master.

And here’s what a comment on a commit looks like:

Commit comment

You could use normal git tools to check out a team member’s feature branch, view the history, etc., but Github one-ups bare git by adding a streamlined user interface and commenting.

Why we like it

Test-Driven Development moves code failure earlier in the development process. It’s better to have a failing test on your development machine than in production. It also allows you to have tighter feedback cycles.

Code reviews that happen right before code goes into master offer similar benefits:

  • The whole team learns about new code as it is written.
  • Mistakes are caught earlier.
  • Coding standards are more likely to be established, discussed, and followed.
  • Feedback from this style of code review is far more likely to be applied.
  • No one forgets context (“Why did we write this?”) since it’s fresh in the author’s mind.

I’ve personally loved this process. Give it a shot!

Written by .