GIT: Controle de Versões Distribuído para Projetos de Software
Publicado em 11 de fevereiro de 2010 por Gleudson Junior
1. Introdução a VCS/SCM
Os sistemas de controle de versão, mais comumente
chamados de VCS* ou mesmo SCM** funcionam como aplicativos
computacionais responsáveis pelo controle e gerenciamento de diferentes versões
na implementação de um determinado documento. Na sua grande maioria esses
sistemas são implantados com a finalidade de controlar e gerenciar o
desenvolvimento de projetos de software, proporcionando a manutenção das suas
versões, de um histórico e desenvolvimento dos códigos fontes e
conseqüentemente da documentação de todo o projeto.
Esse tipo
de ferramenta se mostra bastante presente em organizações e empresas de âmbito
tecnológico e de desenvolvimento de projetos de software, sendo também bastante
utilizado para o desenvolvimento de ferramentas Open Source (Código Aberto). Sua utilidade pode ser
denotada por diversos aspectos, seja ele para pequenos projetos, como também
para projetos de maior escala comercial.
Existem
vários sistemas que propõe estas funcionabilidades, entre os mais conhecidos e
utilizados em diversos projetos, encontram-se: CVS, ou Concurrent Version
System (Sistema de Versões Concorrentes)
e o SVN, mais conhecido como Subversion, esses dois últimos no ambiente livre,
na outra ponta podemos citar sistemas comerciais como: Clearcase da IBM ou o SourceSafe
da Microsoft. A grande maioria dos projetos de desenvolvimento de softwares
livre, optam pelo Subversion que é a evolução do inveterado CVS, no entanto
podemos citar uma exceção a essa “regra”, que é a ferramenta chamada Bitkeeper,
que apesar de ser comercial, foi por muito tempo utilizado para o gerenciamento
e controle de versões do Kernel Linux, até o surgimento do GIT. Muitas
organizações comerciais também utilizam o SVN, apesar de algumas dessas
empresas preferirem realmente uma solução paga, daí partem em optar pelos produtos
mencionados acima. A escolha por empregar uma solução comercial comumente se dá
por questões de garantias, visto que as soluções livres não se responsabilizam
por bugs, erros ou perdas de informações no software, em contra partida podemos
elevar as melhores condições de empregabilidade, segurança e desempenho das
ferramentas livres.
Todos os
caminhos que nos levam ao emprego de um sistema de controle de versão são
comprovados pela sua eficácia e por estes fazerem parte dos principais
requisitos para a manutenção e aprimoramento dos processos que envolvem um
projeto de software, tanto quando sua ligação com processos de certificações
como o SPICE*** e o CMMI****, que tendem a garantir um
modelo unificado para os processos de nível corporativo.
Os
principais proveitos em se empregar um sistema de controle de versão para
monitorar as alterações realizadas durante as implementações de um determinado
software são: controle e gerenciamento de históricos de alterações;
identificação e restauração de versões estabilizadas; ramificações que ajudam
na divisão do projeto, facilitando assim o trabalho de desenvolvimento em
paralelo e principalmente o sincronismo oferecido para a equipe de trabalho.
* VCS: acrônimo
de Version Control System
** SCM: acrônimo
de Source Code Management
*** SPICE: acrônimo
de Simulated Program whit Integrated
Circuits Emphasis
**** CMMI: acrônimo
de Capability Maturity Model Integration
2. Entendendo seu funcionamento
Para entendermos os itens três e quatro deste
artigo, precisamos primeiro nos debruçar no que diz respeito ao funcionamento
de um sistema de controle de versão, ou seja, devemos explanar os conceitos
básicos relacionados ao modelo apresentado.
O controle de versionamento é basicamente dividido em dois segmentos: o repositório, que é responsável pelo armazenamento das informações e a área de trabalho (Desktop). O repositório como havia descrito acima, é responsável pelo armazenamento das informações relacionadas ao projeto, em modo persistente no sistema de arquivo escolhido, ou até mesmo em um banco de dados. Nele será guardado todo o histórico de desenvolvimento do projeto e registrado também qualquer tipo de modificação realizada nos arquivos nele alocados.
O responsável
pelo desenvolvimento do documento nunca trabalha diretamente nos arquivos do
repositório, ele deve antes obter em sua área de trabalho uma cópia local,
também chamada de cópia de trabalho (Working
Copy) que contém a copia da ultima versão de cada arquivo do projeto e esta
deverá ser monitorada para identificar qualquer tipo de alteração realizada.
Essa área geralmente fica isolada das demais. A comunicação e sincronização
entre o repositório e a área de trabalho se dão por duas operações distintas: commit e update, como demonstrado na figura abaixo:
Figura 1: topologia básica de um sistema para controle de
versão.
O commit
é responsável por submeter um pacote contendo uma ou mais modificações realizadas
durante o desenvolvimento na área de trabalho que é a origem, para seu destino
que é o repositório. O update por sua vez faz o trabalho proporcionalmente
inverso, isto é, ele envia uma cópia de trabalho da ultima versão estável
contida no repositório para a área de trabalho do desenvolvedor.
Cada
operação de commit gera uma nova revisão no repositório, registrando sempre
todas as modificações realizadas, data e autor. Criando uma alusão a operação,
é como se uma revisão fosse uma “fotografia” de todos os arquivos e diretórios
em um determinado tempo da evolução do projeto. Essas “fotografias” de tempos
passados são armazenadas no repositório e podem ser analisadas ou restauradas
sempre que for desejado e o conjunto dessas revisões é justamente o que chamamos
de histórico do projeto.
Podemos
subdividir o sistema de controle de versão basicamente em dois tipos, de acordo
com a maneira que cada um deles garante o controle e o gerenciamento do seu
repositório: centralizado e distribuído. Nos CVS centralizados as mudanças são
feitas para um repositório central e único, ao contrário dos distribuídos, onde
os desenvolvedores trabalham diretamente no próprio repositório.
Então
agora podemos dizer que, tanto o controle de versionamento centralizado quanto
o distribuído basicamente funcionam sob os repositórios e as áreas de trabalho.
A distinção está justamente em como cada uma dessas revisões estão adornadas no
processo como um todo.
3. Controle de versionamento centralizado
Os sistemas de controle de versão
centralizados, apesar de possuírem um processo de funcionamento bem mais
simples que os distribuídos, proporcionam algumas vantagens relevantes em
relação aos modelos distribuídos, várias dessas se referem justamente pela sua
simplicidade e facilidade em centralizar, controlar e gerenciar os dados
alocados em único repositório central.
Como
especificado no próprio termo, os sistemas de controle de versão centralizados mantém
as informações relativas aos arquivos em um repositório central, acessível a todos
os desenvolvedores do projeto. Não é nada incomum ouvir-se dizer que esse
modelo centralizado é uma arquitetura cliente/servidor.
Nota: o acesso dos desenvolvedores do projeto em relação
aos dados do repositório deve responder as normas de segurança impostas ao
sistema.
Em um
sistema de controle de versão centralizado, cada colaborador (desenvolvedor) do projeto mantém uma cópia
dos arquivos alocados no repositório central, além de armazenar alguns metadados*. No momento em que se efetua
uma alteração em qualquer arquivo do projeto, o desenvolvedor faz uma
atualização desses arquivos no repositório, tornando públicas suas mudanças.
Esse processo se dá por um comando conhecido como commit.
Um dos
pontos culminantes que se deve ressaltar em um modelo de controle centralizado,
é a facilidade de se controlar o acesso aos arquivos de um determinado projeto,
devido ao fato de as informações encontrarem-se reunidas em apenas um único
repositório central.
Figura 2: modelo de controle de versão centralizado.
Também
por conta da simplicidade de implementação desse modelo, os VCS centralizados
apresentam algumas desvantagem em relação aos distribuídos, fazendo com que se
tornem notoriamente pouco referenciados para implantação em ambientes de
desenvolvimento com maior nível de complexidade, ou ainda quando os
colaboradores se vêem “ilhados” geograficamente e não contam com uma conexão
estável e direta com o repositório central. Dessa forma pode-se dizer que o
modelo centralizado é extremamente dependente do repositório central onde estão
alocados todos os dados referentes ao projeto, de tal maneira que um
desenvolvedor nunca poderá obter qualquer informação de arquivos sem que este
esteja alocado no repositório central e passível de acesso através de uma conexão
direta, apesar de que esta restrição não impede que o desenvolvedor continue
editando os arquivos.
Embora
seja bastante vantajoso manter um único repositório por questões que envolvem a
segurança do controle de acesso ao mesmo, isto pode se tornar um grande
problema quando não existe uma política segura e confiável de backups. É
interessante dizer que a escolha da melhor política de backup para um
repositório de dados, é variável de acordo com a maneira que o VCS aloca os
arquivos e seus metadados, isso se dá pelo fato de alguns VCS se utilizarem de
uma arvore de arquivos lógicos ordenados para manter suas informações, quando
outros tendem a adotar um banco de dados para tal fim.
* Metadados: dados
sobre outros dados, relacionados a esses arquivos, que serve para equiparar com
as informações já existentes no repositório.
4. Controle de versionamento distribuído
Proporcionalmente inverso aos
sistemas de controle de versões centralizados, os VCS distribuídos, também
chamado de DVCS* tem uma arquitetura
muito mais complexa e até um tanto quanto complicada para compreensão de
iniciantes, em contra partida nos apresenta uma série de vantagens que não são
possíveis de aplicar ao modelo centralizado.
Dando
vista ao processo no âmbito operacional, um DVCS não é muito desigual a um VCS
centralizado, pois os desenvolvedores de um determinado projeto também fazem
commit de suas alterações durante o desenvolvimento dos arquivos, da mesma
forma quem geram tarballs, patches, atualizam seus arquivos ou analisam seu
histórico de alteração.
A grande
sacada do modelo distribuído está no fato de não haver um único repositório
centralizado, mas sim diversos repositórios espalhados na rede e um repositório
para cada desenvolvedor, sob a dependência da ferramenta que está sendo
utilizada pelo projeto. Desta maneira, por exemplo, pode-se fazer com que os
repositórios “filhos” de um mesmo repositório “pai” compartilhem suas
alterações paralelamente entre si.
Em um
sistema de controle distribuído, uma conexão permanente com o servidor não é um
requisito essencial para o funcionamento do sistema, visto que cada
desenvolvedor é responsável por manter seu próprio repositório, dessa forma
todas as alterações feitas no longo do desenvolvimento podem passar por um
commit local e então somente quando necessário ou solicitado, devem atingir o
repositório “pai”, ou paralelos a ele, caso exista algum. Incrementado a esse
contexto, o “pai” destes repositórios “filhos” podem realizar um commit destas
mudanças, no seu repositório “pai, tornando com que suas modificações se tornem
públicas para os demais membros do conjunto de repositórios.
Figura 3: modelo de controle de versão distribuído
Organizar
e acessar os repositórios desta maneira torna os DCVS totalmente aplicáveis
para equipes de trabalho que estão geograficamente espalhados pelo mundo, ao
qual nem sempre possuem uma conexão estável entre os colaboradores do projeto.
Porém isso não quer dizer que uma conexão de rede, ou ao menos uma forma de
disseminar estas mudanças não seja importante para o funcionamento de DCVS,
acontece que quando um desenvolvedor utiliza um sistema de controle distribuído
ele pode ter acesso às informações do repositório “pai”, mesmo que não exista uma
conexão com o mesmo. No entanto estas informações dizem respeito à última
sincronização do repositório local, com o repositório paralelo ou o repositório
“pai”. Além do mais, o fato de ser distribuído não impede necessariamente que o
repositório “filho” replique suas alterações para o repositório “pai”, pois se
isso não acontecesse, as suas modificações não seriam reproduzidas para os
demais colaboradores do projeto.
Podemos
citar como um exemplo semelhante de utilização e complexidade desse modelo, as
trocas (downloads e uploads) de
arquivos na plataforma p2p, onde se torna um pouco mais difícil o controle
sobre o acesso aos dados existentes em um determinado repositório. A partir
disso é que vem a procura e empregabilidade de algumas ferramentas que possuem
funcionabilidades específicas capazes de solucionar este tipo de problema.
* DVCS: acrônimo de Distributed Version Control Systems
5. Introdução ao Git
Enquadrada a um sistema de controle
de versão distribuído (DVCS) podemos
encontrar uma aplicação bastante eficiente, que tende a propor diversos recursos
a fim de sanar os problemas supracitados, estamos falando do projeto Git.
Ele é um
projeto de Software Livre, liberado sob a licença GPL*, que foi inicialmente criado por Linus Torvalds**, visando o controle e desenvolvimento dos códigos fontes
do Kernel Linux, hoje ele é mantido por Junio Hamano. O grande objetivo do Git é
atender a todas as exigências do modelo de desenvolvimento do Kernel Linux,
tais como manipulação de grandes conjuntos de arquivos, desenvolvimento de
projeto distribuído, operação de ramificações e mesclagens (merges) complexas, integridade do
código, desempenho, entre outras.
Cada
diretório local de desenvolvimento Git é tido como um repositório, onde se
encontra todo histórico de desenvolvimento dos commits locais e a capacidade de
controle das revisões do código, tudo isso sem a dependência de um acesso
direto a uma rede ou a um único servidor central.
O desenho
inicial do Git foi inspirado por outras duas aplicações de controle de versão:
o Bitkeeper, e o Monotone. Seu
projeto original possuía uma arquitetura com um mecanismo de funcionamento
bastante abstrato, difícil para a compreensão de desenvolvedores iniciantes. Com
a evolução e a aparição de novas necessidades, o projeto original acabou se
tornando em um sistema de controle de versão completo, que passou a ser adotado
por empresas de alto nível.
São
inúmeros projetos de software que hoje empregam o Git para o controle de versão
de código, podendo citar como principais exemplos: Android, Btrfs da Oracle,
Gnome, Google, Kernel Linux, Perl, Qt (toolkit),
Ruby on Rails, Samba, Servidor X.org.
* GPL: acrônimo
de Gnu General Public license
** Linus Torvalds: criador
do kernel Linux
6. Por que o Git?
É totalmente indiscutível que todo
projeto de software independente do seu tamanho ou complexidade, necessita hoje
de um sistema para versionamento de código. Isso não é mais uma questão de
escolha. No momento em que se inicia um projeto de software, mesmo que este
esteja sendo manipulado por apenas um desenvolvedor, o controle de versões
passa a não ser uma tarefa de teor trivial, ou algo que se possa considerar opcional.
Daí é que
surge o grande problema da maioria dos projetos de software: qual VCS utilizar?
Grande parte dos desenvolvedores se vê hoje mal acostumados com a utilização e
manipulação do CVS, Subversion ou mesmo o SourceSafe da Microsoft. É bem
verdade que alguns deles atendem aos requisitos de determinados projetos de
forma aceitável, nem sempre satisfatória, mas felizmente hoje podemos contar
com ferramentas que oferecem funcionabilidades bem mais evoluídas nesse âmbito.
O Linus
Torvalds, por exemplo, sofria desse mal: como controlar uma gama enorme de
colaborações provenientes de todo o mundo? Nos primórdios a maneira de controle
dos códigos se constituía num processo manual, onde se testava e implantava
manualmente retalhos de código, mas isso com o passar do tempo tendia a se
tornar impraticável, por questões que envolviam o grande esforço de trabalho dos
envolvidos no projeto. Quando ele sentiu a necessidade de empregar um sistema
para controlar os códigos do núcleo Linux, decidiu de pronto não utilizar nem o
CVS, nem o Subversion, por limitações já descritas. Então optou pelo Bitkeeper,
que apesar de ser comercial, se enquadrava perfeitamente as necessidades do
projeto. No entanto, como explicar e principalmente motivar a comunidade de um
software livre a utilizar um aplicativo comercial? Perante essas dificuldades,
decidiu então desenvolver seu próprio sistema para controle de versões, optando
pelo modelo distribuído, daí nasceu o Git.
“Ser distribuído significa que você não tem uma
localização central que se mantém a par de seus dados, um único lugar, mais
importante que qualquer outro lugar. Este modelo centralizado não funciona...”.
Linus
Torvalds – Palestra ministrada sobre o Git no Tech Talk Google.
Nos
sistemas de controle distribuídos (item quatro),
cada colaborador do projeto obtém em sua máquina local um clone completo do
repositório principal. O que difere o Git das demais ferramentas, é justamente
a grande escala de otimização desse repositório. Um dos exemplos clássicos
dessa otimização, é o que acontece com alguns projetos, onde a última revisão
de código é apenas um pouco maior que todo o código armazenado no repositório,
incluindo atualizações e modificações.
A grande
jogada está na estrutura desse sistema, onde todo o repositório encontra-se
armazenado localmente, como isso o desenvolvedor não tem nenhum problema com
permissões de escrita. Está tudo armazenado localmente na sua estação de
trabalho. Alem da possibilidade de trabalhar no desenvolvimento do projeto em
modo off-line, sem necessitar de um acesso a rede nem internet, gerando assim
maior comodidade e mobilidade aos colaboradores.
No Git
cada desenvolvedor tem o repositório completo em sua estação de trabalho, que
também é conhecido como “repositório central”, mas que na verdade é apenas um
dos clones que foi eleito como “repositório principal” e que caso sofra uma
perda irreversível, deve ser substituído por qualquer um desses outros
repositórios. Isso mantém viva a arquitetura distribuída do desenvolvimento do
software, onde se garante que qualquer um dos repositórios clonados possa ser
eleito como “repositório principal”
O que
acontece é que ao invés de se fazer um “checkout” e copiar o topo do projeto, o
Git permite fazer um “clone” e obter uma cópia completa do repositório. Fazendo
com que cada desenvolvedor tenha todo o repositório em sua máquina local e
possibilitando a sua substituição caso haja alguma perda de informação.
7. Utilização Básica do Git
7.1 Instalando
Para instalar o Git no terminal de
trabalho, basta digitar no terminal do Sistema Operacional o comando abaixo:
# sudo apt-get install git-core
Obs.: o
comando acima deve ser aplicado para distribuições Debian/Linux. Caso possua
outra distribuição instalada, acesse: http://code.google.com/p/msysgit/downloads/list
para baixar e instala a versão mais recente.
7.2 Iniciando o repositório
Nesse momento deve-se criar o
diretório em que será iniciado o projeto, em seguida iniciar verdadeiramente o
repositório Git no diretório.
# mkdir
novo_projeto
# cd
novo_projeto
# git
init
7.3 Trabalhando no repositório
Git
Sempre que for necessário adicionar
um novo arquivo no repositório devem-se utilizar os seguintes comandos:
# touch
novo_arquivo.sh
# git add
novo_arquivo.sh
# git
commit –m ‘novo_arquivo.sh adicionado no repositório”
O Git
possui o que chamamos de “área intermediária”. Nesta área será permitido
configurar o modo em que o commit vai ficar antes de enviá-lo ao repositório.
Com isso você pode utilizar os comandos: add
e rm que são responsáveis pela
adição e remoção de arquivos e diretórios. Depois será apenas necessário utilizar
o comando commit para enviar as alterações para o repositório local.
Nota: deve-se atentar bastante na utilização do comando
rm. Se caso ele for utilizado sem o parâmetro -cached o arquivo será removido
sumariamente do repositório.
7.4 Submetendo as modificações
para o repositório
De acordo com a arquitetura
distribuída do Git, ainda é necessário que as modificações realizadas no braço
local sejam submetidas para o repositório remoto, onde outros desenvolvedores
terão acesso. Para tanto se deve utilizar o seguinte comando:
# git
push orign master
Onde, o
parâmetro orign é o nome do
repositório remoto e master é o nome
do branch. Para adicionar o repositório remoto basta utilizar o comando:
# git remote add orign usuario@meu_repositorio.com.br:/home/usuario/repositorio.git
7.5 Clonando um repositório remoto
Para
obter um clone do repositório remoto deve-se utilizar o comando:
# git clone usuario@meu_repositorio.com.br:/home/usuario/repositorio.git
8. Conclusão
Este
artigo nos motiva a acreditar que, uma vez que tenha escolhido um determinado
sistema de controle de versão, cuidadosamente estudado e preparado para seu projeto,
este pode e deve ser de grande valia para o aumento da produtividade e
melhorias no gerenciamento e controle dos arquivos. No entanto, é importante
salientar que para haver uma escolha correta do sistema de controle que se
encaixe perfeitamente ao contexto do problema, é necessário obter conhecimento
das características técnicas, funcionabilidades, desempenho, vantagens e
desvantagens de cada ferramenta disponível, dessa forma sendo possível
sinalizar quais dessas características são mais relevantes para suprir as
necessidades.
Foi
justamente isso que se tentou mostrar neste documento. A indicação e o emprego
do Git, uma ferramenta que atende de forma eficiente e satisfatória os
requisitos relacionados ao controle dos códigos fonte para sistemas
distribuídos, sendo totalmente aplicável em grande parte dos projetos atuais.
9. Referências
[1]
Wikipédia (CVS):
http://pt.wikipedia.org/wiki/Cvs
(Acessado
em 03/12/2009)
[2]
Introdução a Controle de Versão Distribuído: http://betterexplained.com/articles/intro-to-distributed-version-control-illustrated/
(Acessado em 20/12/2009)
[3]
Controle de versões com o Git:
http://blog.softa.com.br/2009/9/controle-de-vers-es-com-o-git
(Acessado
em 05/01/2010)
[4] L Glassy. Using version control to oberve student software development
processes. Jornal of Computing Sciences in Colleges. Janeiro 2006
[5]
Entendendo o Conceito do Git:
http://www.eecs.harvard.edu/~cduan/technical/git/
(Acessado
em 05/01/2010)
[6] Palestra – Linus Torvalds on Git. Tech Talk Google. Maio 2007.