controle de versão gerenciamento - linuxnewmedia.com.br filepara commitar e marcar mensagens,...

6
66 www.linuxmagazine.com.br TUTORIAL | Controle de versão com Git Controle de versão Gerenciamento distribuído Conheça o Git, sistema distribuído de controle de versão que garante a integridade e consistência de dados com segurança e esforço mínimo. por Falko Benthin D ocumentos e código-fonte que são utilizados, alterados e processados por vários usuários estão muitas vezes loca- lizados em um servidor central de arquivos, enquanto os indivíduos trabalham com cópias locais. Pesqui- sar manualmente as diferenças entre documentos muitas vezes deixa dúvi- das quanto a existência de uma nova versão de um documento e, se assim for, quem o alterou pela última vez. Um sistema de controle de versão, como utilizado em muitos projetos de software, pode ajudar a arrumar a bagunça. Um dos candidatos mais fortes nesta área é o Git [1]. O Git foi desenvolvido em 2005 por Linus Torvalds para gerenciar o código fonte do kernel Linux. Para fazer isso, precisou satisfazer uma série de requisitos: Tinha que ser rápido, oferecer suporte a várias ramificações parale- las, e ser capaz de trocar dados entre repositórios diferentes; Tinha que oferecer suporte a verificações de integridade de da- dos e evitar que objetos de dados armazenados no repositório fossem modificados retroativamente. Comparado com outros sistemas de controle de versão, o Git é ca- racterizado pela sua suave curva de aprendizado, redundância de dados através de repositórios locais, baixo consumo de memória, e serviços gra- tuitos, como o GitHub e o Gitorious. Instalação O Git é um programa de linha de comando disponível para Linux, Mac OS X, Solaris e MS Windows. Não obstante, ele também contempla vá- rias interfaces gráficas, incluindo Gitk, Git-cola [2], SmartGit [3], giggle [4], e Gitg [5], bem como interfaces online como Gitweb, Cgit [6], e Gitlab [7]. O Git está nos repositórios da maioria das distribuições, por isso podemos instalá-lo facilmente usan- do as ferramentas de gerenciamento de pacotes adequadas. Se preferir a última versão, poderá instalar o sis- tema de controle de versões como root com três comandos: # ./configure # make all doc # make install install-doc install-html TUTORIAL Figura 1 Quando inicializamos, o Git não está interessado em saber se o diretório está vazio ou já contém alguns arquivos.

Upload: others

Post on 16-Oct-2019

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Controle de versão Gerenciamento - linuxnewmedia.com.br filepara commitar e marcar mensagens, modelos de commit, confi gurações de diff e merge, ou recursos simi-lares; para tanto,

66 www.linuxmagazine.com.br

TUTORIAL | Controle de versão com Git

Controle de versão

Gerenciamento distribuído

Conheça o Git, sistema distribuído de controle de versão que garante a integridade e consistência de dados com segurança e esforço mínimo. por Falko Benthin

Documentos e código-fonte que são utilizados, alterados e processados por vários

usuários estão muitas vezes loca-lizados em um servidor central de arquivos, enquanto os indivíduos trabalham com cópias locais. Pesqui-sar manualmente as diferenças entre documentos muitas vezes deixa dúvi-das quanto a existência de uma nova versão de um documento e, se assim for, quem o alterou pela última vez. Um sistema de controle de versão, como utilizado em muitos projetos de software, pode ajudar a arrumar a bagunça. Um dos candidatos mais fortes nesta área é o Git [1] .

O Git foi desenvolvido em 2005 por Linus Torvalds para gerenciar o código fonte do kernel Linux. Para fazer isso, precisou satisfazer uma série de requisitos:

➧ Tinha que ser rápido, oferecer suporte a várias ramifi cações parale-las, e ser capaz de trocar dados entre repositórios diferentes;

