This is a very simple git workflow. It (and variants) is in use by many people. I settled on it after using it very effectively at Athena. GitHub does something similar; Zach Holman mentioned it in this talk.
Update: Woah, thanks for all the attention. Didn't expect this simple rant to get popular.
Special Thanks to friends for feedback:
master
must always be deployable.- all changes made through feature branches (pull-request + merge)
- rebase to avoid/resolve conflicts; merge in to
master
Or, as Zach Holman succinctly put it:
# everything is happy and up-to-date in master
git checkout master
git pull origin master
# let's branch to make changes
git checkout -b my-new-feature
# go ahead, make changes now.
$EDITOR file
# commit your (incremental, atomic) changes
git add -p
git commit -m "my changes"
# keep abreast of other changes, to your feature branch or master.
# rebasing keeps our code working, merging easy, and history clean.
git fetch origin
git rebase origin/my-new-feature
git rebase origin/master
# optional: push your branch for discussion (pull-request)
# you might do this many times as you develop.
git push -u origin my-new-feature
# optional: feel free to rebase within your feature branch at will.
# ok to rebase after pushing if your team can handle it!
git rebase -i origin/master
# But when you do that overwrite your published branch
# See this discussion: http://stackoverflow.com/questions/33123802/merge-after-rebasing-feature-branch-in-git/33125444?noredirect=1#comment54063368_33125444
git push origin my-new-feature --force-with-lease
# merge when done developing.
# --no-ff preserves feature history and easy full-feature reverts
# merge commits should not include changes; rebasing reconciles issues
# github takes care of this in a Pull-Request merge
git checkout master
git pull origin master
git merge --no-ff my-new-feature
# Then get rid of the feature branch
git branch -d my-new-feature
# Delete the branch also on origin: http://stackoverflow.com/questions/2003505/delete-a-git-branch-both-locally-and-remotely/2003515#2003515
git push origin --delete my-new-feature
# And prune it for it to stay gone
git remote prune origin
# optional: tag important things, such as releases
git tag 1.0.0-RC1
# autosetup rebase so that pulls rebase by default
git config --global branch.autosetuprebase always
# if you already have branches (made before `autosetuprebase always`)
git config branch.<branchname>.rebase true
No DO or DON'T is sacred. You'll obviously run into exceptions, and develop your own way of doing things. However, these are guidelines I've found useful.
- DO keep
master
in working order. - DO rebase your feature branches.
- DO pull in (rebase on top of) changes
- DO tag releases
- DO push feature branches for discussion
- DO learn to rebase
- DON'T merge in broken code.
- DON'T commit onto
master
directly.- DON'T hotfix onto master! use a feature branch.
- DON'T rebase
master
. - DON'T merge with conflicts. handle conflicts upon rebasing.
Yes. Merge bubbles aren't inherently bad. They allow you to revert entire features at a time. They get confusing and annoying to deal with if they cross (commits interleave), so don't do that.
http://en.wikipedia.org/wiki/Atomic_commit#Atomic_Commit_Convention
Thanks wikipedia, I couldn't have put it better myself.
Why not gitflow or another complex workflow?
Be my guest. I've used gitflow and other similar models. After working in various teams, this is just what I've come to use. But next time you have to ask someone whether it is okay to push or pull from this or that branch, remember my face.
But, is it web-scale?
Friends claim more complex models are necessary for scaling large teams,
maintaining old releases, controlling information flow, etc. It very well may
be that using multiple mainlines (e.g. develop
, stable
, release
, v2
,
tested
, etc) is exactly what fits your organization's constraints. That's
for you to decide, not me (unless we work together -- oh hi there!).
But you always have to wonder, "shouldn't I use tags for that"? For example, tracking releases on a branch is a bit silly. A release commit can be tagged. You can checkout a tag, just like any branch, or any commit, and do whatever it is you need to do.
My guess is this relationship holds:
So, perhaps taking five minutes to teach your team how to use checkout
and
tag
might save you more than 15% on car insurance.
Sometimes I see people forking repositories in order to issue pull-requests. Yes, you may have to do this when contributing to open-source projects you don't regularly contribute to. But, if you are a contributor, or working in the same org, get push rights on the repo and push all your feature branches to it. Issue pull requests from one branch to another within the same repo.
Up to you. Github does git merge --no-ff
so that the commit message indicates
the pull request number. This is useful information to have, don't just throw
away history for the sake of it. You never know what will be useful to look at
in the future.