Gerenciamento de código e compartilhamento de conhecimento em equipes de desenvolvimento ágil
Uma breve história sobre controle de versão e colaboração.
Pré-história
Em tempos remotos da humanidade, quando os primeiros desenvolvedores tentavam se adaptar a um meio ambiente digital de extrema vulnerabilidade e munidos apenas de poucas tecnologias, toda a gestão de arquivos era feita de forma manual.
A organização destes arquivos dependia muito da lógica que a equipe, ou mesmo o próprio desenvolvedor, decidia utilizar. Variando as estratégias e sem uma metodologia padrão para criar seu sistema de arquivos. Gerenciando as versões (se é que podemos definir isto como gestão) baseado em algumas pastas. Tudo de forma manual e muito trabalhosa.
Este modelo se tornou obsoleto por trazer uma carga de complexidade enorme entregando pouca ou nenhuma eficiência. Tornando a gestão de projetos de software uma saga infernal.
Evoluindo para o controle de versão Centralizado
Confrontados com a problemática de gerir seus entregáveis, tecnologias foram desenvolvidas para facilitar e adicionar uma camada de controle e histórico para os projetos.
Com este formato já era possível controlar vários arquivos ao mesmo tempo. Ferramentas como SVN, TFS são as mais utilizadas para esta estratégia que centraliza todo o código gerido em apenas um servidor.
Neste fluxo somos obrigados resolver todos os conflitos localmente antes de integrar o código com o servidor do repositório para cada commit.
A necessidade de resolver os conflitos, adicionado a um servidor único, gera lentidão e constate retrabalho sempre que um integrante da equipe insere suas modificações no código base. Pois todos são obrigados a atualizar suas versões locais, resolver os conflitos quando houverem, para que possam efetivamente integrar seus commits ao repositório oficial. Tornando o fluxo de trabalho um pouco "travado".
Apesar dos sensíveis ganhos com esta abordagem, encontramos alguns problemas de integração que são vivenciados diariamente.
Controle de Versão distribuído
Com a chegada de tecnologias como GIT e Mercurial, foram desenvolvidos novos paradigmas para a gestão de projetos de software.
Em uma abordagem descentralizada conseguimos gerir várias alterações. Ampliando o poder e o desacoplamento das modificações.
O fluxo de conflitos foi invertido. Com esta abordagem nós conseguimos seguir o fluxo localmente sem problemas, inserindo commits, deixando os conflitos para o momento da integração com o servidor central.
Outro ganho da distribuição é a existência de múltiplos hosts para o projeto. Facilitando com que todos possam trabalhar independentemente e integrando seus códigos pontualmente.
Mas para que este fluxo, mais atual, funcione com a confiabilidade e segurança que desejamos é necessário aplicar algumas práticas para que não entremos na saga infernal do controle de versão.
Referência: http://ericsink.com/vcbe/html/history_of_version_control.html
Comparando Fluxos para controle de versão
Duas abordagens básicas para times ágeis utilizando GIT como controle de versão.
Feature Branch Workflow
A ideia central é que todas as features devem ser implementadas em uma branch dedicada a alteração em questão, e então integrada a branch principal (master). Esse encapsulamento facilita a contribuição de diversos contribuidores trabalharem em paralelo sem interferir no código base. Isto significa que a branch master nunca conterá códigos quebrado, o que é uma grande vantagem para a integração contínua.
Encapsular suas modificações em uma branch possibilita a vantagem de criar Pull Requests. Esta ação possibilita iniciar discussões sobre a implementação, compartilhar conhecimento, manter padrões, sugerir melhorias, etc.
Neste fluxo ainda temos um repositório central e mantemos uma branch principal (master) para refletir nosso histórico. Mas em vez de criar commits diretamente na branch principal, nós criamos uma branch para a feature que estamos trabalhando com um nome descritivo como por exemplo animated-menu-itens, feature/authentication ou mesmo issue-#1012. A ideia é representar de forma clara e descritiva o propósito que estamos desenvolvendo em cada branch.
Feature branch é uma forma incrivelmente flexível para desenvolver projetos. O problema é, algumas vezes é flexível demais. Para times muito grandes é melhor definir uma metodologia com regras mais específicas.
Gitflow Workflow
Gitflow Workflow é similar aos outros modelos no que diz respeito a descentralização dos repositórios e os desenvolvedores conseguem trabalhar localmente subindo suas alterações para o repositório central. A principal diferença está na estrura de branches do projeto.
Gitflow — Historical Branches
Em vez de uma única branch (master), o fluxo usa duas branches principais para manter o histórico do projeto. A branch master mantém os releases oficiais, enquanto a branch develop serve como um ponto de integração para features. É convencionado que ao integrar as alterações da branch Develop na master sejam criadas tags com todos os commits contendo um número de versão.

Gitflow — Feature branches
Cada nova feature deve ser desenvolvida em sua própria branch. Elas devem ser criadas a partir da branch Develop, como sua branch pai.
Quando a feature estiver completa e chegarmos ao momento de integrar o nosso código, o Pull Request deve ser aberto para integrar com a branch develop, e nunca diretamente para a branch master.

Gitflow — Release Branch
Somente quando a branch develop conter features suficientes para a criação de um release. Você deverá criar um fork da branch develop para criar o release. Criar essa branch começa o ciclo de release, e a partir deste ponto não serão integradas novas features. Apenas correções de bugs, documentação e outras atividades relacionadas a release poderão ser adicionadas a branch release.
Com a release pronta para a entrega, ela será integrada a branch master e criamos uma tag com o número da versão. A release também deve ser integrada a develop, o que provavelmente deve ter progredido desde que o release foi criado.
Use uma branch dedicada a preparação da release para tornar isso possível que um time trabalhe na release corrente enquanto os outros times continuam a trabalhar nas features para a nova release.