➧ Tinha que oferecer suporte a verifi cações de integridade de da-dos e evitar que objetos de dados armazenados no repositório fossem modifi cados retroativamente.

Comparado com outros sistemas de controle de versão, o Git é ca-racterizado pela sua suave curva de

aprendizado, redundância de dados através de repositórios locais, baixo consumo de memória, e serviços gra-tuitos, como o GitHub e o Gitorious.

Instalação O Git é um programa de linha de comando disponível para Linux, Mac OS X, Solaris e MS Windows. Não obstante, ele também contempla vá-rias interfaces gráfi cas, incluindo Gitk , Git-cola [2] , SmartGit [3] , giggle [4] , e Gitg [5] , bem como interfaces online como Gitweb , Cgit [6] , e Gitlab [7] .

O Git está nos repositórios da maioria das distribuições, por isso podemos instalá-lo facilmente usan-do as ferramentas de gerenciamento de pacotes adequadas. Se preferir a última versão, poderá instalar o sis-tema de controle de versões como root com três comandos: # ./configure# make all doc# make install install-doc install-html

TU

TO

RIA

L

Figura 1 Quando inicializamos, o Git não está interessado em saber se o diretório está vazio ou já contém alguns arquivos.

Page 2: Controle de versão Gerenciamento - linuxnewmedia.com.br filepara commitar e marcar mensagens, modelos de commit, confi gurações de diff e merge, ou recursos simi-lares; para tanto,

67

| TUTORIALControle de versão com Git

Linux Magazine #98 | Janeiro de 2013

após baixar o código fonte doGitHub [8] .

Como confi gurar O Git oferece amplas possibilidades para confi gurações globais, de usuá-rio e específi cas de um determinado projeto. Confi gurações globais do sistema são encontradas em /etc/gitconfig ; confi gurações do usuário estão no arquivo ~/.gitconfig no dire-tório home do usuário. Confi gurações que afetam apenas um único projeto são armazenadas em .git/config do repositório correspondente.

Neste artigo, cobriremos apenas as confi gurações mais importantes. Se o usuário, adicionalmente, quiser modifi car o esquema de cores, o editor para commitar e marcar mensagens, modelos de commit, confi gurações de diff e merge, ou recursos simi-lares; para tanto, deverá verifi car a man page do Git e a documentação do projeto [9] .

Um dos passos mais importantes é apresentar-se ao Git, fornecendo nome e endereço de email: # git config --global user.name "<firstname> <lastname>"

# git config --global user.email <my>@<email>.<ext>

O Git usa essas duas informações mais tarde para atribuir snapshots (“commits”) a um usuário. A opção --global signifi ca que as confi gurações se aplicam a todos os repositórios de um usuário Git por padrão. Se quiser-mos utilizar um nome ou endereço de email diferentes para um projeto específi co, precisaremos executar o git config no respectivo repositório, mas sem a opção -- global .

Quando os usuários executam um commit, o Git normalmente chama o editor padrão do sistema e recorre ao Vi , se nenhum padrão for defi nido. Pelo fato de o Vi muitas ve-zes ser o padrão – e muitos usuários não gostarem da ideia de usá-lo – o Git permite que o usuário selecione seu editor preferido. Basta digitar :

# git config --global core.editor <preferred_editor>

e substitua com o nome do seu edi-tor preferido.

Git em ação O Git é muito fácil de usar no trabalho diário. Para iniciar um projeto com o sistema de controle de versão, quer este seja o código fonte ou um documento de escritório, precisamos inicializar o Git no diretório apropriado com:

git init

O Git cria, então, um diretório oculto, ./git , que posteriormente é utilizado para monitorar o projeto e seu desenvolvimento ( fi gura 1 ). Quan-do inicializarmos um diretório, ele não precisa conter todos os arquivos.

Para visualizar o status de um repositório, execute o comando git status . Este comando lista os arquivos que o Git ainda não mo-nitorou, os arquivos que foram al-terados desde o último commit, e os arquivos que foram alterados na área de preparação. A fi gura 2 mos-

