Controle de Versão

Um sistema de controle de versão (ou sistema de controle de revisão) é uma combinação de práticas e tecnologias para rastrear e controlar as mudanças nos arquivos do projeto, em particular o código fonte, documentação, e páginas da web. Se você nunca usou um controle de versão antes, a primeira coisa que vocÇe deve fazer é encontrar alguém que o tenha, e colocá-lo para participar do projeto. Hoje em dia, todos esperam que ao menos o código fonte do projeto esteja em um controle de versão, e provavelmente não irá levar o projeto a sério se ele não usar um controle de versão com o mínimo de competência.

O motivo do controle de versão ser tão universal é que ele ajuda virtualmente com todos os aspectos de tocar um projeto: comunicação entre desenvolvedores, gererenciamento de lançamentos, gerenciamento de bugs, estabilidade de código e esforços experimentais de desenvolvimento, e atribuição e autorização de mudanças para desenvolvedores em particular. O sistema de controle de versões fornece um força de coordenação central entre todas essas áreas. O coração de um controle de versão é o gerenciamento de mudança: identificando cada modificação sutil realizada nos arquivos do projeto, anotando toda e cada alteração com metadados como a data da alteração e o autor, e então reproduzindo o fato para qualquer um que perguntar, da maneira que ele quiser. É um mecanismo de comunicação onde é mudança é a unidade básica de informação.

Esta seção não discute todos os aspectos da utilização de um sistema de controle de versão. Ele é tão abrangente que será tratada topicamente no decorrer do livro. Aqui, iremos nos concentrar em escolher e configurar um sistema de controle de versões de uma forma que irá promover o desenvolvimento estrada abaixo.

Vocabulário do Controle de Versão

Este livro não o ensina como usar o controle de versão se você nunca o utilizou antes, mas seria impossível discutir sobre o assunto sem conhecer alguns termos chaves. Estes termos são úteis independentemente de qualquer sistema de controle de versão em particular: eles são os substantivos e verbos básicos de uma colaboração em rede, e será utilizada de forma genérica no decorrer do livro. Mesmo se não houvesse sistemas de controle de versão no mundo, a questão do gerenciamento de mudanças iria permanecer, e estas palavras nos fornece a linguagem para falar sobre o assunto de maneira concisa.

commit

Realizar uma mudança no projeto; mais formalmente, armazenar uma mudança no banco de dados de controle de versão de uma forma que ela possa ser incorporada em versões futuras do projeto. O "Commit" pode ser usado com um verbo ou como um substantivo. Como um substantivo, ele é essencialmente um sinônimo de "mudança". Por exemplo: "Eu acabei de comitar uma correção para corrigir o bug de crash do servidor que o pessoal tem reportado no Mac OS X. Jay, você pode por favor revisar o commit e verificar se eu não estou usando o alocador indevidamente?"

log message

Um pequeno comentário anexado a cada commit, descrevendo a natureza e o propósito do commit. Log messages estão entre os documentos mais importantes no projeto: elas são a ponte entre a linguagem altamente técnica das mudanças individuais de um código e uma linguagem mais direcionada aos usuários de funcionalidades, correções de bugs, e progresso do projeto. Mais adiante nesta seção, veremos maneiras de distribuir log messages para os públicos apropriados; o “Codifying Tradition” no Capítulo 6, Communications também discute maneiras de encorajar os contribuidores a escrever log messages concisas e úteis.

update

Solicitar que as mudanças dos demais (commits) sejam incorporadas em sua cópia local do projeto; ou seja, deixar a sua cópia "atualizada". Esta é uma operação muito comum; a maioria dos desenvolvedores atualizam seus códigos diversas vezes por dia, de maneira que eles sabem que estão executando algo muito próximo do que os demais estão trabalhando, e caso eles encontrem um bug, eles tem certeza que ele ainda não foi corrigido. Por exemplo: "Olá, eu notei que o código de indexação está sempre desprezando o último byte. Este é um novo bug?" "Sim, mas ele foi corrigido na semana passada—atualize seu código e ele deve desaparecer."

repositório

