Meu conselho para fazer lançamentos é ter Versões de recurso e versões de manutenção. Lançamentos de recursos seriam os lançamentos que recebem novos recursos. Estes são adicionados ao seu tronco do subversion. Quando você acha que esses recursos estão completos, você os ramifica em uma ramificação de lançamento. Quando o processo de controle de qualidade estiver satisfeito com essa versão, você codificará a versão e implantará o código em seus servidores.
Agora, quando você recebe um relatório de bug, você envia esta correção para o branch e para o tronco. Quando estiver satisfeito com o número de bugs corrigidos, você pode marcar e implantar uma versão de manutenção.
É importante que você tenha uma ramificação da sua base de código ativo (ou tenha a capacidade de criar uma conhecendo a revisão ativa) separada de sua ramificação de desenvolvimento, para que você possa implantar correções em seu código ativo sem ter que implantar novos recursos ou código não testado.
Eu recomendaria usar o sistema de empacotamento nativo de sua distribuição para implantar novo código. Se você tem um pacote que contém toda a sua base de código, você sabe que todo o seu código foi implementado em uma espécie de operação atômica, você pode ver qual versão está instalada em um relance, pode verificar sua base de código usando checksum. Retroceder é apenas um caso de instalar a versão do pacote anteriormente instalada.
O único roadblock que vejo para você implementando isso é que você parece ter várias cópias da base de código para clientes diferentes em execução em um único servidor. Eu tentaria organizar seu código para que todos os clientes executassem os mesmos arquivos e não usassem cópias. Não sei quão fácil isso seria para você, mas reduzir o número de cópias com as quais você terá de lidar reduzirá enormemente sua dor de cabeça.
Estou assumindo que, como você mencionou o LAMP, você está usando PHP ou outra linguagem de script, que não requer um processo de compilação. Isso significa que você provavelmente está perdendo um processo maravilhoso chamado Integração Contínua. O que isso basicamente significa é que seu código está sendo continuamente testado para garantir que ainda esteja em um estado liberável. Toda vez que alguém verifica um código novo, um processo o pega e executa o processo de criação e teste. Com uma linguagem compilada você normalmente usaria isso para garantir que o código ainda fosse compilado. Com cada idioma, você deve aproveitar a oportunidade para executar testes de unidade (seu código está em unidades testáveis, não é?) E testes de integração. Para sites, uma boa ferramenta para testar testes de integração é o Selenium. Em nossas construções Java, também medimos a cobertura de código e as métricas de código para ver como progredimos com o tempo. O melhor servidor de IC que encontramos para o Java é o Hudson, mas algo como o buildbot pode funcionar melhor em outros idiomas. Você pode criar pacotes usando seu servidor de CI.