Figura 2 Saída de status do Git mostrando candidatos para a área de preparação.

Figura 3 O próximo commit diz respeito a muitos arquivos novos.

Page 3: Controle de versão Gerenciamento - linuxnewmedia.com.br filepara commitar e marcar mensagens, modelos de commit, confi gurações de diff e merge, ou recursos simi-lares; para tanto,

68 www.linuxmagazine.com.br

TUTORIAL | Controle de versão com Git

tra um projeto recém-inicializado, onde o Git ainda não está monito-rando quaisquer arquivos.

Podemos imaginar a área de prepa-ração como um lugar onde residem os arquivos que serão adicionados ao snapshot Git no próximo commit. É possível enviar os arquivos, diretórios ou todo o projeto selecionado para a área de teste digitando git add <file> ou git add . . O status muda, então, de untracked para new fi le ( fi gura 3 ).

Commits Quando um autor quer salvar seu trabalho atual em um snapshot, ele pode usar git commit para fazer isso, após mover todos os arquivos afeta-dos para a área de preparo. Além dos arquivos e mudanças, o Git registra os nomes e endereços de email do

autor / committer para cada commit, juntamente com a data de criação e commit.

Depois de digitar o comando, o Git abre um editor (previamente confi gurado), que permite que o usuário digite uma mensagem de confi rmação. O usuário pode aceitar a sugestão do Git, que lista todas as alterações desde o último commit – simplesmente removendo o sinal de cerquilha no início – ou pode digitar sua própria mensagem ( fi gura 4 ).

A mensagem de commit deve indicar o que foi modifi cado. Pelo fato de o Git apresentar uma visão concisa dos commits quando o re-gistro é consultado, a primeira linha deve sempre conter um resumo. Isto é especialmente verdadeiro se a mensagem de commit for lon-

ga. Particularmente quando várias pessoas estão colaborando, breves comentários ajudam a explicar por que algo mudou e se quaisquer pro-blemas ou erros ocorreram ou são esperados (quadro 1).

O primeiro commit é geralmente chamado de “commit inicial”; deve-mos nomear todos os outros commits de modo que os participantes do projeto possam ver imediatamente o que o commit fez. Mensagens como minor bugfi x (correção de pequenos bugs) não dizem nada de útil – uma mensagem mais signifi cativa deve ser Segmentation fault in fl ip fl op on.cpp fi xed (falha de segmentação no fl ip fl op on.cpp corrigida). Muitas ve-zes, especialmente em colaboração distribuída, onde todos os membros do projeto precisam receber o esta-do atual sem demora, os commits incluem apenas pequenas altera-ções. Se uma pequena mensagem de commit é sufi ciente, podemos adicioná-la diretamente quando chamarmos o Git como:

$ git commit -m "MPI_Type_create_ struct added for LineHistogram"

sem a necessidade de executar o editor.

Ramifi cações Se adicionarmos novos recursos em um aplicativo existente, há sempre um risco de que partes funcionais sejam afetadas. O Git assume as preocupações para o pior cenário possível, permitindo diferentes ra-mifi cações em um projeto. Uma ramifi cação pode ser comparada a um playground, onde podemos experimentar novos recursos sem colocar em risco as partes existentes de um aplicativo.

Para criar uma nova ramifi cação, podemos usar o comando

git branch <name>

Um número qualquer de ramifi -cações paralelas pode existir, e você pode alternar entre elas com:

Figura 4 O usuário pode editar mensagens de commit em um editor de sua preferência.

Figura 5 O Git suporta muitas ramifi cações simultâneas; um asterisco indica a área de trabalho atual.

Page 4: Controle de versão Gerenciamento - linuxnewmedia.com.br filepara commitar e marcar mensagens, modelos de commit, confi gurações de diff e merge, ou recursos simi-lares; para tanto,