Um banco de dados no qual mudanças são armazenadas. Alguns sistemas de controle de versão são centralizados:há um único repositório mestre que armazena todas as mudanças feitas no projeto. Outros são descentralizados: cada desenvolvedor tem seu próprio repositório, e alterações podem ser trocadas entre repositórios arbitrariamente. O sistema de controle de versão manté controle das dependências entre as alterações, e quando é hora de lançar uma versão, um conjunto particular de alterações é aprovado para aquele lançamento. O questionamento referente a se centralizado ou descentralizado é melhor é uma das duradouras guerras santas do desenvolvimento de software; tente não cair na armadilha de discutir sobre isso em suas listas de projetos.

checkout

O processo de se obter uma cópia do projeto a partir de um repositório. Um checkout geralmente gera uma árvore de diretórios chamada de cópia de trabalho (working copy), a partir da qual alterações podem ser comitadas de volta ao repositório original. Em alguns sistemas de controle de versão descentralizados, cada cópia é em sí mesma um repositório, e mudanças podem ser extraídas de (ou enviadas a) qualquer repositório que esteja disposto a aceitá-las.

Cópia de Trabalho

Uma árvore de diretórios privada do desenvolvedor contendo o código fonte do projeto, e possivelmente suas páginas da web ou outros documentos. Uma cópia de trabalho também contém um pouco de metadata gerenciado pelo sistema de controle de versão, que conta de que repositório vem a cópia de trabalho, que "revisões" (veja abaixo) dos arquivos estão presentes, etc. Geralmente, cada desenvolvedor tem sua própria cópia de trabalho, na qual ele faz e testa mudanças, e da qual ele envia.

revision (revisão), change (mudança), changeset (grupo de mudança)

Uma "revision" é geralmente uma encarnação específica de um arquivo ou diretório em particular. Por exemplo, se um projeto iniciar na revisão 6 do arquivo F, e então alguém efetua uma mudança e o commit do arquivo F, isto produz a revisão 7 de F. Alguns sistemas também usam "revision", "change", or "changeset" para se referir a um conjunto de modificações em que se é efetuado o commit uma única vez, como uma unidade conceitual.

Estes termos ocasionalmente possuem significados técnicos distintos nos diversos sistemas de controle de versões, mas a idéia principal é sempre a mesma: eles fornecem uma forma precisa de dizer exatamente em uma linha histórica as modificações de um arquivo ou de um conjunto de arquivos (traduzindo, imediatamente antes ou depois que um bug é corrigido). Por exemplo: "Ah sim, ela corrigiu isto na revisão 10" ou "Ela corrigiu isso na revisão 10 do foo.c."

Quando alguém fala sobre um arquivo ou um conjunto de arquivos sem especificar uma revisão em particular, geralmente se assume que se trata da revisão mais recente disponível.

diff

Uma representação textual de uma mudança. Uma diff mostra quais linhas foram modificadas e como elas foram modificadas, e adiciona algumas linhas próximas para contextualizar em ambos os lados. Um desenvolvedor que já está familiarizado com o código pode geralmente confrontar uma diff com o código e identificar do que se trata a mudança, e até identificar possíveis bugs.

tag (ou etiqueta)

Uma informação para uma coleção em particular de arquivos para revisões especificadas. Tags são usadas geralmente para preservar snapshots interessantes do projetos. Por exemplo, uma tag é gerada para cada release pública, exatamente com os conjuntos de arquivos/revisões que compreendem aquela release. Nomes comuns de tags são escritas como Release_1_0, Delivery_00456, etc.

branch (ou ramo)

Uma cópia do projeto sob o controle de versão, porém isolada de uma maneira que as mudanças realizadas no branch não afetem o resto do projeto e vice-versa, exceto quando as mudanças são deliberadamente mescladas ("merge") de um lado para o outro (veja abaixo). Branches (ou ramos) também são conhecidas como "linhas de desenvolvimento". Mesmo quando um projeto não possui branches explícitas, o desenvolvimento ainda é considerado como sendo executado no "branch principal", também conhecido como "linha principal" ou "trunk".

