I've searched the web for best practices around software release process with Git. It seems that the practices vary a lot. One of the best articles I have come across is this one (I had to Flattr that post):
http://nvie.com/posts/a-successful-git-branching-model/
The process there is quite complex and sophisticated. I imagine it is required and very beneficial for large-scale projects. In our case (just several developers) I believe we are better off with much simpler process. But it's still a great source of inspiration.
In the release process there are some artifacts we recently talked about and which could be important for us:
== A single stable branch ==
This is the branch containing only stable (production-ready) code. In AutoQA we call in "stable". In the aforementioned article they call it "master". There's a small difference in the process of adding hotfixes. We used the same branch for pushing hotfixes and then tagged a new hotfix release at some point. They have a separate "hotfix" branch for those purposes and merge in once they want to create a hotfix release. But otherwise it's the same.
The benefits of having such a branch: * People following this branch don't have to track release announcements or periodically list available tags. Simple "git pull" will always give them latest stable code.
The drawbacks of having such a branch: * It is not trivial to maintain this branch with full commit history. My simple approach for AutoQA 0.5.0 was to create a patch from stable to v0.5.0 and apply it on stable [1]. But that does not keep history. The history is retained if you run "git log v0.5.0", but not if you run "git log stable". Tim tried to fix that problem by merging v0.5.0 and stable [2]. But that has its own drawbacks. You need to solve merge conflicts by hand and even if you do that, it is still possible that stable differs from v0.5.0 (some code changes didn't need to be detected as conflicts). With Tim's approach you still need to diff your branches afterwards and resolve any remaining differences by my diff-n-patch approach. It looks better in the end, but it also requires more work. Interestingly the guy in that article didn't mention this problem at all (although they must have encountered this problem too).
All in all, stable branch has its uses and its challenges. We don't even need it, there are other approaches (described below). It's just a matter what we desire. Do you think there are people out there following just our stable branch? Do we care if they have to switch tags from time to time?
== Release branches ==
The principle is simple. With each tagged (minor) release we fork off a separate branch out of it. For example for 0.5.0 release we create "0.5-stable" branch. For 0.6.0 release we create "0.6-stable" branch. The rest of the process is the same as we have used till now. All hotfix commits are pushed to the relevant release branch and then tagged in some point of time. It then looks like this:
-o--o--o--o--o--o-- (master) ^\ | o--o--o- (0.5-stable) | ^ | tag:0.5.1 tag:0.5.0
In this picture we have tagged 0.5.0 on master, then forked off 0.5-stable branch, pushed three more commits into that branch and then tagged 0.5.1 release.
Advantages: * There are no issues with merging. We can work on more releases at once (not relevant to our project imho).
Disadvantages: * Having the latest stable code requires checking the tags periodically and switching to the latest one.
Maybe you wonder - will we have lots and lots of these branches, eventually exploding the output of "git branch -r"? No. The nice thing here is that we need to create this release branch only when it's needed (we discover a bug that needs a hotfix). Also we can delete these branches once we are sure we won't work on this branch anymore (i.e. once 0.6.0 is out we can delete 0.5-stable in our case). Because don't forget, both branches and tags are the same in Git -- pointers. Branches are just moving pointers, while tag pointers stay put. Once we know there will be no more development, the tag is all we need to keep, the branch can be removed.
I consider this approach quite nice. In the past I was too concentrated on having a stable branch where you can always "git pull" the latest stable code. But maybe we don't need it after all and release branches would satisfy our needs instead? (We can of course have both stable branch and release branches, but I consider that unnecessarily complicated.)
== Branches used for tagging ==
There was a discussion lately on which branch we should tag our releases. I would like to clarify that. Due to the Git's nature this question does not really apply. In the above text I already described that branches and tags are almost the same -- pointers. The branch determines just the top commit and all other commits are linked through ancestor relationship. So you can't say "this commit is on branch X", you can just say "this commit is accessible from branches X, Y and Z". There is no ownership relationship. That means it doesn't really matter which branch the particular commit used to belong, it only matters if that is the top of the tree we want to archive by tagging. The important questions are then: * Does it contain the code we want? * Does it refer the commit tree log we want?
It means that these approaches are equivalent: (master)$ git tag 0.5.0 and (master)$ git checkout -b 0.5-stable (0.5-stable)$ git tag 0.5.0 Both contain the same code and both refer to the same tree.
However, if we do big-patch approach for our stable branch (like I did a few days ago), those approaches are not interchangeable:
tag:0.4.0 tag:0.5.0 v v --o--o--o--o--o--o--o-- (master) \ \ o---o----------o--- (stable) ^ tag:0.4.1
If I do "git log 0.5.0", I get a fine-grained list of commit history. Now imagine I would tag a different commit:
tag:0.4.0 v --o--o--o--o--o--o--o-- (master) \ \ o---o----------o--- (stable) ^ ^ tag:0.4.1 tag:0.5.0
Now I get the same code for "git checkout 0.5.0", but I get only a fraction of commit history for "git log 0.5.0". Not that it doesn't serve the purpose. But the first approach is just better, because it keeps also the history.
== Conclusion ==
I have described the current approaches. I may have misunderstood something, I'll welcome corrections.
As for our project, I'm open to any suggestions. I think that our current practice serves us well. I'm fine with the big-patch approach for stable branch, because the commit history is retained for master branch and for all the tags. I'm fine with Tim's merging approach too.
OTOH I'm also fine with switching to using release branches. They are pretty. And it may be simpler for understanding that our current approach.
I don't think it would be viable for us to do both, release branches and stable branch. KISS.
Once we decide what we want, I'll document the process on our wiki.
Keep the comments coming :)
Kamil
[1] http://piratepad.net/M9RUj1qAe2 [2] https://fedorahosted.org/pipermail/autoqa-devel/2011-June/002475.html
Wow, this is impressive - you spent some time compiling this :)
Thanks for typing it all up.
Tim
On 07/01/2011 09:31 AM, Kamil Paral wrote:
I've searched the web for best practices around software release process with Git. It seems that the practices vary a lot. One of the best articles I have come across is this one (I had to Flattr that post):
Wow, that's a lot of detail. Nice find.
The process there is quite complex and sophisticated. I imagine it is required and very beneficial for large-scale projects. In our case (just several developers) I believe we are better off with much simpler process. But it's still a great source of inspiration.
In the release process there are some artifacts we recently talked about and which could be important for us:
== A single stable branch ==
This is the branch containing only stable (production-ready) code. In AutoQA we call in "stable". In the aforementioned article they call it "master". There's a small difference in the process of adding hotfixes. We used the same branch for pushing hotfixes and then tagged a new hotfix release at some point. They have a separate "hotfix" branch for those purposes and merge in once they want to create a hotfix release. But otherwise it's the same.
The benefits of having such a branch: * People following this branch don't have to track release announcements or periodically list available tags. Simple "git pull" will always give them latest stable code.
How many people are following AutoQA stable right now with their own installations? If people are following the stable branch, I imagine that they would prefer to decide when to upgrade on their own instead of whenever we update stable but I could be wrong on that one.
The drawbacks of having such a branch: * It is not trivial to maintain this branch with full commit history. My simple approach for AutoQA 0.5.0 was to create a patch from stable to v0.5.0 and apply it on stable [1]. But that does not keep history. The history is retained if you run "git log v0.5.0", but not if you run "git log stable". Tim tried to fix that problem by merging v0.5.0 and stable [2]. But that has its own drawbacks. You need to solve merge conflicts by hand and even if you do that, it is still possible that stable differs from v0.5.0 (some code changes didn't need to be detected as conflicts). With Tim's approach you still need to diff your branches afterwards and resolve any remaining differences by my diff-n-patch approach. It looks better in the end, but it also requires more work. Interestingly the guy in that article didn't mention this problem at all (although they must have encountered this problem too).
I think that it's less of a problem with the vim plugin I found but there may be other approaches, too. Either way, you're right that there is a potential for conflicts and mistakes - probably not the ideal thing to do.
All in all, stable branch has its uses and its challenges. We don't even need it, there are other approaches (described below). It's just a matter what we desire. Do you think there are people out there following just our stable branch? Do we care if they have to switch tags from time to time?
I wonder if the question might be better phrased as: are there people out there who want the AutoQA releases and don't just take the rpms from the autoqa fedorapeople repo?
If someone is frustrated about having to switch tags/branches, I imagine that they would also be frustrated about having to build their own RPM or install AutoQA on all involved machines.
== Release branches ==
The principle is simple. With each tagged (minor) release we fork off a separate branch out of it. For example for 0.5.0 release we create "0.5-stable" branch. For 0.6.0 release we create "0.6-stable" branch. The rest of the process is the same as we have used till now. All hotfix commits are pushed to the relevant release branch and then tagged in some point of time. It then looks like this:
This sounds a lot cleaner and easier to me. +1
== Branches used for tagging ==
There was a discussion lately on which branch we should tag our releases. I would like to clarify that. Due to the Git's nature this question does not really apply. In the above text I already described that branches and tags are almost the same -- pointers. The branch determines just the top commit and all other commits are linked through ancestor relationship. So you can't say "this commit is on branch X", you can just say "this commit is accessible from branches X, Y and Z". There is no ownership relationship. That means it doesn't really matter which branch the particular commit used to belong, it only matters if that is the top of the tree we want to archive by tagging. The important questions are then: * Does it contain the code we want? * Does it refer the commit tree log we want?
I guess that I'd vote for tagging after branching here. My rationale for that is that the versions would look the same after the X.0 release. I do think that the later X.Y releases should be tagged on their respective branch, though.
--o--o--o--o--o--o--o-- (master) \ \ <cherry pick> o--------------o--- (0.5 branch) ^ ^ tag:0.5.0 tag:0.5.1
Then again, I don't have any really strong opinions on this so I could go either way on it. A ref is a ref is a ref. Like you said, the important thing is that we get the code we're looking for and hopefully the right commit log, too.
== Conclusion ==
I have described the current approaches. I may have misunderstood something, I'll welcome corrections.
As for our project, I'm open to any suggestions. I think that our current practice serves us well. I'm fine with the big-patch approach for stable branch, because the commit history is retained for master branch and for all the tags. I'm fine with Tim's merging approach too.
OTOH I'm also fine with switching to using release branches. They are pretty. And it may be simpler for understanding that our current approach.
I think this is cleaner and easier than merging but still preserves the commit history. This gets my vote going forward.
I don't think it would be viable for us to do both, release branches and stable branch. KISS.
So you're saying that I should hold off on a proposal for emailing all patches and requiring sign-off by 2 other people before pushing to master?
BTW, I'm not serious about that proposal.
On Fri, 2011-07-01 at 18:03 -0600, Tim Flink wrote:
Wow, this is impressive - you spent some time compiling this :)
Thanks for typing it all up.
+1 ... thanks for spending some time on this, Kamil :)
On 07/01/2011 09:31 AM, Kamil Paral wrote:
I've searched the web for best practices around software release process with Git. It seems that the practices vary a lot. One of the best articles I have come across is this one (I had to Flattr that post):
Wow, that's a lot of detail. Nice find.
The process there is quite complex and sophisticated. I imagine it is required and very beneficial for large-scale projects. In our case (just several developers) I believe we are better off with much simpler process. But it's still a great source of inspiration.
In the release process there are some artifacts we recently talked about and which could be important for us:
== A single stable branch ==
This is the branch containing only stable (production-ready) code. In AutoQA we call in "stable". In the aforementioned article they call it "master". There's a small difference in the process of adding hotfixes. We used the same branch for pushing hotfixes and then tagged a new hotfix release at some point. They have a separate "hotfix" branch for those purposes and merge in once they want to create a hotfix release. But otherwise it's the same.
The benefits of having such a branch: * People following this branch don't have to track release announcements or periodically list available tags. Simple "git pull" will always give them latest stable code.
How many people are following AutoQA stable right now with their own installations? If people are following the stable branch, I imagine that they would prefer to decide when to upgrade on their own instead of whenever we update stable but I could be wrong on that one.
The drawbacks of having such a branch: * It is not trivial to maintain this branch with full commit history. My simple approach for AutoQA 0.5.0 was to create a patch from stable to v0.5.0 and apply it on stable [1]. But that does not keep history. The history is retained if you run "git log v0.5.0", but not if you run "git log stable". Tim tried to fix that problem by merging v0.5.0 and stable [2]. But that has its own drawbacks. You need to solve merge conflicts by hand and even if you do that, it is still possible that stable differs from v0.5.0 (some code changes didn't need to be detected as conflicts). With Tim's approach you still need to diff your branches afterwards and resolve any remaining differences by my diff-n-patch approach. It looks better in the end, but it also requires more work. Interestingly the guy in that article didn't mention this problem at all (although they must have encountered this problem too).
I think that it's less of a problem with the vim plugin I found but there may be other approaches, too. Either way, you're right that there is a potential for conflicts and mistakes - probably not the ideal thing to do.
All in all, stable branch has its uses and its challenges. We don't even need it, there are other approaches (described below). It's just a matter what we desire. Do you think there are people out there following just our stable branch? Do we care if they have to switch tags from time to time?
I wonder if the question might be better phrased as: are there people out there who want the AutoQA releases and don't just take the rpms from the autoqa fedorapeople repo?
If someone is frustrated about having to switch tags/branches, I imagine that they would also be frustrated about having to build their own RPM or install AutoQA on all involved machines.
== Release branches ==
The principle is simple. With each tagged (minor) release we fork off a separate branch out of it. For example for 0.5.0 release we create "0.5-stable" branch. For 0.6.0 release we create "0.6-stable" branch. The rest of the process is the same as we have used till now. All hotfix commits are pushed to the relevant release branch and then tagged in some point of time. It then looks like this:
This sounds a lot cleaner and easier to me. +1
== Branches used for tagging ==
There was a discussion lately on which branch we should tag our releases. I would like to clarify that. Due to the Git's nature this question does not really apply. In the above text I already described that branches and tags are almost the same -- pointers. The branch determines just the top commit and all other commits are linked through ancestor relationship. So you can't say "this commit is on branch X", you can just say "this commit is accessible from branches X, Y and Z". There is no ownership relationship. That means it doesn't really matter which branch the particular commit used to belong, it only matters if that is the top of the tree we want to archive by tagging. The important questions are then: * Does it contain the code we want? * Does it refer the commit tree log we want?
I guess that I'd vote for tagging after branching here. My rationale for that is that the versions would look the same after the X.0 release. I do think that the later X.Y releases should be tagged on their respective branch, though.
--o--o--o--o--o--o--o-- (master) \ \ <cherry pick> o--------------o--- (0.5 branch) ^ ^ tag:0.5.0 tag:0.5.1
Then again, I don't have any really strong opinions on this so I could go either way on it. A ref is a ref is a ref. Like you said, the important thing is that we get the code we're looking for and hopefully the right commit log, too.
== Conclusion ==
I have described the current approaches. I may have misunderstood something, I'll welcome corrections.
As for our project, I'm open to any suggestions. I think that our current practice serves us well. I'm fine with the big-patch approach for stable branch, because the commit history is retained for master branch and for all the tags. I'm fine with Tim's merging approach too.
OTOH I'm also fine with switching to using release branches. They are pretty. And it may be simpler for understanding that our current approach.
I think this is cleaner and easier than merging but still preserves the commit history. This gets my vote going forward.
I'm more accustomed to this approach, so this would get my vote. Of course, I still have a lot more reading to do from the link provided above.
The terms "stable" and "git development" always seemed like contradictions to me. If someone wants to follow autoqa stable ... install the packages, or grab the latest stable tarball. Maintaining a "stable" git branch seems like a fair amount of work/history_munging for little reward.
Aside ... with the tag+branch approach, this lends a bit better to Makefile assistance as there are plenty of other projects that use this approach. We can document the release process in terms of a few makefile targets (e.g. 'make newrelease') to ensure the process is done correctly each time. I can follow-up on that if we choose this option.
Thanks, James
OTOH I'm also fine with switching to using release branches. They are pretty. And it may be simpler for understanding that our current approach.
I think this is cleaner and easier than merging but still preserves the commit history. This gets my vote going forward.
I'm more accustomed to this approach, so this would get my vote.
It is decided then. I created a first shot at the documentation at:
https://fedoraproject.org/wiki/User:Kparal/Sandbox:Git_release_process
If you don't have any concerns, I'll merge it into the final release documentation page [1].
On Thu, 2011-07-07 at 09:51 -0400, Kamil Paral wrote:
OTOH I'm also fine with switching to using release branches. They are pretty. And it may be simpler for understanding that our current approach.
I think this is cleaner and easier than merging but still preserves the commit history. This gets my vote going forward.
I'm more accustomed to this approach, so this would get my vote.
It is decided then. I created a first shot at the documentation at:
https://fedoraproject.org/wiki/User:Kparal/Sandbox:Git_release_process
If you don't have any concerns, I'll merge it into the final release documentation page [1].
Nice ... I'll absorb your draft and offer any feedback shortly.
I'd like to see the entire process handled by make targets to avoid inconsistent branch and tag names. I'm thinking things like ... 'make newversion' and 'make tag' etc... I'll experiment with that once the document is finalized.
Thanks, James
On Thu, 2011-07-07 at 10:10 -0400, James Laska wrote:
On Thu, 2011-07-07 at 09:51 -0400, Kamil Paral wrote:
OTOH I'm also fine with switching to using release branches. They are pretty. And it may be simpler for understanding that our current approach.
I think this is cleaner and easier than merging but still preserves the commit history. This gets my vote going forward.
I'm more accustomed to this approach, so this would get my vote.
It is decided then. I created a first shot at the documentation at:
https://fedoraproject.org/wiki/User:Kparal/Sandbox:Git_release_process
If you don't have any concerns, I'll merge it into the final release documentation page [1].
Nice ... I'll absorb your draft and offer any feedback shortly.
I'd like to see the entire process handled by make targets to avoid inconsistent branch and tag names. I'm thinking things like ... 'make newversion' and 'make tag' etc... I'll experiment with that once the document is finalized.
Maybe a dumb question ... the document explains the X.Y.Z (major, minor, revision) versioning scheme. Right now, it only lists how to increment minor# and revision#. Is there need for a major# at this time? Should we collapse X.Y.Z into just X.Y?
Thanks, James
On Thu, 07 Jul 2011 14:14:46 -0400 James Laska jlaska@redhat.com wrote:
I'd like to see the entire process handled by make targets to avoid inconsistent branch and tag names. I'm thinking things like ... 'make newversion' and 'make tag' etc... I'll experiment with that once the document is finalized.
Maybe a dumb question ... the document explains the X.Y.Z (major, minor, revision) versioning scheme. Right now, it only lists how to increment minor# and revision#. Is there need for a major# at this time? Should we collapse X.Y.Z into just X.Y?
I know that I'm not all that worried about what numbers we use for a versioning scheme and I'm pretty sure Kamil has said almost the same thing - as long as we're pretty consistent and the scheme makes sense, it doesn't matter a whole lot what the numbering scheme actually is.
I imagine that the X was set to 0 in the docs out of convenience and habit but I'm fine with either 0.X.Y or dropping the 0 and moving to X.Y.
Either way, it might not be a bad idea to update the docs to not specify 0 as the major or drop the major version number entirely.
Tim
Maybe a dumb question ... the document explains the X.Y.Z (major, minor, revision) versioning scheme. Right now, it only lists how to increment minor# and revision#. Is there need for a major# at this time?
I didn't document it because I suppose we won't need it for a long time :) Essentially the process for incrementing major number is the same as for minor number (we will create a new branch 'release-1.0', 'release-2.0', etc). I can amend the documentation if you want.
Should we collapse X.Y.Z into just X.Y?
I like to use simpler versioning schemes for end-user applications. Pidgin 1, Pidgin 2, Pidgin 3, Pidgin 3.1 (bugfix) would work for me. OTOH for libraries and frameworks I think it's good to provide hints of breaking compatibility. My idea for AutoQA would be:
1. incrementing major number for API changes (when all users have to re-write their custom tests; of course we don't support that yet) 2. incrementing minor number for any feature additions 3. incrementing revision number for bugfix releases (no new features)
I have added all the information into
https://fedoraproject.org/wiki/AutoQA_Release_Process
I have re-worked it quite a bit and included some information that may not reflect team opinions (like the versioning principles). Feel free to comment, it's a work in progress.
Also if no-one objects, I'll delete our origin/stable branch and create origin/release-0.5 release branch instead (for future hotfixes of AutoQA 0.5).
Kamil
On Mon, 2011-07-11 at 08:55 -0400, Kamil Paral wrote:
I have added all the information into
https://fedoraproject.org/wiki/AutoQA_Release_Process
I have re-worked it quite a bit and included some information that may not reflect team opinions (like the versioning principles). Feel free to comment, it's a work in progress.
The example (https://fedoraproject.org/wiki/AutoQA_Release_Process#Major_or_minor_release...) uses the 'minor' update example (so do most examples in the document). Using your X.Y.Z format, should the examples be using '0.Y.0' instead of '0.X.0'? </nit>
The {{admon/info}} section talks about using a branch named 'branch-X.0', should that be 'release-X.0' following the branch name format used elsewhere?
The section names 'Intermediary tasks' and 'Closing tasks' don't resonate well with me. Perhaps...
* 'Intermediary tasks' -> Seems this is no longer needed with your additions to the document. Perhaps we can move the content to where you reference them earlier. * Closing tasks -> perhaps rename to 'Release'
Also if no-one objects, I'll delete our origin/stable branch and create origin/release-0.5 release branch instead (for future hotfixes of AutoQA 0.5).
Thanks Kamil. I'll hold off on packaging any of the hot-fixes until that is completed.
Thanks, James
On Mon, 2011-07-11 at 08:55 -0400, Kamil Paral wrote:
I have added all the information into
https://fedoraproject.org/wiki/AutoQA_Release_Process
I have re-worked it quite a bit and included some information that may not reflect team opinions (like the versioning principles). Feel free to comment, it's a work in progress.
The example (https://fedoraproject.org/wiki/AutoQA_Release_Process#Major_or_minor_release...) uses the 'minor' update example (so do most examples in the document). Using your X.Y.Z format, should the examples be using '0.Y.0' instead of '0.X.0'? </nit>
I didn't consider the format description at all. But you're right, it makes more sense to have it consistent with it. Fixed.
The {{admon/info}} section talks about using a branch named 'branch-X.0', should that be 'release-X.0' following the branch name format used elsewhere?
Thanks for spotting that.
The section names 'Intermediary tasks' and 'Closing tasks' don't resonate well with me. Perhaps...
- 'Intermediary tasks' -> Seems this is no longer needed with your
additions to the document. Perhaps we can move the content to where you reference them earlier.
I'm referencing them from two different locations ("Major or minor releases" and "Revision releases"). I suppose there will be more tasks in the future (like updating the ChangeLog file, once we have it) and I didn't want to duplicate all instructions twice. I'm not sure how to format the document to have it readable, but not duplicating.
Help appreciated.
- Closing tasks -> perhaps rename to 'Release'
Renamed.
On 07/11/2011 08:41 AM, Kamil Paral wrote:
The section names 'Intermediary tasks' and 'Closing tasks' don't resonate well with me. Perhaps...
- 'Intermediary tasks' -> Seems this is no longer needed with your
additions to the document. Perhaps we can move the content to where you reference them earlier.
I'm referencing them from two different locations ("Major or minor releases" and "Revision releases"). I suppose there will be more tasks in the future (like updating the ChangeLog file, once we have it) and I didn't want to duplicate all instructions twice. I'm not sure how to format the document to have it readable, but not duplicating.
Help appreciated.
What about keeping the structure as is and renaming the 'Intermediary Tasks' section to be something a bit more descriptive like 'Code Change Tasks'?
It would match better with the 'Release Tasks' section name that way.
Tim
What about keeping the structure as is and renaming the 'Intermediary Tasks' section to be something a bit more descriptive like 'Code Change Tasks'?
It would match better with the 'Release Tasks' section name that way.
Thanks, I renamed it. But then I re-worked the structure again into a single workflow line. I think it's just perfect now. Thanks for forcing me to do that, I like it much better now. :-)
What do you think?
Also if no-one objects, I'll delete our origin/stable branch and create origin/release-0.5 release branch instead (for future hotfixes of AutoQA 0.5).
I've done it as described above. This is the current state:
Release-0.5 branch now contains one commit, which is the hotfix for bodhi comments. We should tag it as 0.5.1 soon if we don't discover the need for further bugfixes.
autoqa-devel@lists.fedorahosted.org