Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
How often should I commit changes to source control ? After every small feature, or only for large features ?
I'm working on a project and have a long-term feature to implement. Currently, I'm committing after every chunk of work, i.e. every sub-feature implemented and bug fixed. I even commit after I've added a new chunk of tests for some feature after discovering a bug.
However, I'm concerned about this pattern. In a productive day of work I might make 10 commits. Given that I'm using Subversion, these commits affect the whole repository, so I wonder if it indeed is a good practice to make so many ?
Anytime I complete a "full thought" of code that compiles and runs I check-in. This usually ends up being anywhere between 15-60 minutes. Sometimes it could be longer, but I always try to checkin if I have a lot of code changes that I wouldn't want to rewrite in case of failure. I also usually make sure my code compiles and I check-in at the end of the work day before I go home.
I wouldn't worry about making "too many" commits/check-ins. It really sucks when you have to rewrite something, and it's nice to be able to rollback in small increments just in case.
When you say you are concerned that your "commits affect the whole repository" --- are you referring to the fact that the whole repository's revision number increases? I don't know how many bits Subversion uses to store it, but I'm pretty sure you're not going to run out of revision numbers! Many commits are not a problem. You can commit ten times as often as the guy next door and you won't increase your carbon footprint at all.
A single function or method should be named for what it does, and if the name is too long, it is doing too much. I try to apply the same rule to check-ins: the check-in comment should describe exactly what the change accomplishes, and if the comment is too long, I'm probably changing too much at once.
I like this small article from Jeff Atwood: Check In Early, Check In Often
I personally commit every logical group of code that is finished/stable/compiles and try not to leave the day without committing what I did that day.
If you are making major changes and are concerned about affecting others working on the code, you can create a new branch, and then merge back into the trunk after your changes are complete.
If your version control comment is longer than one or two sentences, you probably aren't committing often enough.
I follow the open-source mantra (paraphrased) - commit early, commit often.
Basically whenever I think I've added useful functionality (however small) without introducing problems for other team members.
This commit-often strategy is particularly useful in continuous integration environments as it allows integration testing against other development efforts, giving early detection of problems.
I commit everytime I'm done with a task. That usually takes 30 mins to 1 hr.
Don't commit code that doesn't actually work. Don't use your repository as a backup solution.
Instead, back up your incomplete code locally in an automated way. Time Machine takes care of me, and there are plenty of free programs for other platforms.
The rule of thumb, that I use, is check-in when the group of files being checked-in can be covered by a single check-in comment.
This is generally to ensure that check-ins are atomic and that the comments can be easily digested by other developers.
It is especially true when your changes affect a configuration file (such as a spring context file or a struts config file) that has application wide scope. If you make several 'groups' of changes before checking in, their impact overlaps in the configuration file, causing the 2 groups to become merged with each other.
I don't think you should worry so much about how often. The important thing here is what, when and why. Saying that you have to commit every 3 hours or every 24 hours really makes no sense. Commit when you have something to commit, don't if you don't.
Here's an extract from my recommended best practices for version control:
[...] If you are doing many changes to a project at the same time, split them up into logical parts and commit them in multiple sessions. This makes it much easier to track the history of individual changes, which will save you a lot of time when trying to find and fix bugs later on. For example, if you are implementing feature A, B and C and fixing bug 1, 2 and 3, that should result in a total of at least six commits, one for each feature and one for each bug. If you are working on a big feature or doing extensive refactoring, consider splitting your work up into even smaller parts, and make a commit after each part is completed. Also, when implementing independent changes to multiple logical modules, commit changes to each module separately, even if they are part of a bigger change.
Ideally, you should never leave your office with uncommitted changes on your hard drive. If you are working on projects where changes will affect other people, consider using a branch to implement your changes and merge them back into the trunk when you are done. When committing changes to libraries or projects that other projects—and thus, other people—depend on, make sure you don’t break their builds by committing code that won’t compile. However, having code that doesn’t compile is not an excuse to avoid committing. Use branches instead. [...]
Your current pattern makes sense. Keep in mind how you use this source control: what if you have to rollback, or if you want to do a diff? The chunks you describe seem like exactly the right differential in those cases: the diff will show you exactly what changed in implementing bug #(specified in checkin log), or exactly what the new code was for implementing a feature. The rollback, similarly, will only touch one thing at a time.
I also like to commit after I finish a chunk of work, which is often several times a day. I think it's easier to see what's happening in small commits than big ones. If you're worried about too many commits, you may consider creating a branch and merging it back to the trunk when the whole feature is finished.
Here's a related blog post: Coding Horror: Check In Early, Check In Often
As others have stated, try to commit one logical chunk that is "complete" enough that it does not get in other devs' way (e.g., it builds and passes automated tests).
Each dev team / company must define what is "complete enough" for each branch. For example, you may have feature branches that require the code only to build, a Trunk that also requires code to pass automated tests, and labels indicating something has passed QA testing... or something like that.
I'm not saying that this is a good pattern to follow; I'm only pointing out that how done is "done" depends on your team's / company's policies.
I also like to check in regularly. That is every time I have a completed a step towards my goal.
This is typically every couple of hours.
My difficulty is finding someone willing and able to perform so many code reviews.
Our company policy is that we need to have a code review before we can check anything in, which makes sense, but there is not always someone in the department who has time to immediately perform a code review. Possible Solutions:
More work per check in; less checkins == less reviews.
Change the company checkin policy. If I have just done some refactoring and the unit tests all run green, maybe I can relax the rule?
Shelve the change until someone can perform the review and continue working. This can be problematic if the reviewer does not like you code and you have to redesign. Juggling different stages of a task by 'shelving' changes can become messy.
The moment you think about it.
(as long as what you check in is safe)
Depends on your source code system and what else you have in place. If you're using Git, then commit whenever you finish a step. I use SVN and I like to commit when I finish a whole feature, so, every one to five hours. If I were using CVS I'd do the same.
I agree with several of the responses: do not check in code that will not compile; use a personal branch or repository if your concern is having a "backup" of the code or its changes; check in when logical units are complete.
One other thing that I would add is that depending on your environment, the check-in rate may vary with time. For example, early in a project checking in after each functional piece of a component is complete makes sense for both safety and having a revision history (I am thinking of cases where earlier bits get refactored as later ones are being developed). Later in the project, on the other hand, entirely complete functionality becomes more important, especially during integration development/testing. A half-integration or half-fix does not help anyone.
As for checking in after each bug fix: unless the fix is trivial, absolutely! Nothing is more of a pain than finding that one check in contained three fixes and one of them needs to be rolled back. More often than not it seems that in that situation the developer fixed three bugs in one area and unwinding which change goes to which bug fix is a nightmare.
I like to commit changes every 30-60 minutes, as long as it compiles cleanly and there are no regressions in unit tests.
Well, you could have your own branch to which you can commit as often as you like, and when you are done with your feature, you could merge it to the main trunk.
On the frequency of Commits, I think of it this way, how much pain would it be to me if my hard disk crashed and I hadn't committed something - the quantum of this something for me is about 2 hours of work.
Of course, I never commit something that doesn't compile.
At least once a day.
I don't have a specific time limit per commit, I tend to commit once a test has passed and I'm happy with the code. I wouldn;t commit code that does not compile or is otherwise in a state that I would not feel good about reverting to in case of failure
You have to balance the compromise between safety and recoverability on the one hand and ease of change management for the entire project on the other.
The best scheme that I've used has had two answers to that question.
We used 2 completely separate repositories : one was the project wide repository and the other was our own personal repository (we were using rcs at the time).
We would check into our personal repository very regularly, pretty much each time you saved your open files. As such the personal repository was basically a big, long ranging, undo buffer.
Once we had a chunk of code that would compile, tested ok and was accepted as being ready for general use it was checked into the project repository.
Unfortunately this system relied on the use of different VCS technologies to be workable. I've not found any satisfactory method of achieving the same results while using two of VCS of the same type (eg. two subversion repositories)
However, I have had acceptable results by creating "personal" development branches in a subversion repository - checking into the branch regularly and then merging into the trunk upon completion.
If you're working on a branch which won't be released, a commit is always safe.
However, if you are sharing it with other developers, committing non-working code is likely to be a bit annoying (particularly if it's in an important place). Normally I only commit code which is effectively "working" - not that it's been fully tested, but that I've ascertained that it does actually compile and not fail immediately.
If you're using an integrated bug tracker, it may be helpful to do separate commits if you've fixed two bugs, so that the commit log can go against the right bugs. But then again, sometimes one code change fixes two bugs, so then you just have to choose which one to put it against (unless your system allows one commit to be associated with multiple bugs)
I still believe in the phrase 'commit often, commit early'. I prefer decentralized VCS like Mercurial and there's no problem to commit several things and push it upstream later.
This is really a common question, but the real question is: Can you commit unfinished code?
Whenever you finish some code that works and won't screw anyone else up if they get it in an update.
And please make sure you comment properly.
Related
I just made the move to version control the other day, and after a bad experience with Subversion, I switched to Mercurial, and so far am happy with it.
Although I understand and appreciate the idea of version control, I don't really have any practical experience with it.
Right now, I am using it for a couple websites I am working on, and a couple questions have come to mind:
When/how often should I commit? After any major change, whether it works or not? When I'm done for the night? Only when it reaches it's next stable iteration? After any bugfixes?
Would I branch off when I wanted to, say, change the layout of a menu, then merge back in?
Should I branch? What is the difference (for just me, a lone developer) between branching, then merging back in, and cloning the repository and pulling it back in?
Any other advice for a version control newbie?
So far, everyone has given me good advice, but very team-oriented. I would like to clarify:
At the moment, I am just using VC on some websites I do on the side. Not quite full-out freelance work, but for the purposes of VC, I am the only one that really touches the website code.
Also, since I am using PHP on the sites, there is no compiling to be done.
Does this change your answers significantly?
Most of the questions you're asking about depends mostly on who you are working with. If you're a lone developer it shouldn't matter a lot, since you can do whatever you'd like. But if you're in a team where you have to share your code then you should discuss with your team members what the code of conduct should be since sharing changes between one another can become tricky at times.
The discussion regarding code of conduct doesn't need to be lengthy, it can be very brief; as long everyone is on the same page on how to use the repository that is shared between the programmers in the team. If you want to use the more advanced features in Mercurial, such as cherry picking or patch queues, then try using them so that it won't impact your team members in a negative way, such as rebasing on a public repository.
Remember version control has to be easy to use for everyone in the team, or else it won't be used.
When/how often should I commit? After any major change, whether it works or not? When I'm done for the night? Only when it reaches it's next stable iteration? After any bugfixes?
While working with a team there are several approaches, but the common rule is to commit early and often. The main reason on why you should commit often is to make merge conflicts easier to handle.
A merge conflict is simply put whenever merging a file that has been changed by at least two people doesn't work because they've been editing on the same lines. If you're holding on to a commit that involves a very large change with several lines of changes across several files, it will become very difficult to manage for the receiver to manage the conflicts that may occur. The merge conflict becomes even more difficult to handle if the said set of changes are held on for too long.
There are some exceptions to the rule of committing often and one is whenever you have a breaking change. although if you have the ability to commit locally (which you are doing in Mercurial and git inherently) you could commit breaking changes. As long as you fix whatever broke, you should push it upstream to the shared repository when you've fixed your own breaking change.
Would I branch off when I wanted to, say, change the layout of a menu, then merge back in?
Should I branch?
There are many branching strategies to choose from (there is the Streamed Lines paper from 1998 that has an exhaustive pattern list of branching strategies) and when you're making them for yourself it should be open game for yourself. However when working in teams, you'd better discuss openly with the team if you need to branch or not. Whenever you have the urge to branch though you should ask yourself the following questions:
Will my future changes be breaking the work of others?
Will my team have a direct negative impact from the changes I'll be doing until I'm done?
Is my code throwaway code?
If the answer is yes in any of the questions above you should probably branch publically, or keep it for yourself (since you can do that in Mercurial in several ways). You should first discuss with your team on how to execute the whole endavour to see if there is any other way of doing it and if you're going to merge your changes back in, sometimes there are factors at play where there is no need to branch (this is mostly related to how modular the code is).
When you decide to branch be prepared to handle a merge conflict. It is sane to assume the one who created the branch and made the commits to be able to merge it back into the "main branch". At these times it would be great if everyone in the team made relevant commit comments.
As a side note: You do write good commit comments, right? RIGHT!? A good commit comment usually tells why that particular change was made or what feature the committer was working on instead of a nondescript "I made a commit" kind of comment. This makes it easier for the one who is handling the big merge conflict to figure out what line changes can be overwritten and which ones to keep while going through the revision history.
Compile times, or build times rather, sometimes play into the branch discussion you may have. If your project has a slow build time then it might be a good idea to use a staging strategy in your branches. This strategy takes into account that all developers should integrate to a "main line" and changes that are approved are elevated (or "promoted") to the next stage, such as testing or release lines. It is classically illustrated with tag names for open source software like this:
main -o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-> ...
\ \ \
test o-----------o--------------o---------> ...
1.0 RC1 \ 1.0 RC2 2.0 RC1
release o----------------------> ...
1.0
The point with this is that testers can work without being interrupted by the programmers and that there is a known baseline for those who are in release management. In distributed version control, the different lines could be cloned repositories and it may look a bit different since repositories share the versioning graph. The principle however is the same.
Regarding web development, there are virtually no build times. But branching in stages (or by tagging your release revisions) it becomes easier to roll-back if you want to check a difficult-to-track-down bug.
However, a whole other thing comes into play and that is the time it takes to deploy the site. Version control tools in my experience are really bad at asset management. Handling art assets that are in total up to several GB usually is a huge pain in the butt to handle in Subversion (more so in Mercurial). Assets may require you to handle them in another way that is less time consuming, such as putting them in a shared space that are synched and backed up in a traditional manner (art assets are usually not worked on concurrently as with source code files).
What is the difference (for just me, a lone developer) between branching, then merging back in, and cloning the repository and pulling it back in?
The concepts of branching and keeping remote repositories are closer now than with centralized version control tools. You could almost consider them being the same thing. In Mercurial (and in git) you can "branch" either by:
Cloning a repository
Creating a named branch
Creating a named branch means that you're making a new path in the versioning graph for the repository you're creating it on. Creating a cloned repository means you're copying the source repository into a new location, and making a new path in the cloned repository's versioning graph. They are both two different implementations of branching as a general concept in version control.
In practice, the only difference between both methods that you should care about is in usage. You clone a repository to have a copy of the source code and have a place to store your own changes in and you create named branches whenever you want to do small experiments for yourself.
Since browsing through branches is a bit quirky for those who accustomed to a straight line of commits, advanced users know how to manipulate their versions so the version history is "clean" with e.g. cherry picking or rebase. At the moment git docs actually explain rebase rather well.
These are the practices that I follow
Each commit should make sense: one bug fix (or a set of bugs related to each other), one (small) new feature, etc. The idea is that if you need to rollback, your rollbacks fall on well defined "boundaries"
Every commit should have a good message explaining what you are committing. Really get into this habit, you will thank yourself later. Doesn't have to be verbose, a few sentences can do. If you are using a bug tracking system, associating a bug number with your commit is also extremely helpful
Now that I use git and branching is so incredibly fast and cheap, I tend to make a new branch for each new feature I'm about to implement. I'd never even consider doing this for many other VCSes. So branching depends on the system you are using, your codebase, your team, etc, there are no hard rules there.
I prefer to always use the command line and get to know my VCS's commands directly. The disconnect that a GUI based frontend can cause can be a pain, and even damaging. Controlling your source code is very important, it's worth getting in there and doing it directly. But that's just my preference.
Back up your VCS. I back up my local repository with Time Machine, and then I push out to a remote repository on my server, and that server is backed up as well. VCS alone is not really a "backup", it can go down too just like anything else.
When/how often should I commit?
You'll probably get lots of contradictory answers on this one. My view is that you should commit changes when they are working, and each commit (or checkin) should contain exactly one "edit". An "edit" is an atomic set of changes that go together to fix a bug or implement a new feature.
There is a theory that you should check in code every few hours even if it's not working, but in that case you will need to be working on your own branch - you don't want to be checking in broken code to your main line, or onto a shared branch.
The advantage of checking in every night is that you have backups (assuming that your repository is on a different machine).
As for branching:
you should have main line that contains always working code.
you should have a current development branch that contains the latest code. When you are happy with this (and it's passed all it's tests) you should merge it back into the main line.
you might want a branch that contains the last released version. This can be used for testing/debugging bugs and releasing patches (in extremis).
update before each commit
provide commit comments
commit as soon as you have something finished
don't commit anything that makes the code in the repository not compiling or buggy
update every morning
sometimes verbally communicate with colleages if there is something important to update
commit code relevant to exactly one thing (i.e. fixing a bug, implementing a feature)
don't worry to make very small commits, as long as they conform to the previous rule
Btw, what's the bad experience with Subversion?
I commit when I am finished a piece of work and only if it is working. It's bad practise to commit to somewhere where other people use the code.
Branching is something that people will argue about. Some people say never branch and just have switches to get something working or not. Do what you feel more comfortable but don't branch just because you can. I use branching and Branch when i am working on a major bit of work where if I commit broken code by accident its not going to affect everyone else.
Q: When/how often should I commit? After any major change, whether it works or not? When I'm done for the night? Only when it reaches it's next stable iteration? After any bugfixes?
A: Whenever you are feeling comfortable, I am commiting as soon as a unit of work is finished and working (which does not mean that the complete task has to be finished). But you should not commit something that does not compile (might inhibit other people in the team,if any). Also, you should not commit incomplete stuff to the trunk if there is any possibility that you have to implement a quick fix or small change before completing it.
Q: Would I branch off when I wanted to, say, change the layout of a menu, then merge back in?
A: Only if there is a possibility that you have to implement a quick fix or small change before completing your task.
The nice thing about branching is that all commits you are doing in the branch will still be available for future reference (if necessary). Also it is much simpler and faster than cloning the repo, I think ;-)
I agree with others on commit times.
Regarding branching, I generally branch only when working on something that breaks what others are doing or when a patch needs to be rolled to production in a file that already has changes that should not go to production. If you're only one developer, then the first scenario doesn't really apply.
I use tags to manage releases - the "production" tag is always associated with the current prod code, and each release is tagged with "release-YYYYMMDD". This allows you to roll back if necessary.
Automated merging isn't perfect. Just because there isn't a line-edit conflict doesn't mean there isn't a syntactic conflict, and that doesn't mean there isn't a semantic conflict.
Does anyone have strategies for authoring low-conflict changes? Is this something that falls out of TDD or other approaches (Certainly TDD will help catch them, but does it actually prevent)?
I've always found that the smaller my commits, the less likely they are to have merge conflicts. The folks who have big problems always seem to go off for days and work on things, then try to merge them all at once.
Right now I'm working on a 2 man team where we are right in the same codebase all the time. We each work in a personal branch and then integrate to a shared branch whenever we have something working. That's usually several times a day. We almost never have merge conflicts, and when we do they're pretty trivial.
So... get the latest code from the repository frequently. Work in your own branch, so you can commit your changes and merge other folks' work without affecting the rest of the team. Then push your own code up to the shared branch as frequently as possible so the changes will be as small as possible.
Also, talk to your team. If you know someone else is working in a specific file, you might want to wait until they get their work in before you jump in. Sometimes you can't help it, but communication at least lets you plan for a complicated merge rather than being surprised.
Classes that violate the single responsiblity principle are the hardest to merge. Finding a class that was difficult to merge probably is a sign that it needs to be refactored, probably in the direction of more parts.
First of all, your code base should be modular. Second, what you need is communication with the rest of your team. Everybody should know who is working on what. If there is a change in the internal API, it should be made clear to the whole team.
Also, before commiting, always fetch the last version, and if complex merging is needed, do it locally.
This is really a human problem, not a technical one. Source control doesn't replace proper communication channels. Your Project Manager should be on top of every changes, and he should realize when a change will span several people.
Also, common sence is needed. :)
Unit testing is of course a big help to catch the most elusive bugs that can come up when merging.
Talk to your fellow developers, and try to avoid sychronous editing of the same block of code wherever possible. Having a well-modularised architecture (small classes, decoupled functionality) makes this possible almost all the time.
If we ever do have a clash, we often resolve it by one of us switching to writing unit tests for untested code for a few minutes.
I am a novice in the world of source/version control and I have been doing as much reading as physically possible to get my head around the different techniques that people use for their own source/version control.
One thing that I have noticed is a pretty distinct break in the methods of developers into two (possibly more?) groups: one group prefers to keep their trunk in an always-stable state and performs all maintenance and future development in the branches, while others prefer to do all of their development in the trunk and keep it in a not-so-stable state.
I am curious as to what the community here at StackOverflow prefers or if you have your own methods.
Note: If it would help tailor the answers, I should note that I am a single developer (at most there would be two or three others in the same project) who works primarily in ASP.NET and SQL Server 2005
As I'm sure you've noticed from searching the web for answers on this topic, this is one of those things where the best answer is "It depends.", and as most of the responses have indicated, it's a trade-off between how easy do you want to be able to commit/merge new code vs. managing an extensive version history that you can easily roll back for support or debugging purposes.
I work for a small company, which means that at any given time, we could have 3 or 4 different versions of code on developer machines that have not yet been committed to the repository. We use TortoiseSVN for our version control system, which gives us the ability to branch/merge without too much difficulty, as well as being able to view the update log or revert our local copies to an earlier revision pretty easily.
Based on your question, I suppose we would fall under the group of developers who attempts to keep, at all times, a stable Trunk, and we branch new code and test it before merging it back into the Trunk. We also make an effort to keep "snapshots" of each version release so that, if necessary, we can easily check out an earlier version and re-build it, without incorporating any new features intended for a future release (This is also a great mechanism for tracking down bugs, as you can use earlier versions of code to help determine when a particular bug was first introduced into your code. However, one thing to be careful of is if your application references common code that is maintained separately from your version-ed code, you will need to keep track of that too!).
On the repository, it ends up looking something like this:
Trunk
v1.0.1.x Release
v1.0.2.x Release
v1.0.2.x Bug-Fix A <-- (These get merged back into Trunk, but remain on the repo)
v1.0.2.x Bug-Fix B
v1.1.1.x Release
v1.2.1.x Development <-- (This will get merged back to Trunk, and replaced by a Release folder)
v1.2.1.x New Feature A <-- (These get merged back into the Development branch)
v1.2.1.x New Feature B
When I first started at the company, our version structure was not quite as sophisticated, and in my experience, I would say that if you have any need whatsoever to keep track of earlier versions, it is will worth the effort to put something like this together (like I said earlier, it doesn't have to look exactly like this, so long as it fits your individual needs), keep it well documented so that all contributors can maintain it (the alternative is that the creator ends up "babysitting" the repo, which quickly becomes an incredible waste of time), and encourage all your developers to follow it. It may feel like a lot of effort in the beginning, but you'll appreciate it the first time you need to take advantage of it.
Good luck!
I do all my development in the trunk. I'm a single developer and don't want to deal with the hassle of branching. When my code is stable I just tag that current version. For example I'd tag version 1.0, 2.0 beta, 2.0 release candidate 1, version 2.0, etc. Branching would probably a better alternative if you’re maintaining old versions for bug fixes and support but since I don't do this I don't worry about it.
The differences may have to do with how painful merging is or isn't in a given version control system.
With git, branching and merging is practically effortless, so it's a common workflow for me to keep my master clean and do all my work in branches. Branching and merging in svn, particularly in previous versions, isn't quite so cheap and easy, so when I was using svn I tended to work directly on the trunk.
Always stable. Even if I'm a single developer -- almost especially if I'm a lone developer.
Having a broken tree to me means one less way to know what I should be doing.
Big changes go in branches, as well as stable releases, and do the smallest unit of changes possible at any given point so as to keep moving forward at a good pace.
This is the methodology which we follow:
Any stable release should be taken from the trunk. Any further work or modifications should go inside the working branch and should be merged with trunk when ready to release.
If have multiple independent developments, each group should have there on branch which they should sync with trunc periodically and merge it back to trunk when ready.
I've always used the main trunk as head of code. Generally new development code goes in there.
We branch for releases and we may branch for a "big" destabilizing experiment.
When we make bug fixes they go into in main first and then they get merged (back-ported) into the appropriate version branch if required.
If the big experiment works out it get's merged back into main.
We use tags for build numbers in the version branches and the main. That way we can get back to a specific version and build if we have to.
I'm in for the always-stable trunk. You need to be able to rebuild the latest stable version at any time...
In your case, I'd strongly recommend avoiding a lot of branching. It's really a fairly advanced process and not necessary for small projects and small teams.
Try and keep it simple to start with, I always try to have a known working build that can reproduced for testing and deployments etc. Depending on your repository you could use revision number (SVN), or just label the known working versions as they are required.
If you find you have multiple people touching the same files then you will need to consider a branching strategy, other than that for such a small dev team it will just be un-necessary overhead...(IMO)
One aspect is how long will the changes be in an unstable state.
When a change I make might affect other people, or the nightly build, then I do my work on a branch, and merge when stable.
When the changes I make won't affect other people (because it is my private code at home, rather than code at work), then I'm OK with checking in non-working intermediate states if that's what I want. Sometimes, I'll make a few checkins in a row which are not stable; that's OK for me when it is just me who is affected and the workflow will be continuous. It's if I come back in a few years time (as opposed to just a few days) and things aren't working that it gets problematic (one disadvantage of having been around as long as I have - I do have some projects that are still in development and maintenance that are old enough to vote).
I use a variant of tagging to achieve repeatable builds - so if I need to go back to a stable version for a bug-fix, I can use the tag information to do that. It is crucial to be able to get a stable version on demand.
One key distinction is how big files tend to be on average. Big files (1000 lines +) tend to have many independent changes that are trivially automatically mergeable. So the fact that someone else is actively changing a file you are about to start work on is probably uninteresting, so it is ok if the system makes that hard to discover.
So you tend to end up a VC strategy that has a lot of branches, and easy merges. New functionality is written in new branches.
If you are working with the smaller, highly-cohesive files typical of an OO design, in a language like Java, such accidental conflicts are a lot rarer. Even as an artificial example, it is pretty hard to come up with two sets of changes that can be made to a class (and corresponding JUnit test cases) that can sensibly be made in isolation and then automatically weaved back together by a text merge tool.
If you do a lot of refactoring (renaming and splitting files) then that stresses out the merge tool even more.
So you tend to be best off with a VC strategy that has an identifiable and usable stable trunk and minimal branches.
In the first approach, new functionality is written in new branches, and merged when complete. In the second, it is written in new files, and enabled when complete.
Of course, if you do the second, you definitely need strong protection from the baseline becoming unusable for any length of time (i.e. continuous integration and a strong automatically-run test suite).
Our policy when delivering a new version is to create a branch in our VCS and handle it to our QA team. When the latter gives the green light, we tag and release our product. The branch is kept to receive (only) bug fixes so that we can create technical releases. Those bug fixes are subsequently merged on the trunk.
During this time, the trunk sees the main development work, and is potentially subject to refactoring changes.
The issue is that there is a tension between the need to have a stable trunk (so that the merge of bug fixes succeed -- it usually can't if the code has been e.g. extracted to another method, or moved to another class) and the need to refactor it when introducing new features.
The policy in our place is to not do any refactoring before enough time has passed and the branch is stable enough. When this is the case, one can start doing refactoring changes on the trunk, and bug-fixes are to be manually committed on both the trunk and the branch.
But this means that developpers must wait quite some time before committing on the trunk any refactoring change, because this could break the subsequent merge from the branch to the trunk. And having to manually port bugs from the branch to the trunk is painful. It seems to me that this hampers development...
How do you handle this tension?
Thanks.
This is a real practical problem. It gets worse if you have several versions you need to support and have branched for each. Even worse still if you have a genuine R&D branch too.
My preference was to allow the main trunk to proceed at its normal rate and not to hold on because in an environment where release timings were important commercially I could never argue the case that we should allow the code to stabilise ("what, you mean you released it in an unstable state?").
The key was to make sure that the unit tests that were created for the bug fixes were transitioned across when the bug was migrated into the main branch. If your new code changes are genuinely just re-factoring then the old tests should work equally well. If you changes are such that they are no longer valid then you can't just port you fix in any case and you'll need to have someone think hard about the fix in the new code stream.
After quite a few years managing this sort of problem I concluded that you probably need 4 code streams at a minimum to provide proper support and coverage, and a collection of pretty rigorous processes to manage code across them. It's a bit like the problem of being able to draw any map in 4 colours.
I never found any really good literature on this subject. It will inevitably be linked to your release strategy and the SLAs that you sign with your customers.
Addendum: I should also mention that it was necessary to write the branch merging as specific milestones into the release schedule of the main branch. Don't under-estimate the amount of work that might be entailed in bring your branches together if you have a collection of hard-working developers doing their job implementing features.
Where I work, we create temporary, short-lived (less than day -- a few weeks) working branches for every non-trivial change (feature add or bugfix). Trunk is stable and (ideally) potentially releasable all the time; only done items get merged into it. Everything committed from trunk gets merged into the working branches every day; this can be largely automated (we use Hudson, Ant and Subversion). (This last point because it's usually better to resolve any conflicts sooner than later, of course.)
The current model we use was largely influenced by an excellent article (which I've plugged before) by Henrik Kniberg: Version Control for Multiple Agile Teams.
(In our case, we have two scrum teams working on one codebase, but I've come to think this model can be beneficial even with one team.)
There is some overhead about the extra branching and merging, but not too much, really, once you get used to it and get better with the tools (e.g. svn merge --reintegrate is handy). And no, I do not create a temp branch always, e.g. for smaller, low-risk refactorings (unrelated to the main items currently under work) that can easily be completed with one commit to trunk.
We also maintain an older release branch in which critical bugs are fixed from time to time. Admittedly, there may be manual (sometimes tedious) merging work if some particular part of code has evolved in trunk significantly compared to the branch. (This hopefully becomes less of an issue as we move towards continually releasing increments from trunk (internally), and letting marketing & product management decide when they want to do an external release.)
I'm not sure if this answers your question directly, or if you can apply this in your environment (with the separate QA team and all) - but at least I can say that the tension you describe does not exist for us and we are free to refactor whenever. Good luck!
Maybe Git (or other DVCS) are better at handling merges to updated code thanks to the fact that they (really) manage changes rather than just compare files... As Joel says :
With distributed version control, merges are easy and work fine. So you can actually have a stable branch and a development branch, or create long-lived branches for your QA team where they test things before deployment, or you can create short-lived branches to try out new ideas and see how they work.
Not tried yet, though...
Where I work, we keep with the refactoring in the main branch. If the merges get tricky, they just have to be dealt with on an ad-hoc basis, they're all do-able, but occasionally take a bit of time.
Maybe our problem comes from the fact that we have branches that must have quite a long life (up to 18 months), and there are many fixes that have to be done against them.
Making sure that we only branch from extremely stable code would probably help, but will not be so easy... :(
I think the tension can be handled by adding following ingredients to your development process:
Continuous integration
Automated functional tests (I presume you already count with unit tests)
Automated delivery
With continuous integration, every commit implies a build where all unit tests get executed and you are alarmed if anything goes wrong. You start working more with head and you are less prone to branching the code base.
With automated functional tests, you are able to test your application at the click of the button. Generally, since these tests take more time, these are run nightly.
With this, the classic role of versioning starts to lose the importance. You do not make your decision on when to release based on the version and its maturity, it’s more of the business decision. If you have implemented unit and functional testing and your team is submitting tested code, head should always in state that can be released. Bugs are continuously discovered and fixed and release delivered but this is not any more cyclical process, it’s the continuous one.
You will probably have two types of detractors, since this implies changing some long rooted practices. First, the paradigm shift of continuous delivery seems counter-intuitive to managers. “Aren’t we risking to ship a major bug?” If you take a look at Linux or Windows distros, this is exactly what they are doing: pushing releases towards customers. And since you count with suite of automated tests, dangers are further diminished.
Next, QA team or department. (Some would argue that the problem is their existence in itself!) They will generally be aversive towards automating tests. It means learning new and sometimes complicated tool. Here, the best is to preach by doing it. Our development team started working on continuous integrations and in the same time writing the suite of functional tests with Selenium. When QA team saw the tool in action, it was difficult to oppose its implementation.
Finally, the thurth is that the process I described is not as simple as addig 3 ingredinents to your development process. It implies a deep change to the way you develop software.
In my current job the supervisor's practice is to only check in production ready code. Most recently the project I was on involved work by 3 different developers with some file overlap. This meant manually integrating changes despite the fact that some changes took a day and then it was done. I wanted to see if this was a common practice and get suggestions on how to change this practice with the knowledge that many times my opinion means little in the grand scheme of things.
You can use various ways to handle this situation, depending on your source control system.
Private branches: Allow you to check in and work on code while you go, merging back and forth at appropriate times.
Shelvesets/pacakaged changesets: Allow you to store changesets and send them around for review - ensuring they're production ready before check in.
As to whether this is an appropriate way to work, we don't allow check-in to main branches without prior review. To pass review your code must pass various automated tools, and then must be acceptable to your peer reviewer. For some definitions of "production ready" - this is it. Therefore, we do something like what you do. However, we use private branches to ensure that check-ins can still be made while this is in progress, and that other check-ins don't have to interfere.
If production ready means tested in an integration environment, then it sounds like you may need staging branches or something similar.
Code that is checked in should be unit tested, but, to me, "production ready" implies that it's gone through integration and system testing. You can't do that until a code freeze, so I don't see how you can do that before every check in.
Start by switching away from VSS to something more reliable & feature-rich. See How to convince a company to switch their Source Control
Then apply known-good practices:
Check in often
Pick up others' changes often, to simplify merging
Use fast unit tests to make sure each change meets a minimum bar
Require that that the checked-in code always builds, and always passes tests.
Now you won't be "production ready" at this point: you will still need a couple weeks to test & fix before you can deploy. Getting that time down is awesome for you, and awesome for your customer, so invest in:
High quality automated acceptance tests.
wouldn't it be a good idea to have a testing branch of the repo that can have the non "production ready code" checked in after the changes are done and tested?
the main trunk should never have code checked in that breaks the build and doesn't pass unit tests, but branches don't have to have all those restrictions in place.
I would personally not approve of this because sometimes that's the best way to catch problem code with less experienced developers (by seeing it as they are working on it) and when you "check in early and often" you can rollback to earlier changes you made (as you were developing) if you decide that some changes you made earlier was actually a better idea.
I think it may be the version control we user, VSS in combination with a lack of time to learn the branching. I really like the idea of nightly check ins to help with development and avoid 'Going Dark'. I can see him being resistant to the trunks but perhaps building a development SS and when the code is production ready move it to production SS.
From the practices I have seen the term production quality is used as a 'frightener' to ensure that people are scared of breaking top of tree, not a bad thing to be honest because top of tree should always work if possible.
I would say that best practice is that you should only be merging distinct (i.e. seperate) functional components on the top of tree. If you have a significant overlap on deltas to the same source files I think this 'might' indicate that somewhere along the line the project management has broken down, and that those developers should have merged their changes to seperate integration branch before going in to the main line sources. An individual developer saying that they unit tested their stuff is irrelevant, because the thing they tested has changed!
Trying to solve integration problems on your main line codeline will inevitably stall other unrelated submissions.
Assuming that you are working in a centralized version control system (such as Subversion), and assuming that you have a concept of "the trunk" (where the latest well-working code lives):
If you work on new features in "features branches"/"experimental branches", then it's OK to commit code which is far from finished. (When the feature is done, you commit the well-behaving result into the "trunk".)
But you will not win a popularity contest if committing non-compiling/obviously non-working code into the "trunk" or a "release branch".
The Pragmatic Programmers have a book called Pragmatic Version Control using Subversion which includes a section with advice about branches.
Check in early and check in often for two main reasons -
1 - it might make it easier to integrate code
2 - in case your computer explodes your weeks of work isn't gone
An approach I particularly like is to have different life cycle versions in the depot. That is,for example, have a dev version of the code that is where the developers check in code that is in being worked on; then you could have a beta version, where you could add beta fixes to your code; and then a production version.
There is obvious overhead in this approach, such as the fact that you will have a larger workspace on you local machine, the fact that you will need need to have a migration process into place to move code from one stage to the next (which means a code freeze when doing the integration testing that goes with the migration), and that depending on the complexity of the project(s) you might need to have tools that change settings, environment variables, registry entries, etc.
All of this is a pain to set up, but you only do it once, and once you have it all in place, makes working on different stages of the code a breeze.
#bpapa
Nightly backups of work folders to servers will prevent losing more than a days work.
#tonyo
Let's see the requirement documents were completed the day after we finished coding. Does that tell you about our project management?
We are a small shop so while you would think change is easy there are some here that are unbending to the old ways.