Branches oferecem uma maneira isolada de diferentes linhas de desenvolvimento entre eles. Por exemplo, um branch pode ser usado para um desenvolvimento experimental que poderia desestabilizar muito a linha principal (ou trunk). Assim como uma branch pode ser usada como um local para estabilizar uma nova release. Durante o processo de release, o desenvolvimento regular continua sem interrupções no branch principal do repositório; enquanto isso, na branch da release, nenhuma mudança é permitida com exceção daquelas que são aprovadas pelos gerentes de releases. Desta forma, disponibilizar uma release não precisa interferir no andamento dos trabalhos de desenvolvimento. Veja em “Use branches to avoid bottlenecks” mais adiante neste capítulo para uma discussão mais detalhada sobre branches.

merge (a.k.a. port) (ou junção)

Mover uma mudança de um branch para o outro. Isso inclui um merge da linha principal com algum branch, ou vice versa. Na verdade, estes são os tipos mais comuns de merge; é raro transportar mudanças entre dois branches não-principais. Veja “Singularidade de Informação” para mais detalhes sobre este tipo de merge.

"Merge" tem um segundo significado: é o que o sistema de controle de versão faz quando identifica que duas pessoas mudaram o mesmo arquivo mas sem interferências. Como as duas mudanças não interferem uma com a outra quando uma pessoa a atualiza sua cópia do arquivo (já contendo suas próprias mudanças), as mudanças da outra pessoa serão automaticamente agregadas. Isto é muito comum, especialmente em projetos que contém muitas pessoas trabalhando no mesmo código. Quando duas modificações diferentes se interferem, o resultado é um "conflito"; veja abaixo.

conflict (ou conflito)

É o que acontece quando duas pessoas tentam modificar a mesma parte do código de maneiras diferentes. Todos os sistemas de controle de versão detectam conflitos automaticamente, e notificam pelo menos um humano de que suas mudanças conflitam com as de outra pessoa. O humano notificado deve então resolver o conflito, e comunicar a resolução para o sistema de controle de versão.

lock (ou bloqueio)

Um jeito de declarar a intenção de modificar exclusivamente um arquivo ou diretório. Por exemplo, "Não consigo commitar nenhuma mudança para as páginas web no momento. Parace que Alfred as bloqueou enquanto conserta as imagens de fundo." Nem todos os sistemas de controle de versão suportam a habilidade de bloquear, e daqueles que suportam, nem todos requerem que a habilidade seja usada. Isso se dá porque desenvolvimento paralelo é a regra, e bloquear pessoas de acessar um arquivo é contrário à este ideal.

Sistemas de controle de versão que requerem o bloqueio para realizar commits usam um modelo chamado bloquear-modificar-desbloquear. Aqueles que não requerem usam o modelo chamado copiar-modificar-juntar. Uma excelente explicação e comparação dos dois modelos à fundo pode ser encontrada em http://svnbook.red-bean.com/svnbook-1.0/ch02s02.html. No geral, o modelo copiar-modificar-juntar é melhor para desenvolvimento aberto, e todos os sistema de controle de versão discutidos neste livro suportam este modelo.

Escolhendo o sistema de Controle de Versão