69

| TUTORIALControle de versão com Git

Linux Magazine #98 | Janeiro de 2013

git checkout <name>

O comando git branch sem es-pecifi car um nome mostra todas as ramifi cações existentes. O Git marca a á atual com um asterisco ( fi gura 5 ) – qualquer commit subsequente afeta somente esta ramifi cação.

Todas as alterações feitas em uma ramifi cação não infl uenciam as ou-tras de maneira alguma. Depois de completar a implementação de novos recursos e testar bastante, podemos mesclar a ramifi cação com a mas-ter usando:

git merge <name>

Ramifi cações desnecessárias são facilmente removidas com:

git branch -d <name>

Se quiser mudar o nome de uma ra-mifi cação, faça isso usando o comando

git branch -m <newname>

O que há de novo? O comando git diff permite visu-alizar e identifi car rapidamente as diferenças entre as ramifi cações, commits ou arquivos, como no exem-plo a seguir: git diff <Branch1>..<Branch2>git diff <CommitID>git diff <filename>

Este comando demonstra ser es-pecialmente útil quando estamos interessados apenas em corrigir erros de algumas alterações que são difíceis de encontrar com um olhar casual.

Histórico do projeto Um projeto cresce, commits se ali-nham, e um milestone é alcançado, por isso é hora de um changelog. Ao invés de arruinar seu cérebro tentando lembrar o que aconteceu desde a última etapa, você somente pergunta ao Git - supondo que tenha sempre acrescentado signifi cativas mensagens de commit.

Por exemplo, o comando :

git log

revela o que aconteceu a cada com-mit, quem foi o responsável por isso, e quando foi feita uma alteração no projeto. O log pode ser curto e incisivo ou muito detalhado, dependendo da requisição. Se digitarmos o coman-do sem parâmetros adicionais, o Git gera o hash exclusivo de um com-mit, o autor, a data, e a mensagem do commit. A opção --graph mostra ramos separadamente ( fi gura 6 ). O parâmetro --oneline limita a saída para o início do hash do commit e a mensagem de commit, e nunca usa mais que uma linha para isso.

Mitigando danos Considere este breve cenário: de-pois de vários dias de trabalho de desenvolvimento sob pressão aguda de tempo e privação de sono, de re-pente o desenvolvedor encontra-se rodeado de código “sujo” que não funciona como deveria. Tentar re-mover os commits manualmente é provavelmente impossível, portanto ou ele volta à estaca zero, ou pode fazer uso dos benefícios do contro-le de versão e operar um rollback (reverter) para a última revisão naqual trabalhava.

Se o desenvolvedor em questão tiver certeza absoluta de que as úl-timas horas foram, de fato, um caso perdido, poderá executar um rollback severo digitando:

git reset --hard <CommitID>

O CommitID refere-se ao va-lor hash de 40 dígitos do snapshot desejado. Os hashes tipicamen-te diferem na medida em que o Git necessita apenas dos primei-ros sete dígitos para identificar o commit claramente. O rollback severo redefine todos os arquivos no diretório de trabalho e na áreade preparação.

Se substituíssemos --hard por --soft , o Git iria zerar o commit es-pecifi cado para a versão “HEAD”, que serve então como o último com-mit. Neste caso, todas as alterações no diretório de trabalho e na área de teste são mantidas. O usuário terá que decidir por si mesmo se voltar para a última versão usando soft faz sentido em um labirinto de confu-são de código.

Outra opção de rollback é o git checkout , com o qual o usuário já está familiarizado ao alternar entre ramifi cações. Para fazer um rollba-ck, podemos renomear a ramifi ca-ção principal e recuperar o último snapshot utilizável com :

git checkout <CommitID> Figura 6 Log do Git mostrando o histórico do projeto.

Page 5: Controle de versão Gerenciamento - linuxnewmedia.com.br filepara commitar e marcar mensagens, modelos de commit, confi gurações de diff e merge, ou recursos simi-lares; para tanto,

