We have branches prod
for production releases and dev
for ongoing development.
We work mainly in dev
branch and from time to time, customer decides which features/bugfixes he wants to come to prod
and we cherry-pick them.
From my understanding, cherry-picks contradict to git flow
model.
And so far I don't see how to adapt our flow to avoid it.git flow
assumes that you know beforehand should the change go to prod
or not
Does community see any way around it?
git fetch
git checkout origin/dev -B issue-12345 # new branch for issue #12345 from bug tracking system
# ... do many atomic commits
git fetch
git checkout origin/dev -B dev
git merge issue-12345 --no-ff -m "Bug #12345 - Bug title from bug tracking system"
# ... fix merge conflicts if any and commit
git branch -D issue-12345
git push
NOTES
Merge 'issue-12345' into 'dev'
--no-ff
because we want all issue to be represented as a merge. So git log dev --first-parent
returns high-level view of the tasks completedgit merge --squash
and its rebase analogues. We want whole task history to be preservedgit fetch
git checkout origin/prod -B issue-12345
git log origin/dev --grep "#12345" --oneline --reverse # get all commits that have to be cherry-picked, usually that's only one merge commit (abcd1234)
git cherry-pick abcd1234 -x -m 1 # '-m 1' required for cherry-picking merge commit
# ... fix merge conflicts if any and commit
# ... repeat for other commit if any
git checkout origin/prod -B prod
git merge issue-12345-prod --no-ff -m "Bug #12345 - Bug title from bug tracking system"
# ... fix merge conflicts if any and commit (although that's unlikely for them to occur)
git branch -D issue-12345
git push
git flow
told us to doSee http://nvie.com/posts/a-successful-git-branching-model/ for more details
In terms of that article our dev
branch corresponds to develop
, prod
corresponds to master
, release branches are not used
According to git flow
, only feature branches should be based on dev
branch, and they are never merged to prod
.
However hotfix branches should be based on prod
and then merged to both prod
and dev
.
git flow
is not applicable for usprod
branch or not.dev
, we won't be able to merge it to prod
later on if that will be requested (possibly much-much later)prod
, we won't be able to benefit from other tasks completed before.Let's say we have a task #12345 to implement a new Contact Us
page. And then we have a task #23456 to change the page's background color from white to yellow.
We based our issue-12345
branch from prod
and then merged it into dev
and waiting for approval to merge it into prod
.
Then we start working on issue-23456
and based on prod
again. But prod
code doesn't even have any mentions of Contact Us
page yet. So we'll have to do some quirks such as merging issue-12345
branch into issue-23456
first.
That's complicated enough for even that simple case. And you can imagine it will be much more difficult if you want to use some code introduced in other task.
Task #34567 asks to implement Feedback
page. This page is very similar to Contact Us
page so it has similar css. We would like to reuse it. But how? It's not fair to say that #34567 depends on #12345. So it would be illogical to base issue-34567
on issue-12345
. So what? Rewrite code manually? Copy-paste? Or still cherry-picks?
I don't see any reasonable solution for such issue.
git-flow (seen here translated as regular git commands) is based on merging branches (features into dev, dev into master)
git cherry-pick
is not compatible with merge because of:
So if your current workflow based on cherry-picking works, you ought to keep it.
However, as explained in "If you cherry pick, your branch model is wrong":
Their insight is that, with git (or any DAG-based SCM), if you can anticipate where a commit may/will be need to applied, you can put it on it’s own branch, and merge it into those various places as needed.
This will get the change applied to all the necessary branches (you can merge it into release as well as master), but not result in the commit getting copy/pasted. Instead, new merge commits will be recorded, so no new commit ids, and the history (what branches have this commit?) is tracked nicely in the DAG.
Yet:
The con to not cherry picking is that you’ll need to know up front that you want your commit applied into multiple places, so that you can place it on it’s own branch.
In your case, that would involve multiple separate feature branches, merged into master only after approval by the client.
Regarding git-flow, it is true it is not a good fit for you. An integration model is more accurate:
It is simpler to have an integration
branch which starts from master
and with:
integration
branchintegration
branch each time other features have been merged to integration
: that involve communicating with the team in charge of that feature branch as they will have to reset their own copy of the feature branch each time it is rebased (since its history would change)integration
, can be reverted at any time if that feature is dropped: all other feature branches not yet merged need to rebase themselves on top of the updated integration
branch.Once the integration
branch is feature complete and has passed user acceptance tests, it would be merged to master
(or prod
)
From the OP's scenario, when features can go individually into prod at any time, you don't need dev
or integration
:
Day 1.
prod
=dev
=integration
Let's consider only prod
and integration
here, and feature or issue branches.
Day 2. Issue #1 raised. Here it is obvious. All branches are the same. So we can
git checkout prod -B issue-1
Day 3. Issue #1 fixed. Do we merge
issue-1
branch anywhere?
Merge --no-ff to integration
Day 4. Issue #2 raised. Basing from integration branch again?
Here based on prod
. Especially if it is an issue (detected in prod
).
If it is a feature, you can consider starting it from integration
, but since features will be dropped from integration
, the benefit of an early integration won't be a guaranty.
Day 5. Issue #2 fixed. Merging anywhere?
To integration
(merge --no-ff
), to check if issue 2 works with issue 1.
Day 6. Issue #2 approved to get into prod. What do we do?
First, rebase issue-2
on top of prod
(in case of prod have evolved since then)
Then merge --no-ff issue-2
to prod
.
Reset integration
to prod
, and merge all the other features branches back into integration
, in order to validate if they play well together on top of the new prod (which now includes issue-2
).
Day 7. Issue #1 approved to get into prod. What do we do?
First, rebase issue-1
on top of prod
: that will validate that issue-1
is still working, even when based on top of issue-2
(which was merged into prod
previously).
Then, merge --no--ff.
Note the use of merge --no-ff
, which generates a merge commit in prod
or integration
from a feature/issue branch: if said feature/issue needs to be dropped from prod
, all you need to do is to revert that unique merge commit in prod
or integration
(instead of reverting a series of commits representing the branch to drop).
Working with cherry-pick
is a very decent way to do it.
The "problem" is that git flow merge you branches into each other (fully and then delete them as part of its flow) so using cherry-pick
along with git-flow
is some sort of abusing git flow.
In my opinion you should consider developing feature toggle mechanism for choosing which features to turn/off per customer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With