We use the feature branch workflow in our small team of developers. We're currently working on a large project, so one of the developers has pushed their feature branch to origin, where everyone else can checkout their own local copy.
[leonard@dev public]$ git branch -avv
master 9d53b40 [origin/master] Fix reviews
* responsive 0c04643 [origin/responsive] Add media queries
remotes/origin/HEAD -> origin/master
remotes/origin/master 9d53b40 Fix reviews
remotes/origin/responsive 0c04643 Add media queries
When developing on master, we create feature branches (i.e. master_hotfix), then when we're ready to merge it in we first rebase master
on to it before doing so. This gives us a nice linear history that we prefer. We thought this would be the best way to do this with our responsive project too, so we would create a new branch (i.e. responsive_some-feature) based on the responsive branch. The same git pull
, git rebase responsive responsive_some-feature
can then be used here, too.
But we're a bit confused as to whether we should (and if so, at what point) rebase master
on to responsive
? Before the responsive
branch was pushed to origin
, rebasing master
on to it was simple, but is rebasing master
to responsive
then responsive
to responsive_some-feature
correct? When I do, I see (along with a few conflicts) this:
# On branch responsive
# Your branch and 'origin/responsive' have diverged,
# and have 112 and 109 different commit(s) each, respectively.
#
nothing to commit (working directory clean)
Usually at this point I see a clean working directory, where I can then checkout master
and merge my feature branch in. Alas, after this rebase the commits from master
are in there, with the new commits in responsive
coming after them, correctly, but is this the right method? How should I proceed, or should I use a different method to keep responsive
up to date with master
?
Edit: I've made a graphic to illustrate my workflow better:
Should I rebase master onto a branch that's been pushed?
No, you should follow the general rule - never rewrite the public history
(= never rebase branch that's been pushed).
In the case of simple feature branches, you are able to rebase them (rewrite history) before the push. Or, at least, you can be sure that only one developer works with the feature branch and do forced push if you have branches have diverged
situation.
In the case of the responsive
branch, it is public and used by many developers.
So you can not rebase it on top of master, do the regular merge for this branch.
Note: as mentioned in the comments, you have a bit confusing terminology in your post. So I assume that ...we first rebase master on to it [feature branch]...
actually means the opposite and you rebase feature branches on top of master.
The "normal" (no history rewrite) flow with feature branches look like this:
1) we have a feature branch
... O ---- O ---- A ---- B master
\
C feature-branch
2) we do the merge, usually with merge commit (D)
sometimes it can be fast-forward without the merge commit
... O ---- O ---- A -- B -- D - master
\ /
-- C -- feature-branch
The flow with re-base:
1) we have a feature branch
... O ---- O ---- A ---- B master
\
C feature-branch
2) we rebase feature branch on top of master
note, that we changed the history and have new C' commit on
the feature branch
... O ---- O ---- A ---- B master
\
C' branch_xxx (feature branch)
3) we do the merge, master is fast-forwarded since there is nothing new
on master
... O ---- O ---- A -- B -- C' - master (fast forwarded)
\ /
C' feature-branch
It works good if there is only one developer who works on the feature branch. So the history rewrite is safe.
But when you add your responsive
branch in, the flow, as I understand, is this:
1) we have a feature branch
... O ---- O ---- A ---- B master
\
R1 -- R2 responsive
\
F1 responsive-feature-branch
2) now see what happens if `responsive-feature-branch` is still active (someone works on it) and we rebase the `responsive` on top of `master`:
... O ---- O ---- A ---- B master
\ \
\ R1' -- R2' responsive'
\
R1 -- R2 responsive
\
F1 responsive-feature-branch
Do you see the problem? Now you have two responsive
branches which are diverged (see also explanation in my post).
You can push the rebased responsive'
using '-f' (force) flag, but what will the developer who works on the responsive-feature-branch
do? He'll just have the new upstream history and will have to rewrite his-own local history accordingly.
You can do this forced update if you are sure that nobody have active branches derived from responsive
and everyone will need then update their local repos.
But I don't recommend this, because you can't guarantee that there are no active sub-branches and someday you'll definitely find that your repository has messed up. I think that pretty linear history not worth the time you'll need to spend on resolving these issues.