70 www.linuxmagazine.com.br

TUTORIAL | Controle de versão com Git

em seguida, torne esta a nova versão principal com :

git checkout -b master

Este é um atalho para não ter que digitar os seguintes comandos:

git branch <name>git checkout <name>

( fi gura 7 ). A vantagem deste tipo de rollback é que inicialmente são man-tidas todas as alterações e quaisquer ideias não utilizáveis poderão ser ex-cluídas mais tarde. Usar git checkout não só ajuda a zerar completamente os commits, como também arquivos

separadamente. Tudo o que o usuário ainda precisa fazer é especifi car o nome do arquivo. Assim, usar o comando:

git checkout af4673fa6 main.cpp

restaura a revisão af4673fa6 do ar-quivo main.cpp .

Versões distribuídas O Git foi projetado desde o início como um sistema de controle de versão distribuído, o que signifi ca que várias partes interessadas podem trabalhar em um projeto ao mesmo tempo. Em contraste com um siste-ma de controle de versão centrali-

zado, que precisa de uma conexão com o repositório do servidor para obter logs e commits, repositórios Git são executados localmente e podem sincronizar com um servi-dor assim que uma conexão de rede estiver disponível.

Como o servidor só precisa dis-tribuir as alterações, é bom que ele seja executado em um repositório vazio. Este repositório contém ape-nas os arquivos do diretório do pro-jeto Git, .git , e ajuda os membros do projeto a sincronizar seus dados. Podemos criar um repositório vazio no servidor com:

$ git init --bare <repository>.git

As permissões de acesso que se aplicam aqui são os padrões do umask da conta de usuário utilizada para criar o repositório ( fi gura 8 ). No computador local, podemos clonar o repositório remoto usando:

$ git clone ssh://<server>/ <path>/<repository>.git

O Git suporta a sincronização de repositórios via protocolos Git, SSH, e HTTP(S). O Git não suporta a autenticação em si, ao invés disso conta com o SSH para identifi car os usuários que fazem upload de um commit. Aplicativos auxiliares como o Gitolite [10] ajudam a evitar que todos os envolvidos no projeto pre-cisem ter uma conta de usuário com direitos plenos para se autenticar.

Após a criação de um repositório vazio recém-clonado, é necessário populá-lo criando arquivos de pro-jeto no repositório local, em seguida commitá-los e sincronizá-los com o repositório remoto. O comando a seguir faz essa proeza:

$ git push <bare> <local>:<remote>

O item <bare> especifi ca o repo-sitório remoto, <local> que refere-se à ramifi cação local, e <remote> é a ramifi cação remota. Após o commit inicial, o próprio Git reconhece se

Figura 7 O comando checkout do Git não é apenas útil para alternar entre ramifi cações, mas também para rollbacks.

Figura 8 Um repositório vazio contém apenas o diretório .git para um proje-to, mas nenhum arquivo de trabalho.

Figura 9 Usando o push para sincronizar os repositórios Git local e remoto.

Page 6: Controle de versão Gerenciamento - linuxnewmedia.com.br filepara commitar e marcar mensagens, modelos de commit, confi gurações de diff e merge, ou recursos simi-lares; para tanto,

71

| TUTORIALControle de versão com Git

Linux Magazine #98 | Janeiro de 2013

contrapartes remotas existem para ramifi cações locais; um simples git push é o sufi ciente ( fi gura 9 ).

A contraparte para git push é git pull ; este combina os comandos git fetch e git merge para sincronizar o repositório local com o remoto. Os comandos fetch e merge mui-tas vezes iniciam interações bem complexas com repositórios remo-tos, portanto vale a pena dar uma

olhada na documentação do Git para ambas as ferramentas.