Os dois sistemas de Controle de Versão mais populares no momento que este livro foi escrito no mundo do software livre são Concurrent Versions System (CVS, http://www.cvshome.org/) e Subversion (SVN, http://subversion.tigris.org/).

O CVS existe há um bom tempo. Desenvolvedores mais experientes já estão familiarizados com ele, que faz mais ou menos o que você precisa, e como ele já é popular há um bom tempo, você provavelmente não vai entrar em longas discussões se ele é ou não a escolha correta. Porém, o CVS possui algumas desvantagens. Ele não fornece uma maneira fácil de encontrar mudanças em diversos arquivos; ele não permite que você renomeie ou copia arquivos sob o controle de versão (o que faz com que uma reorganização em sua árvore de código após iniciar o projeto te dê uma bela dor de cabeça); tem um suporte pobre a merge; ele não lida muito bem com arquivos grandes ou com arquivos binários; e algumas operações são lentas quando se tem um grande número de arquivos.

Nenhuma das falhas do CVS é fatal, e ele ainda é bem popular. Porém, nos últimos anos o mais recente Subversion vem ganhando espaço especialmente para novos projetos .[17]. Se você está iniciando um novo projeto, eu recomento o Subversion.

Por outro lado, como eu estou envolvido no projeto do Subversion, minha objetividade pode ser razoalvelmente questionável. E nos últimos anos diversos novos softwares livres de controle de versão surgiram. Apêndice A, Sistemas de Controle de Versão Livres lista todos os que eu conheço, em uma ordem rudimentar de popularidade. Conforme a lista deixa claro, decidir o sistema de controle de versào pode ser uma pesquisa de uma vida inteira. Possiverlmente você será poupado da decisão pois será decidido por você no lugar que você for armazenar seu software. Mas se você for obrigado a decidir, pergunte aos seus outros desenvolvedores, descubra no que eles possuem maior experiência, escolha um e siga com ele. Qualquer software de controle de versão estável, pronto para produção, irá servir; você não precisa se preocupar demais sobre fazer uma escolha drásticamente errada. Se você simplesmente não conseguir decidir, então fique com o Subversion. Ele é bem simples de aprender, e provavelmente será o padrão por pelo menos alguns anos.

Usando o Sistema de Controle de Versão

The recommendations in this section are not targeted toward a particular version control system, and should be simple to implement in any of them. Consult your specific system's documentation for details.

Version everything

Keep not only your project's source code under version control, but also its web pages, documentation, FAQ, design notes, and anything else that people might want to edit. Keep them right next to the source code, in the same repository tree. Any piece of information worth writing down is worth versioning—that is, any piece of information that could change. Things that don't change should be archived, not versioned. For example, an email, once posted, does not change; therefore, versioning it wouldn't make sense (unless it becomes part of some larger, evolving document).

The reason versioning everything together in one place is important is so people only have to learn one mechanism for submitting changes. Often a contributor will start out making edits to the web pages or documentation, and move to small code contributions later, for example. When the project uses the same system for all kinds of submissions, people only have to learn the ropes once. Versioning everything together also means that new features can be committed together with their documentation updates, that branching the code will branch the documentation too, etc.

Don't keep generated files under version control. They are not truly editable data, since they are produced programmatically from other files. For example, some build systems create configure based on the template configure.in. To make a change to the configure, one would edit configure.in and then regenerate; thus, only the template configure.in is an "editable file." Just version the templates—if you version the result files as well, people will inevitably forget to regenerate when they commit a change to a template, and the resulting inconsistencies will cause no end of confusion.[18]

The rule that all editable data should be kept under version control has one unfortunate exception: the bug tracker. Bug databases hold plenty of editable data, but for technical reasons generally cannot store that data in the main version control system. (Some trackers have primitive versioning features of their own, however, independent of the project's main repository.)

Browsability

The project's repository should be browsable on the Web. This means not only the ability to see the latest revisions of the project's files, but to go back in time and look at earlier revisions, view the differences between revisions, read log messages for selected changes, etc.

Browsability is important because it is a lightweight portal to project data. If the repository cannot be viewed through a web browser, then someone wanting to inspect a particular file (say, to see if a certain bugfix had made it into the code) would first have to install version control client software locally, which could turn their simple query from a two-minute task into a half-hour or longer task.

Browsability also implies canonical URLs for viewing specific revisions of files, and for viewing the latest revision at any given time. This can be very useful in technical discussions or when pointing people to documentation. For example, instead of saying "For tips on debugging the server, see the www/hacking.html file in your working copy," one can say "For tips on debugging the server, see http://subversion.apache.org/docs/community-guide/," giving a URL that always points to the latest revision of the hacking.html file. The URL is better because it is completely unambiguous, and avoids the question of whether the addressee has an up-to-date working copy.

Some version control systems come with built-in repository-browsing mechanisms, while others rely on third-party tools to do it. Three such tools are ViewCVS (http://viewcvs.sourceforge.net/), CVSWeb (http://www.freebsd.org/projects/cvsweb.html), and WebSVN (http://websvn.tigris.org/). The first works with both CVS and Subversion, the second with CVS only, and the third with Subversion only.

Commit emails

Every commit to the repository should generate an email showing who made the change, when they made it, what files and directories changed, and how they changed. The email should go to a special mailing list devoted to commit emails, separate from the mailing lists to which humans post. Developers and other interested parties should be encouraged to subscribe to the commits list, as it is the most effective way to keep up with what's happening in the project at the code level. Aside from the obvious technical benefits of peer review (see “Pratique uma Revisão de Código Visível”), commit emails help create a sense of community, because they establish a shared environment in which people can react to events (commits) that they know are visible to others as well.

The specifics of setting up commit emails will vary depending on your version control system, but usually there's a script or other packaged facility for doing it. If you're having trouble finding it, try looking for documentation on hooks, specifically a post-commit hook, also called the loginfo hook in CVS. Post-commit hooks are a general means of launching automated tasks in response to commits. The hook is triggered by an individual commit, is fed all the information about that commit, and is then free to use that information to do anything—for example, to send out an email.

With pre-packaged commit email systems, you may want to modify some of the default behaviors:

  1. Some commit mailers don't include the actual diffs in the email, but instead provide a URL to view the change on the web using the repository browsing system. While it's good to provide the URL, so the change can be referred to later, it is also very important that the commit email include the diffs themselves. Reading email is already part of people's routine, so if the content of the change is visible right there in the commit email, developers will review the commit on the spot, without leaving their mail reader. If they have to click on a URL to review the change, most won't do it, because that requires a new action instead of a continuation of what they were already doing. Furthermore, if the reviewer wants to ask something about the change, it's vastly easier to hit reply-with-text and simply annotate the quoted diff than it is to visit a web page and laboriously cut-and-paste parts of the diff from web browser to email client.

    (Of course, if the diff is huge, such as when a large body of new code has been added to the repository, then it makes sense to omit the diff and offer only the URL. Most commit mailers can do this kind of limiting automatically. If yours can't, then it's still better to include diffs, and live with the occasional huge email, than to leave the diffs off entirely. Convenient reviewing and commenting is a cornerstone of cooperative development, much too important to do without.)

  2. The commit emails should set their Reply-to header to the regular development list, not the commit email list. That is, when someone reviews a commit and writes a response, their response should be automatically directed toward the human development list, where technical issues are normally discussed. There are a few reasons for this. First, you want to keep all technical discussion on one list, because that's where people expect it to happen, and because that way there's only one archive to search. Second, there might be interested parties not subscribed to the commit email list. Third, the commit email list advertises itself as a service for watching commits, not for watching commits and occasional technical discussions. Those who subscribed to the commit email list did not sign up for anything but commit emails; sending them other material via that list would violate an implicit contract. Fourth, people often write programs that read the commit email list and process the results (for display on a web page, for example). Those programs are prepared to handle consistently-formatted commit emails, but not inconsistent human-written mails.

    Note that this advice to set Reply-to does not contradict the recommendations in “O Longo Debate do Responder a” earlier in this chapter. It's always okay for the sender of a message to set Reply-to. In this case, the sender is the version control system itself, and it sets Reply-to in order to indicate that the appropriate place for replies is the development mailing list, not the commit list.

Use branches to avoid bottlenecks

Non-expert version control users are sometimes a bit afraid of branching and merging. This is probably a side effect of CVS's popularity: CVS's interface for branching and merging is somewhat counterintuitive, so many people have learned to avoid those operations entirely.

If you are among those people, resolve right now to conquer any fears you may have and take the time to learn how to do branching and merging. They are not difficult operations, once you get used to them, and they become increasingly important as a project acquires more developers.

Branches are valuable because they turn a scarce resource—working room in the project's code—into an abundant one. Normally, all developers work together in the same sandbox, constructing the same castle. When someone wants to add a new drawbridge, but can't convince everyone else that it would be an improvement, branching makes it possible for her to go to an isolated corner and try it out. If the effort succeeds, she can invite the other developers to examine the result. If everyone agrees that the result is good, they can tell the version control system to move ("merge") the drawbridge from the branch castle over to the main castle.

It's easy to see how this ability helps collaborative development. People need the freedom to try new things without feeling like they're interfering with others' work. Equally importantly, there are times when code needs to be isolated from the usual development churn, in order to get a bug fixed or a release stabilized (see “Stabilizing a Release” and “Maintaining Multiple Release Lines” in Capítulo 7, Packaging, Releasing, and Daily Development) without worrying about tracking a moving target.

Use branches liberally, and encourage others to use them. But also make sure that a given branch is only active for exactly as long as needed. Every active branch is a slight drain on the community's attention. Even those who are not working in a branch still maintain a peripheral awareness of what's going on in it. Such awareness is desirable, of course, and commit emails should be sent out for branch commits just as for any other commit. But branches should not become a mechanism for dividing the development community. With rare exceptions, the eventual goal of most branches should be to merge their changes back into the main line and disappear.

Singularidade de Informação

Merging tem um corolário importante: nunca comite a mesma mudança duas vezes. Isto é, uma mudança deve entrar no sistema de controle de versionamento exatamente uma única vez. A revisão (ou conjunto de revisões) na qual a mudança foi efetuada é o seu único identificador. Caso seja necessária a sua efetuação em uma branch diferente da que foi feita, então ela deve ser merged do seu ponto de criação original para os outros pontos de destino —ao contrário de comitar uma mudança textualmente idêntica, que teria o mesmo efeito no código, mas tornaria impossíveis a precisão de estruturação e o gerenciamento de releases.

Os efeitos práticos desta recomendação variam de um sistema de controle de versão para o outro. Em alguns sistemas, merges são eventos especiais, distintos de commits, e têm seus proprios metadados. Em outros, os resultados de merges são comitados da mesma forma que outras mudanças são comitadas, então o principal modo de diferenciar um "merge commit" de um "commit de novas mudanças" é a log message. Na log message de um merge, não repita a mesma existente na mudança original. Ao contrário, apenas indique que está sendo realizado um merge, e forneça a revisão que contenha a mudança original, com um sumário de no máximo uma frase do que ela faz. Se alguém quiser ler a mensagem completa, deverá então consultar a revisão original.

A razão da importância de se evitar a repetição da log message é que, às vezes, elas são modificadas após serem comitadas. Se a log message de uma mudança fosse repetida a cada efetuação de merge, então até se alguém editasse a mensagem original, ainda seria necessário atualizar todas as repetições—o que causaria um monte de confusão.

O mesmo princípio se aplica para reverter uma mudança. Se uma mudança é retirada do código, a log message da reversão deve apenas indicar, especificamente, qual é a revisão (ou revisões) que está sendo revertida, e não descrever a mudança gerada no arquivo derivada da reversão, uma vez que a semântica da mudança pode ser obtida através da leitura da log message original. É claro que a log message da reversão deve indificar a razão pela qual a mudança está sendo revertida, mas ela não deve conter duplicações derivadas da log message original. Se possível, volte e edite a log message original para evidenciar o que foi revertido.

Tudo dito acima significa que você deve usar uma sintaxe consistente quando se referir a revisões. Isto é útil não somente em log messages, mas também em emails, no bug tracker, e em todos os outros lugares. Se você está usando CVS, sugiro "path/to/file/in/project/tree:REV", onde REV é um número de revisão no CVS, como "1.76". Se você está usando Subversion, a sintaxe padrão para a revisão 1729 é "r1729" (endereços de arquivos não são necessários por que o Subversion usa números de revisão globais). Em outros sistemas, normalmente há uma sintaxe padrão para expressar o nome das alterações. Seja qual for a sintaxe apropriada para o seu sistema, estimule as pessoas a usá-la quando forem aplicar mudanças. Uma nomeação de mudanças consistente facilita a estruturação do projeto (como veremos em Capítulo 6, Communications e Capítulo 7, Packaging, Releasing, and Daily Development), e como muita da estruturação será feita por voluntários, se torna necessário deixá-la o simples possível.

Veja também “Releases and Daily Development” em Capítulo 7, Packaging, Releasing, and Daily Development.

Autorização

A maioria dos sistemas de controle de versão oferecem uma funcionalidade para que certas pessoas sejam autorizadas ou não a comitar em sub-áreas do repositório. Seguindo o princípio de que quando na posse de um martelo as pessoas começam a procurar por pregos, muitos projetos usam esta funcionalidade com vigor, garantindo cuidadosamente acesso às pessoas apenas para as áreas as quais foram aprovadas a comitar, e certificando-se de que elas não podem comitar em nenhum outro lugar. (Veja “Committers” em Capítulo 8, Managing Volunteers para ver como é decidido quem pode comitar aonde.)

Provavelmente poucos danos ocorrerão com o uso de um controle tão rigoroso, no entanto uma política mais descontraída também é aceita. Alguns projetos simplesmente usam um sistema de honra: quando uma pessoa é autorizada a comitar, até para uma sub-área do repositório, o que ela recebe, na verdade, é uma senha que a possibilita comitar em qualquer lugar do projeto. Só lhe é pedido que mantenha os seus commits na área determinada. Lembre-se que na verdade não há nenhum risco aqui: em um projeto ativo, todos os commits são revisados, de qualquer modo. Se alguém ver um commit onde não deveria estar, isto será percebido e então será falado algo. Se uma mudança precisar ser desfeita, isto é muito simples —tudo está sob versionamento de controle mesmo, então é só reverter.

Existem diversas vantagens à abordagem mais descontraída. Primeiro, como desenvolvedores evoluem para outras áreas (o que provavelmente acontecerá caso eles continuem no projeto), não haverá sobrecarga administrativa para garantir maiores privilégios. Uma vez tomada a decisão, a pessoa pode começar a comitar na nova área imediatamente.

Em segundo lugar, a expansão pode ser feita de um modo mais refinado. Geralmente, um committer na área X que quer evoluir para a área Y começará a enviar patches para a área Y e pedir por review. Se alguém que já tem permissão a commits na área Y ver o patch e aprová-lo, eles podem avisar a quem o enviou para comitá-lo diretamente (mencionando o nome de quem revisou/aprovou na log message, obviamente). Deste modo, o commit virá diretamente da pessoa que fez a mudança, o que é preferível tanto de um ponto de vista gerencial quanto de um ponto de vista de creditação justa.

Por último, e talvez a mais importante, usar o sistema de honra estimula uma atmosfera de confiança e respeito mútuo. Dar permissão de commit à alguém para um subdomínio é uma confirmação feita sobre o preparamento técnico desta pessoa —isto quer dizer: "Nós vemos que você tem proficiência para comitar em uma certa parte do projeto, então vá fundo." No entanto, impor um controle rígido de autorização diz: "Não apenas estamos impondo um limite sobre a sua proficiência, como também estamos um pouco suspeitos das suas intenções." Isto não é algo que você quer dizer se você puder evitar. Trazer alguém para o projeto como um committer é uma oportunidade de iniciá-los em um círculo de confiança. Uma boa maneira de fazer isto é dar mais poder à esta pessoa do que ela deveria ter, e então informá-la que cabe à ela continuar ou não nestes limites.

O projeto Subversion tem operado através sistema de honra há mais de quatro anos, com 33 committers integrais e 43 committers parciais até o tempo de escrita deste livro. A única distinção que o sistema realmente impõe é a entre committers e não-committers; subdivisões adicionais são mantidas apenas por humanos. Ainda assim, nós nunca tivemos problemas com alguém deliberadamente comitar algo fora do seu domínio. Uma ou duas vezes já aconteceram inocentes mal-entendidos sobre o grau de privilégios de commit de alguém, mas tudo sempre foi resolvido de forma rápida e amigável.

Obviamente, em situações onde auto-policiamento é impraticável, você deve contar com controles de autorização rígidos. Mas tais situação são raras. Até quando existem milhões de linhas de código e centenas ou milhares de desenvolvedores, um commit feito a algum módulo deverá ser revisado por quem trabalha neste mesmo módulo, e então pode-se reconhecer caso alguém tenha feito um commit onde não deveria. Se revisões de commit não estão acontecendo frequentemente, então o projeto tem problemas maiores do que lidar com o sistema de autorização.

Em resumo, não perca muito tempo mexendo com o sistema de autorização do controlador de versões, a não ser que você tenha uma razão específica para tal. Isto normalmente não traz benefícios perceptíveis, e existem vantagens em, ao invés disto, confiar em controles humanos.

É claro que nada disto deve ser interpretado de modo que pareça que as restrições, especificamente, não tenham importância nenhuma. Seria muito ruim para um projeto estimular pessoas a comitarem em áreas nas quais não são qualificadas. Além do mais, em muitos projetos, permissão de commit integral (sem restrições) tem um destaque especial: implica em direito de voto em questões de alto nível, que afetam todo o projeto. Este aspecto político de commit é mais discutido em “Who Votes?” em Capítulo 4, Social and Political Infrastructure.



[18] For a different opinion on the question of versioning configure files, see Alexey Makhotkin's post "configure.in and version control" at http://versioncontrolblog.com/2007/01/08/configurein-and-version-control/.