My git workflow

I’ve written and shared my git workflow a couple times, but only privately. I’ve been meaning to write more about it and share it publicly for some time now. This workflow has worked very well for me for the past year or so, but I am by no means a git expert. Take a look and let me know what you think. I’m always open to hearing about other peoples’ workflows and suggestions. So much to learn – I’ve only scratched the surface.

Some Caveats

These instructions assume that you are working independently on your feature branches and no one else is working on those feature branches with you. If you are collaborating with others in your feature branches then you should not be following these instructions as rebasing and force pushing on your feature branches will screw things up for others using those branches!

This also assumes you are using a pull request based workflow to merge your changes back into the development branch. If you are not using pull requests, you’ll have to merge your changes in manually. There are some great reasons to use pull requests for code review:

  • It helps keep code consistent across the project.
  • It keeps all team members aware of what others are working on.
  • It helps catch mistakes.
  • It reminds you to push your local work to the remote.
  • Good practice for contributing to open source projects.

Starting a new feature/bug fix:

  • Assuming the branch is based off of develop
  • git fetch origin
  • git rebase origin/develop
    gets the latest from origin/develop and applies it to your local branch

Checkout a new branch for the feature

  • git checkout -b feature-name

Make your changes in the code

  • After editing files:
  • git add .
  • git commit -m "Short commit message"
    or
    git commit --amend
    • Use a new commit message if it’s warranted
    • Otherwise, use –amend to make changes to the most recent commit
  • Here is an example of a long commit message:
    git commit -m "Short overview message
     - I'm a more detailed bullet point about the commit
     - I'm another more detailed bullet point about the commit"
    • Break long commit messages into multiple points, with a short leading summary

Push changes to the remote branch

  • Make sure you have the latest from develop
    • git checkout feature-name
      if not already on that branch
    • git fetch origin
    • git rebase origin/develop
  • git push origin feature-name
    If you rebase, and origin/feature-name already exists, you will have to force push:
    git push origin feature-name -f

When ready for review:

  • Create pull request (PR) on github, bitbucket, stash, etc. website
    • Make sure PR merges into develop branch and not master.

Make changes based on feedback from PR

  • git add .
  • git log
    look for the commit you want to ammend
  • git commit --fixup [sha]
    • [sha] is based on commit id you are applying fix to
  • Repeat as many times as necessary

Push fixups to remote

  • git push origin feature-name

Clean up commits after pull request has been approved

  • Rebase to clean up commits
  • git log
    look for [sha-1]
    • [sha – 1] is one commit prior to the one you want to keep
  • git rebase [sha - 1] -i --autosquash
  • git push origin feature-branch -f
    • We have to force push because we’ve rewritten history
  • merge pull request on github/bitbucket/stash website

After merging pull request (PR) into development branch in github/bitbucket/stash UI

  • git checkout development
  • git fetch origin
  • git rebase origin/develop
    Get your committed changes in your local develop
  • git branch -d feature-name
    Delete your local branch, unless you still need it

FAQ

When do I use ‘–amend’ vs ‘–fixup’?

I use ‘–amend’ when I have committed partially completed functionality. When i Am just adding additional functionality to my previous commit, I will use an ammend. It is very useful for making changes to already committed work. When you make an amend, however, you don’t get incremental changes, so it is not good to use after you have started your pull request (there are exceptions). ie, it will be very difficult for your PR reviewer to know what you’ve changed if you use –amend. Instead we use –fixup if the changes will be reviewed.

You will use –fixup to make changes to a pending pull request as then each change is tracked and can be reviewed individually. Once approved, the fixups get combined into the commits they are fixing up.

When is rebasing/force-pushing safe?

The thing to understand about rebasing and force-pushing is that they rewrite history. They are very powerful and useful tools, but must be used responibly, or else they will wreak havoc on other people. Before rebasing, ask yourself Am I the only one using this branch? If the answer is ‘no’, then you should definitely not be rebasing.

Why use Rebase over Merge?

There are lots of great resources out there on this argument, including some great posts on StackOverflow. That said, I probably lean a bit more towards rebase than I should. I like a clean commit history. I think it keeps things cleaner and easier to review. I also like the ability to abort a rebase if things start to go sour. That said, there are some definite disadvantages to rebasing as well. You lose the history of what changes you are incorporating. Reverting after a rebase is a very tricky process. Additionally, using merge vs rebase is a more ‘authentic’ history as rebasing changes timestamps to match the time of the rebase instead of when the work might have actually been done. In my mind, these are all fair tradeoffs for the benefits gained around rebasing – which for me are primarily organizational.


I am by no means a git expert, but this workflow has worked pretty well for me. Let me know your thoughts and questions in the comments.

Leave a Reply

Your email address will not be published. Required fields are marked *