Serviços públicos como o Gi-tHub [11] , Gitorious [12] ou o Google Code [13] são alternativas úteis para um servidor de projeto próprio. Não há custos para pro-jetos livremente acessíveis. Para os projetos que o usuário não de-seja compartilhar com o público em geral, o Gitorious e o GitHub

oferecem também hospedagem comercial de repositórios privados.

Simplesmente ignore Em projetos maiores de software, principalmente, os desenvolvedores tendem a usar diversas estruturas de diretório ou preferem confi gu-rações diferentes para os usuários. Se os desenvolvedores modifi cam arquivos que contêm caminhos ou confi gurações diversas vezes para corresponder com suas preferências e então submetem essas mudanças, outros colaboradores rapidamente fi carão frustrados.

Além disso, os arquivos de confi -guração muitas vezes contêm nomes de usuários e senhas que podemos não querer distribuir. Felizmente, o Git permite excluir arquivos de um commit. Para fazer isso, é só criar um arquivo .gitignore no respectivo diretório de trabalho e listar todos os arquivos do diretório que deseja que o Git ignore em um commit. É preciso digitar um nome de arquivo por linha.

Conclusão Como um sistema de controle de versão distribuído poderoso, o Git pode fazer muito mais do que ape-nas o básico mostrado neste artigo. Seus recursos avançados incluem a aplicação de tags e alteração de base, um daemon para acesso de leitura anônima em repositórios Git, fi ltros e hooks, e a capacidade de remover informações sensíveis ou bibliotecas retroativamente a partir de um repo-sitório. Além disso, várias interfaces gráfi cas e interfaces web oferecem uma abordagem mais conveniente para controlar o Git. ■

Mais informações [1] Git: http://git -scm.com/

[2] Git-cola: http://git -cola.github.com/

[3] SmartGit: http://www.syntevo.com/smartgit/index.html

[4] Giggle: https://live.gnome.org/giggle/

[5] Gitg: https://live.gnome.org/Gitg/

[6] Cgit: http://hjemli.net/git/cgit/

[7] Gitlab: http://gitlabhq.com/

[8] Git (no GitHub): https://github.com/git/git/

[9] Documentação do Git: http://git -scm.com/doc/

[10] Gitolite: https://github.com/sitaramc/gitolite/

[11] GitHub: https://github.com/

[12] Gitorious: http://gitorious.org/

[13] Google Code: http://code.google.com/

Gostou do artigo?Queremos ouvir sua opinião. Fale conosco em [email protected] artigo no nosso site: http://lnm.com.br/article/8047

sso sr/artic

sua om

ne.come:

804

igo?nião.

Quadro 1: Protocolo Para projetos de software em que vários desenvolvedores compartilham um sistema de controle de versão, algumas práticas tem se revelado benéfi cas. Por exemplo, devemos – se possível – também monitorar as alterações feitas por outros desenvolvedores. Isso ajuda a descobrir rapidamente se o código interage com outros componentes e poderá encontrar observações sobre os erros existentes. Os repositórios devem sempre conter apenas um projeto, mesmo que os desenvolvedores possam trabalhar juntos em vários projetos ao mesmo tempo.

Preferencialmente, cada commit deve completar exatamente uma tarefa – por exemplo, um novo recurso ou uma correção de bug. As mensagens de com-mit devem ser autoritárias e explicar casos de uso complicados, especialmen-te se este não é tratado por comentários no código. Se possível, um repositó-rio deve conter apenas os arquivos que os desenvolvedores criaram. Arquivos gerados automaticamente, ou livremente acessíveis através de bibliotecas e ferramentas externas, não devem fazer parte do repositório; na verdade, eles desnecessariamente incham o repositório.

O código publicado com um commit deve funcionar, então outros membros do projeto podem continuar a trabalhar e não têm que começar a corrigir bugs que surgiram. No entanto, um usuário nunca deve remover o código do projeto sem consulta prévia, só por que não gosta ou não o compreende imediatamente.