Skip to content

Instantly share code, notes, and snippets.

@jbenet
Last active July 21, 2025 21:02

Revisions

  1. jbenet revised this gist Feb 21, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion simple-git-branching-model.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    # a **simple** git branching model
    # a **simple** git branching model (written in 2013)

    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](http://athena.ai).
  2. jbenet revised this gist Sep 18, 2014. 3 changed files with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions simple-git-branching-model.md
    Original file line number Diff line number Diff line change
    @@ -22,7 +22,7 @@ Special Thanks to friends for feedback:

    Or, as Zach Holman succinctly put it:

    ![flow](z-git-branching.jpeg)
    ![flow](https://www.evernote.com/shard/s198/sh/ab988957-0a27-4674-9e81-ddb59fb4f2c8/cce725edb5dac7881acc9bc9db2bd26a/deep/0/Pasted-Image-2014-09-17-19-02.png)

    ### The workflow

    @@ -118,7 +118,7 @@ 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.

    ![merge bubbles](z-git-bubbles.png)
    ![merge bubbles](https://www.evernote.com/shard/s198/sh/dd72254c-d495-484a-a1e8-c5f5da2ab3ff/7528df9082beaf9f2465ef970261a7dd/deep/0/Pasted-Image-2014-09-17-19-02.png)


    ### What do you mean by "incremental, atomic" changes?
    @@ -152,7 +152,7 @@ whatever it is you need to do.

    My guess is this relationship holds:

    ![headless](z-git-headless.jpeg)
    ![headless](https://www.evernote.com/shard/s198/sh/2e7a963c-25f2-41d7-b38d-3e5b611ba4b7/f408f2bb0844bb27c3f1bbb71f3f9812/deep/0/Pasted-Image-2014-09-17-19-03.png)

    So, perhaps taking five minutes to teach your team how to use `checkout` and
    `tag` might save you more than 15% on car insurance.
    File renamed without changes
    File renamed without changes
  3. jbenet revised this gist Sep 18, 2014. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions simple-git-branching-model.md
    Original file line number Diff line number Diff line change
    @@ -22,7 +22,7 @@ Special Thanks to friends for feedback:

    Or, as Zach Holman succinctly put it:

    ![flow](https://gist.github.com/jbenet/ee6c9ac48068889b0912/raw/24c6696441e40eae24805426ba5465583414d046/z-git-branching.jpeg)
    ![flow](z-git-branching.jpeg)

    ### The workflow

    @@ -118,7 +118,7 @@ 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.

    ![merge bubbles](https://gist.github.com/jbenet/ee6c9ac48068889b0912/raw/4a6876d77884853521692df8dbb22914f9f81109/z-git-bubbles.png)
    ![merge bubbles](z-git-bubbles.png)


    ### What do you mean by "incremental, atomic" changes?
    @@ -152,7 +152,7 @@ whatever it is you need to do.

    My guess is this relationship holds:

    ![headless](https://gist.github.com/jbenet/ee6c9ac48068889b0912/raw/ef8be1e41fb8ae0e58de732103e09588f6ba8156/z-git-headless.jpeg)
    ![headless](z-git-headless.jpeg)

    So, perhaps taking five minutes to teach your team how to use `checkout` and
    `tag` might save you more than 15% on car insurance.
  4. jbenet revised this gist Sep 18, 2014. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions simple-git-branching-model.md
    Original file line number Diff line number Diff line change
    @@ -22,7 +22,7 @@ Special Thanks to friends for feedback:

    Or, as Zach Holman succinctly put it:

    ![flow](https://gist.github.com/shvechikov/de39c99574488a3de12a/raw/24c6696441e40eae24805426ba5465583414d046/z-git-branching.jpeg)
    ![flow](https://gist.github.com/jbenet/ee6c9ac48068889b0912/raw/24c6696441e40eae24805426ba5465583414d046/z-git-branching.jpeg)

    ### The workflow

    @@ -118,7 +118,7 @@ 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.

    ![merge bubbles](https://gist.github.com/shvechikov/de39c99574488a3de12a/raw/4a6876d77884853521692df8dbb22914f9f81109/z-git-bubbles.png)
    ![merge bubbles](https://gist.github.com/jbenet/ee6c9ac48068889b0912/raw/4a6876d77884853521692df8dbb22914f9f81109/z-git-bubbles.png)


    ### What do you mean by "incremental, atomic" changes?
    @@ -152,7 +152,7 @@ whatever it is you need to do.

    My guess is this relationship holds:

    ![headless](https://gist.github.com/shvechikov/de39c99574488a3de12a/raw/ef8be1e41fb8ae0e58de732103e09588f6ba8156/z-git-headless.jpeg)
    ![headless](https://gist.github.com/jbenet/ee6c9ac48068889b0912/raw/ef8be1e41fb8ae0e58de732103e09588f6ba8156/z-git-headless.jpeg)

    So, perhaps taking five minutes to teach your team how to use `checkout` and
    `tag` might save you more than 15% on car insurance.
  5. @shvechikov shvechikov revised this gist Dec 9, 2013. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions simple-git-branching-model.md
    Original file line number Diff line number Diff line change
    @@ -26,7 +26,7 @@ Or, as Zach Holman succinctly put it:

    ### The workflow

    ```
    ```bash
    # everything is happy and up-to-date in master
    git checkout master
    git pull origin master
    @@ -70,7 +70,7 @@ git tag 1.0.0-RC1

    ### useful config

    ```
    ```bash
    # autosetup rebase so that pulls rebase by default
    git config --global branch.autosetuprebase always

  6. @shvechikov shvechikov revised this gist Dec 9, 2013. 4 changed files with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions simple-git-branching-model.md
    Original file line number Diff line number Diff line change
    @@ -22,7 +22,7 @@ Special Thanks to friends for feedback:

    Or, as Zach Holman succinctly put it:

    ![flow](http://static.benet.ai/skitch/flow-20130926-193419.png)
    ![flow](https://gist.github.com/shvechikov/de39c99574488a3de12a/raw/24c6696441e40eae24805426ba5465583414d046/z-git-branching.jpeg)

    ### The workflow

    @@ -118,7 +118,7 @@ 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.

    ![merge bubbles](http://static.benet.ai/skitch/mergebubbles-20130926-182853.png)
    ![merge bubbles](https://gist.github.com/shvechikov/de39c99574488a3de12a/raw/4a6876d77884853521692df8dbb22914f9f81109/z-git-bubbles.png)


    ### What do you mean by "incremental, atomic" changes?
    @@ -152,7 +152,7 @@ whatever it is you need to do.

    My guess is this relationship holds:

    ![headless](http://static.benet.ai/t/headless.png)
    ![headless](https://gist.github.com/shvechikov/de39c99574488a3de12a/raw/ef8be1e41fb8ae0e58de732103e09588f6ba8156/z-git-headless.jpeg)

    So, perhaps taking five minutes to teach your team how to use `checkout` and
    `tag` might save you more than 15% on car insurance.
    Binary file added z-git-branching.jpeg
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
    Binary file added z-git-bubbles.png
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
    Binary file added z-git-headless.jpeg
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
  7. jbenet revised this gist Sep 28, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion simple-git-branching-model.md
    Original file line number Diff line number Diff line change
    @@ -9,7 +9,7 @@ in [this talk](http://www.youtube.com/watch?v=qyz3jkOBbQY&t=09m12s).
    to get popular.

    Special Thanks to friends for feedback:
    - [@sqs](https://github.com/sqs) from [Sourcegraph](https://sourcegraph.com)
    - [@sqs](https://sourcegraph.com/sqs) from [Sourcegraph](https://sourcegraph.com)
    - [@feross](https://github.com/feross) from [PeerCDN](https://peercdn.com)
    - [@msparks](https://github.com/msparks) from [Google](https://google.com)

  8. jbenet revised this gist Sep 28, 2013. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions simple-git-branching-model.md
    Original file line number Diff line number Diff line change
    @@ -9,9 +9,9 @@ in [this talk](http://www.youtube.com/watch?v=qyz3jkOBbQY&t=09m12s).
    to get popular.

    Special Thanks to friends for feedback:
    - @sqs from [Sourcegraph](https://sourcegraph.com)
    - @feross from [PeerCDN](https://peercdn.com)
    - @msparks from [Google](https://google.com)
    - [@sqs](https://github.com/sqs) from [Sourcegraph](https://sourcegraph.com)
    - [@feross](https://github.com/feross) from [PeerCDN](https://peercdn.com)
    - [@msparks](https://github.com/msparks) from [Google](https://google.com)


    ### The gist
  9. jbenet revised this gist Sep 28, 2013. 1 changed file with 8 additions and 0 deletions.
    8 changes: 8 additions & 0 deletions simple-git-branching-model.md
    Original file line number Diff line number Diff line change
    @@ -5,6 +5,14 @@ I settled on it after using it very effectively at [Athena](http://athena.ai).
    [GitHub](https://github.com) does something similar; Zach Holman mentioned it
    in [this talk](http://www.youtube.com/watch?v=qyz3jkOBbQY&t=09m12s).

    **Update:** Woah, thanks for all the attention. Didn't expect this simple rant
    to get popular.

    Special Thanks to friends for feedback:
    - @sqs from [Sourcegraph](https://sourcegraph.com)
    - @feross from [PeerCDN](https://peercdn.com)
    - @msparks from [Google](https://google.com)


    ### The gist

  10. jbenet revised this gist Sep 27, 2013. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions simple-git-branching-model.md
    Original file line number Diff line number Diff line change
    @@ -72,6 +72,10 @@ git config branch.<branchname>.rebase true

    ### DOs and DON'Ts

    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.

    #### DOs

    - **DO** keep `master` in working order.
  11. jbenet revised this gist Sep 27, 2013. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions simple-git-branching-model.md
    Original file line number Diff line number Diff line change
    @@ -74,12 +74,12 @@ git config branch.<branchname>.rebase true

    #### DOs

    - **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
    - **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'Ts
  12. jbenet revised this gist Sep 27, 2013. 1 changed file with 13 additions and 13 deletions.
    26 changes: 13 additions & 13 deletions simple-git-branching-model.md
    Original file line number Diff line number Diff line change
    @@ -72,23 +72,23 @@ git config branch.<branchname>.rebase true

    ### DOs and DON'Ts

    DOs:
    #### DOs

    - 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
    - **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'Ts:
    #### DON'Ts

    - 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.
    - **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.


    ### Links
  13. jbenet revised this gist Sep 27, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion simple-git-branching-model.md
    Original file line number Diff line number Diff line change
    @@ -14,7 +14,7 @@ in [this talk](http://www.youtube.com/watch?v=qyz3jkOBbQY&t=09m12s).

    Or, as Zach Holman succinctly put it:

    ![flow](http://static.benet.ai/skitch/comfortbeingheadless-20130926-190306.png)
    ![flow](http://static.benet.ai/skitch/flow-20130926-193419.png)

    ### The workflow

  14. jbenet revised this gist Sep 27, 2013. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions simple-git-branching-model.md
    Original file line number Diff line number Diff line change
    @@ -12,6 +12,10 @@ in [this talk](http://www.youtube.com/watch?v=qyz3jkOBbQY&t=09m12s).
    1. **all changes** made through feature branches (pull-request + merge)
    1. rebase to avoid/resolve conflicts; merge in to `master`

    Or, as Zach Holman succinctly put it:

    ![flow](http://static.benet.ai/skitch/comfortbeingheadless-20130926-190306.png)

    ### The workflow

    ```
  15. jbenet revised this gist Sep 27, 2013. 1 changed file with 20 additions and 0 deletions.
    20 changes: 20 additions & 0 deletions simple-git-branching-model.md
    Original file line number Diff line number Diff line change
    @@ -140,3 +140,23 @@ 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.


    ## GitHub notes


    ### Don't fork. Push feature branches to main repo.

    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.**


    ### Should I merge Pull Requests on the site or commandline?

    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.
  16. jbenet renamed this gist Sep 27, 2013. 1 changed file with 13 additions and 14 deletions.
    27 changes: 13 additions & 14 deletions model.md → simple-git-branching-model.md
    Original file line number Diff line number Diff line change
    @@ -22,7 +22,7 @@ git pull origin master
    # let's branch to make changes
    git checkout -b my-new-feature
    # go ahead, make changes now.
    # go ahead, make changes now.
    $EDITOR file
    # commit your (incremental, atomic) changes
    @@ -114,30 +114,29 @@ Thanks wikipedia, I couldn't have put it better myself.

    ### Why not [gitflow](http://nvie.com/git-model/) 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](http://juan.benet.ai/img/juan.batizbenet.headshotsq.jpg).
    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](http://juan.benet.ai/img/juan.batizbenet.headshotsq.jpg).


    ### But, is it [web-scale](http://mongodb-is-web-scale.com/)?

    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`,
    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.
    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:

    ![headless](http://static.benet.ai/t/headless.png)

    So, perhaps taking five minutes to teach your team how to use `checkout` and
    So, perhaps taking five minutes to teach your team how to use `checkout` and
    `tag` might save you more than 15% on car insurance.
  17. jbenet created this gist Sep 27, 2013.
    143 changes: 143 additions & 0 deletions model.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,143 @@
    # a **simple** git branching model

    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](http://athena.ai).
    [GitHub](https://github.com) does something similar; Zach Holman mentioned it
    in [this talk](http://www.youtube.com/watch?v=qyz3jkOBbQY&t=09m12s).


    ### The gist

    1. `master` must always be deployable.
    1. **all changes** made through feature branches (pull-request + merge)
    1. rebase to avoid/resolve conflicts; merge in to `master`

    ### The workflow

    ```
    # 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 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
    # 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
    # optional: tag important things, such as releases
    git tag 1.0.0-RC1
    ```

    ### useful config

    ```
    # 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
    ```

    ### DOs and DON'Ts

    DOs:

    - 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'Ts:

    - 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.


    ### Links

    - https://github.com/blog/1124-how-we-use-pull-requests-to-build-github



    ## FAQ


    ### Won't `git merge --no-ff` generate merge bubbles?

    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.

    ![merge bubbles](http://static.benet.ai/skitch/mergebubbles-20130926-182853.png)


    ### What do you mean by "incremental, atomic" changes?

    http://en.wikipedia.org/wiki/Atomic_commit#Atomic_Commit_Convention

    Thanks wikipedia, I couldn't have put it better myself.


    ### Why not [gitflow](http://nvie.com/git-model/) 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](http://juan.benet.ai/img/juan.batizbenet.headshotsq.jpg).


    ### But, is it [web-scale](http://mongodb-is-web-scale.com/)?

    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:

    ![headless](http://static.benet.ai/t/headless.png)

    So, perhaps taking five minutes to teach your team how to use `checkout` and
    `tag` might save you more than 15% on car insurance.