a rad, but not radical, pragmatic git strategy
I’ve been using Git for over two years, across two jobs, multiple teams and dozens of projects. I’m not a Git Ninja (and pretending to be has earned me exactly 0 second dates) but I’m generally comfortable with and successfully use it. I’d like to share the latest iteration of a strategy for Git that is working for me quite well.

Notice I said iteration. I’ve tried and worked with a lot varying strategies up to this point. I love how flexible Git is. It’s been a pleasure to use and discover and, like my brain, I’m probably only using a fraction of it. But, that’s ok. I have been able to do everything I want with it. And, if I couldn’t at the time there’s the man, a fantastic book, and countless other resources via google.
I think there are tons of existing attempts at general introductions to Git so let’s assume if you’re here and reading this, you understand the basic ability to commit, branch, merge, resolve conflicts and you’ve setup at least one remote reference you’ve pushed and pulled—wait; no, not pull—fetched and merged from.
On that last note, I’d like to suggest you all get in the habit of the same. Stop pulling. It’s a bad habit considering the strategy here and I think it enables you to be more specific with your merge strategies among other things.
Local vs Master or: How I Learned to Stop Worrying and Love the Rebase
Remember all those warnings when you were getting started to never rebase? Time to unlearn. Sort of. I still agree, generally; it should be assumed harmful. It’s a powerful, dangerous feature. If you’re just getting started with it my suggestion is before rebasing anything, ever, create a branch you can safely delete in the unlikely and probable chance that you trash it.
Let me step backward. One of the greatest challenges over the years, teams and projects has, without a contest, been getting a fluid, painless branch and merge strategy when there were differences (albeit subtle) between the local development copy and the production, or master branch.
You want to work locally, but maybe you had to modify the database driver credentials, or that file uploads directory, etc. in order to have your local development copy actually functional. You probably tried creating a dev branch or similar, maybe you were really careful never to commit that db config file change, or you stashed your changes prior to checking your master branch back out, adding, committing and pushing it upstream only to then re-checkout your local branch, merge production, apply your stash and…
— oh, wait, something was upstream you had to fetch and re-merge and there was a conflict and
— oh, shit, did you accidentally commit that database config?
— wait, did you just merge the wrong branch or wrong direction?
— OMG WHAT HAPPENED TO THE HISTORY GRAPH?!
stabs eyes out
Maybe you never made those or similar mistakes in action or strategy. Nice! Let’s keep moving…
The best strategy I’ve found to date is this: checkout your master branch. Create a branch from here called dev, local, whatever. Make any and all necessary local-only changes you never want or need to send anywhere else. Make a single commit and label it something horrible and eye-catching like LOCAL DEVELOPMENT CONFIGURATIONS.
You never want to see that in master or anything else directly merged into it.
Ok, great. Now the fun part. You want to work on something locally but fully intend to merge it back into master, or simply push upstream so a friend can commit and you can work together.

- Checkout master, create your branch off it (let’s say
my-feature-branch). - Create another branch off
my-feature-branchcalleddev.my-feature-branchor the like. - Merge your
devbranch containing the local commit into this.
Now, edit your files, testing locally. Ready to commit?
- Checkout
my-feature-branch - Commit your changes to this branch, lacking the local config commit, and push this one upstream and/or fetch and merge any changes upstream as needed.
- Checkout your
dev.my-feature-branchagain git rebase my-feature-branchrebases your local config commit back to the top of the now updated state ofmy-feature-branch.
And that’s it. Same strategy for committing straight to master, really.
“I’ve made a huge mistake.”
At some point accidentally, or perhaps intentionally as you get comfortable, you’ve made a commit to the dev branch that you want merged back into master. Unfortunately that commit now sits on top of your local config commit.
Like the honey badger, you simply don’t care anymore because Git has you covered with cherry-pick. Grab the hash of that commit you’d like on master, checkout master and cherry-pick that commit, re-checkout your dev branch and git rebase master.
Give yourself a high-five and you owe me a beer.