Convenções:
- branch off:
develop - merge into:
master - naming convention:
release-* or release/*
Gitflow — Maintenance Branches

Branches de manutenção, ou "hotfix" são usadas para pequenas alterações em releases. Esta é a única branch que pode ser integrada diretamente a Master. Assim que a correção estiver disponível, a branch hotfix deve ser incorporada tanto a branch master quanto a branch develop, ou mesmo a feature corrente. A branch master, após receber a correção deve ser tagged com uma versão de atualização.
Seguir esse fluxo libera o seu time para continuar trabalhando em features sem interrupções.
Compartilhando Conhecimento no dia a dia Ágil
Estratégia de apoio a contribuição com foco em compartilhamento de conhecimento.
Pull Requests
Isolar features em branches torna possível discussões via Pull Request. Quando alguém conclui uma feature ele não deve integrar diretamente a Master. Em vez disso, ele enviam o sua feature branch para o repositório central, abre um Pull Request solicitando o merge de suas alterações para Master. Este é o momento que outros desenvolvedores podem compartilhar suas percepções a respeito do código, testar a feature e garantir que a integração ocorrerá sem problemas. Neste momento também podemos trocar experiências, discutir sobre possibilidades de melhorias, mitigar possíveis problemas e também contribuir para a feature em questão sempre que for conveniente.
Issue Tracking
Devemos manter os ambientes, tanto no Github (PR, commits e/ou issues), tanto no board (trello card) linkados. O github deve conter o link para o card ao qual estamos atendendo com as alterações propostas. Isso é possível com a criação de issues.
Também devemos manter link de nossos PR e/ou issues no Card referente a tarefa que estamos atendendo. Criando uma dupla ligação para que seja fácil a navegação entre ferramentas.
Revisão de Código (Code Reviews)
A revisão de código deve acontecer sempre que um PR é aberto. Em um mundo perfeito devemos ter o PR aceito por dois integrante da equipe, que efetivamente revisaram e testaram a branch em questão.
Este é o momento perfeito para entendermos o que foi implementado, discutir a respeito da implementação com o seus pares. Comentar e discutir as alterações propostas através de Pull Requests é uma excelente forma de entender as features que estão sendo inseridas no sistema/projeto.
Este também é o momento de discutirmos sobre a aderência do código aos padrões acordados, ou mesmo (re)definir padrões, assim como decisões arquiteturais.
Se você estiver trabalhando em par na feature em questão. É importante solicita a revisão de um novo par de olhos no código. Assim garantimos que estamos seguindo na direção correta além de receber um feedback de alguém de fora (da tarefa). O olhar apurado de alguém que não está "viciado" no código em questão é fundamental para ampliar a percepção da revisão.
Programação em Par ( Pair Programming)
Pessoalmente eu acredito na programação em par como uma das formas mais efetivas de contribuição e compartilhamento de conhecimento em equipes.
Com a programação em par conseguimos que o time trabalhe junto e integrado, criando, não só um ambiente de compartilhamento intenso, mas também integração entre a equipe.
Para efetivamente praticar a programação em par é necessário que o par sente junto para unir forças na implementação da mesma solução. Eles devem utilizar a mesma estação de trabalho, o mesmo monitor dividindo em a execução da tarefa em piloto e co-piloto.
O piloto, geralmente o mais experiente deve pilotar a máquina, enquanto o co-piloto acompanha a implementação do piloto com atenção para garantir que nada passou despercebido. O co-piloto tem a responsabilidade de identificar possíveis bugs, erros de lógica, e até padrão de código. Enquanto o co-piloto acompanha atentamente a implementação poderá tirar dúvidas e discutir com o piloto a melhor abordagem para a implementação da solução.
Também é indicado que os papeis sejam alternados de tempos em tempos, para que a visibilidade esteja equilibrada entre ambos.
Programação da Máfia (Mob Programming)
Nos últimos anos mob programming vem ganhando espaço na industria de software como prática de desenvolvimento e alternativa ao pair programming. Esta prática envolve reunir toda a equipe para a implementação de uma feature. Da mesma forma como acontece no pair, só que adicionando mais pessoas do time para o desenvolvimento da solução.
Testes
Testes podem servir como documentação do seu código. Além de manterem o seu código estável. Prefira especificações executáveis a documentos estáticos.
Documentação
Mantenha sua documentação simples o suficiente, mas não muito simples. Uma boa documentação é simples o suficiente para concluir o trabalho.
O ideal é que todos os projetos mantenham uma documentação necessária para executar o projeto no README.md da aplicação facilitando para que o desenvolvedor consiga executar o projeto.
Para documentações mais detalhadas é importante manter a wiki do projeto, no caso do Github, isto pode ser feito no próprio repositório, pois ele já prove as ferramentas necessárias para documentar seu projeto.
O histórico da branch principal de um repositório também pode fornecer informações importantes sobre a evolução e documentação do código contido. Sendo assim devemos ter zelo com nosso histórico o mantendo de forma atômica, facilitando a gestão do projeto.
Encontros, Dojo, Coffee/Beer Code
Para assuntos mais específicos e que provavelmente não façam parte do nosso dia a dia, podemos agendar encontros fora do horário produtivo para discussão/disseminação de conteúdo relevante para o time, ou mesmo alguns integrantes que podem inclusive ser de outras squads. Criando um ambiente descontraído e de contribuição entre colegas e equipes.