Skip to content

Instantly share code, notes, and snippets.

@klj613
Created September 21, 2012 21:24
Show Gist options
  • Save klj613/3763991 to your computer and use it in GitHub Desktop.
Save klj613/3763991 to your computer and use it in GitHub Desktop.
Rebase git flow
Rebasing Git Flow
=================
TL;DR
-----
- All feature branches are rebased to latest master
- All staging branches are rebased to latest master
- All finalized feature branches are rebased then --no-ff merged into a staging branch
- All staging branches gets signed off and tested before --no-ff into master
- Remove all history of staging branches
- All feature branches prefixed by an author name is only to be used by the author.
- If any feature-branches rely heavily on each other then they are actually sub-feature-branches of the same feature-branch.
- If any feature-branches rely lightly on each other then you can use `git cherry-pick` to pick up specific commits (e.g. something small) from another branch.
- Once a staging branch is merged into master, all the branches for the features introduced in the that stage branch should be removed.
Basic Example
-------------
* feature-x * feature-y
* *
* *
* *
* *
/ /
* master
Creating a staging branch
-------------------------
`git checkout master`
`git checkout -b stage-1`
`git checkout feature-x`
`git checkout -b stage-1-feature-x`
`git rebase stage-1`
`git checkout stage-1`
`git merge stage-1-feature-x --no-ff -m "Merge branch 'feature-x' into master"`
Note: since feature-x is already on latest master, stage-1-feature-x and feature-x will be on the same commit (fast-forward)
* stage-1 - Merge branch 'feature-x' into master
| \
| * feature-x stage-1-feature-x * feature-y
| * *
| * *
| * *
| * *
/ / /
* master
Staging feature-y with feature-x
--------------------------------
`git checkout feature-y`
`git checkout -b stage-1-feature-y`
`git rebase stage-1`
`git checkout stage-1`
`git merge stage-1-feature-y --no-ff -m "Merge branch 'feature-y' into master"`
* stage-1 - Merge branch 'feature-y' into master
| \
| *' stage-1-feature-y
| *'
| *' [solved conflict here]
| *'
| *'
| /
* Merge branch 'feature-x' into master
| \
| * feature-x stage-1-feature-x * feature-y
| * *
| * *
| * *
| * *
/ / /
* master
Stage passed QA. Fastforward merge to master
--------------------------------------------
`git checkout master`
`git merge stage-1 --ff-only`
* master stage-1 - Merge branch 'feature-y' into master
| \
| *' stage-1-feature-y
| *'
| *' [solved conflict here]
| *'
| *'
| /
* Merge branch 'feature-x' into master
| \
| * feature-x stage-1-feature-x * feature-y
| * *
| * *
| * *
| * *
| / /
*
Cleanup feature branches
------------------------
`git checkout master`
`git branch -d stage-1`
`git branch -d feature-x`
`git branch -D feature-y` (feature-y is not within branch master so have to use -D. However stage-1-feature-y is in master)
`git branch -d stage-1-feature-x`
`git branch -d stage-1-feature-y`
* master - Merge branch 'feature-y' into master
| \
| *'
| *'
| *' [solved conflict here]
| *'
| *'
| /
* Merge branch 'feature-x' into master
| \
| *
| *
| *
| *
| *
| /
*
Advantages
----------
- Feature branches self-contained
- Pretty/_sane_ history
- Want to deploy feature-x before the sprint ends? create a new stage branch, rebase/merge, merge master. Feature-x already in old staging branch? recreate it! (or rebase)
Disadvantages
-------------
- Use of rebase (most people will discourage this)
- Git beginners might get confused
- If you build feature branches and want to keep that history, history will be messy (see above whilst feature-y co-existed with stage-1-feature-y)
- Pull Requests will get 'outdated diffs' messages. However PR's should only happen on a stage branch when it is ready to be merged into master or on a staged feature branch ready to be merged into a stage branch. Please don't use automatic merging! Merge it yourself with custom message.
Special circumstances
---------------------
You've got stage-1 which contains feature-y, feature-x and feature-z. However you need to deploy feature-x ASAP. You'd create stage-2 and rebase/merge feature-x within stage-2 and then fast-forward merge master.
However, feature-y and feature-z was branched off old version of master. We must rebase.
Also stage-1 is branched off old version of mater. We must rebase.
Clean way to do this (as rebase ignores merge commits) is to:
`git branch -D stage-1`
`git checkout feature-y`
`git rebase master`
`git checkout feature-z`
`git rebase master`
`git checkout master`
`git checkout -b stage-1`
`git checkout stage-1-feature-y`
`git rebase stage-1`
`git checkout stage-1`
`git merge stage-1-feature-y --no-ff`
`git checkout stage-1-feature-x`
`git rebase stage-1`
`git checkout stage-1`
`git merge stage-1-feature-x --no-ff`
Now we've got stage-1 up to date with master and all features not merged into master is up to date with master.
(Diagrams to follow in near future)
Note
----
- _Do not_ work off master branch.
- _Do not_ work off staging branches.
- _Always_ work off feature branches, not staged feature branches.
- _Always_ rebase to the branch you want to merge to (`git checkout -b stage-1-feature-x` `git rebase stage-1` `git checkout stage-1` `git merge stage-1-feature-x --no-ff`)
- _Only_ merge QA'd/authorised staging branches to master.
- _Stage branches_ can be re-created (or reset).
- Once a stage branch is merged into master then the _feature branches_ are immutable (finalized) and the original feature branches (non-rebased) should be
removed as shown above.
- Feature branches prefixed with author name should be not be touched by anyone except the author as they wish to change the history as they please.
- You should remove the history of any staging branches to keep a clean history. Such as changing the merge commit messages like the following:
"Merge branch 'feature-x' into master"
instead of
"Merge branch 'stage-n-feature-x' into 'stage-n"
- Therefore when you fast-forward merge master into stage-n it will appear that each feature was actually merged into master and the use of staging branches is hidden.
- As discussed, if you cannot fast-forward merge master into stage-n then you'd have to rebase/reset/recreate the stage-n onto latest master. This will only occur if you
create stage-1 then stage-2 then stage-2 gets merged in before stage-1 and stage-1 has to be updated.
Disclaimer
----------
- This model is untested and still not finalized.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment