A resposta depende do tamanho de sua equipe e da qualidade de seu controle de origem e da capacidade de mesclar conjuntos de mudanças complexos corretamente. Por exemplo, em controle de fonte de filial completo como CVS ou mesclagem de SVN pode ser difícil e você pode ficar melhor com o primeiro modelo, enquanto se usar um sistema mais complexo como IBM ClearCase e com um tamanho de equipe maior, você poderia ser melhor com o segundo modelo ou uma combinação dos dois.
Eu, pessoalmente, separaria o modelo de branch de recurso, onde cada recurso principal é desenvolvido em um branch separado, com sub-branches de tarefa para cada mudança feita por desenvolvedor individual. Conforme os recursos se estabilizam, eles são mesclados ao tronco, que você mantém razoavelmente estável e passa em todos os testes de regressão o tempo todo. Conforme você se aproxima do fim do seu ciclo de lançamento e todos os ramos de recursos se fundem, você estabiliza e ramifica um ramo do sistema de lançamento no qual você apenas faz correções de bugs de estabilidade e backports necessários, enquanto o tronco é usado para o desenvolvimento da próxima versão e você novamente ramificar para novos ramos de recursos. E assim por diante.
Desta forma, o trunk contém sempre o código mais recente, mas você consegue mantê-lo razoavelmente estável, criando rótulos estáveis (tags) nas principais mudanças e fusões de recursos, os branches de recursos são de desenvolvimento rápido com integração contínua e sub-branches de tarefas individuais podem ser frequentemente atualizado a partir do branch de recursos para manter todos trabalhando no mesmo recurso em sincronia, enquanto simultaneamente não afeta outras equipes que trabalham em recursos diferentes.
Ao mesmo tempo, você tem ao longo da história um conjunto de ramos de lançamento, onde você pode fornecer backports, suporte e correções de bugs para seus clientes que por qualquer motivo permanecem nas versões anteriores do seu produto ou mesmo apenas na última versão lançada. Assim como com o tronco, você não configura a integração contínua nos ramos de lançamento, eles são cuidadosamente integrados ao passar em todos os testes de regressão e outros controles de qualidade de lançamento.
Se por algum motivo dois recursos são co-dependentes e precisam de mudanças feitas um pelo outro, você pode considerar desenvolver ambos no mesmo ramo de recurso ou exigir que os recursos mesclem regularmente partes estáveis do código para o tronco e, em seguida, atualize as alterações de tronco para trocar código entre ramos de tronco. Ou, se você precisar isolar esses dois recursos de outros, pode criar uma ramificação comum a partir da qual ramificará essas ramificações de recursos e que poderá usar para trocar código entre os recursos.
O modelo acima não faz muito sentido com equipes com menos de 50 desenvolvedores e sistema de controle de origem sem ramificações esparsas e capacidade de mesclagem adequada como CVS ou SVN, o que tornaria todo este modelo um pesadelo para configurar, gerenciar e integrar.