Conceitos e exemplos em versionamento de código

Preview:

DESCRIPTION

Uma pequena apresentação dedicada a expôr desenvolvedores a conceitos e termos relacionados ao controle de versão de código em projetos de software; essa é uma prática essencial no desenvolvimento de software com a qual todos os desenvolvedores se depararão no decorrer de suas carreiras.

Citation preview

Conceitos e Exemplos em Versionamento de Código

30-40 minutosAtualizado em 20 Ago 2014 falmeida1988@gmail.com

Exemplos com Subversion

IntroduçãoUm sistema de controle de versão de código-fonte (VCS) é um programa que guarda todas as modificações que levaram cada linha de arquivo do seu projeto desde o seu estado inicial (provavelmente em branco) até o estado atual, passando por todas as mudanças intermediárias.

Um VCS pode lhe ser útil se você, por exemplo:● deseja guardar a história do seu projeto e se proteger contra eventuais

perdas, mudanças que causaram erros ou

● pertence a uma equipe de desenvolvimento com 2 ou mais desenvolvedores

Cenários Comuns● Um desenvolvedor deseja mudar uma funcionalidade existente mas deseja

que a antiga fique disponível enquanto a nova versão está sendo escrita;

● Um desenvolvedor percebe que sua aplicação, que estava funcionando, agora contém um erro, mas ele não consegue identificar qual mudança introduziu este erro.

● Dois desenvolvedores estão trabalhando cada um em uma tarefa, mas ambas envolvem mudar um mesmo arquivo de código; ambas as tarefas têm alta prioridade então um não pode esperar até que o outro acabe para então começar a trabalhar. As duas tarefas têm que ser feitas ao mesmo tempo.

Principais ferramentas● CVS

● Subversion (SVN)

● Team Foundation Server (TFS)

● Git

● Mercurial

● Perforce

RepositórioO repositório (também chamado de repo) é o lugar onde o seu projeto, bem como todo o histórico de modificações do mesmo, fica guardado.

Em geral ele é localizado em outra máquina e é identificado por uma url.

Seu repositório reflete a história do seu projeto, até a versão mais recente do seu projeto (também chamada de HEAD).

Quando alguém executa uma operação do tipo commit, o repositório é atualizado com as modificações introduzidas por aquele commit.

Repositório (cont.)Exemplo: criar um repositório local na sua máquina

● svnadmin create /home/usuario/meu-repo

Note que este repositório só poderá ser acessado de dentro da sua máquina através do protocolo file://, por exemplo:*

● svn list file:///home/usuario/meu-repo

* A partir de outras máquinas, este repositório ser acessado de outras formas; por exemplo, os protocolos svn+ssh// e http://.

comando para listar arquivos de um repositório

CheckoutUma operação do tipo checkout faz uma cópia do código de um repositório para o seu diretório atual.

Exemplos:● svn checkout http://example.com:9834/trunk minha_copia

Este comando faz uma cópia do código cujo repositório está em http://svn.example.com:9834/trunk para o diretório atual, sob o nome minha_copia/.

● svn checkout svn+ssh://usuario@servidor/var/svnrepos/meu-repoEste comando usa o protocolo ssh para se conectar ao servidor e faz uma cópia do código em sua máquina (para dentro de um diretório chamado meu-repo/ pois não foi definido um nome alternativo como no exemplo anterior)

Working copy(também chamado de working directory)

A sua working copy é a sua cópia do projeto.

Quando você faz uma operação de checkout ou clone, o diretório para onde os arquivos do projeto foram copiados é a sua working copy.

Nada do que você faz na sua working copy é publicado (para o seu repositório até que você faça um commit), portanto modificações, criação de arquivos e remoção de arquivos na sua cópia local não afetam o seu repositório.

AddUm arquivo ou diretório criado na sua working copy não é versionado (tracked) por default. Para que um VCS (nesse caso, o SVN) comece a versionar (isto é, guardar o histórico de modificações) de um arquivo, é necessário que se execute o comando add:

(dentro de sua working copy)

● svn add arquivo1.txt

Note que um comando do tipo commit só envia para o repositório mudanças em arquivos versionados (isto é, arquivos em que se executou svn add). Arquivos não versionados são ignorados pelo VCS.

CommitA operação de commit atualiza o repositório com modificações feitas nos arquivos versionados em uma cópia local.

● mensagem de commit

● revision N

Exemplos● svn commit a.txt b.txt -m "nova versão"

Este comando atualiza o repositório de origem (de onde você fez checkout) com as mudanças feitas nos arquivos a.txt e b.txt.

uma pequena mensagem explicando o commit e a sua

razão

o estado do repositório após o N-ésimo commit

UpdateUma operação de update faz a sua working copy refletir o estado atual do repositório.

Se, por exemplo, modificações foram feitas por outro desenvolvedor no seu repositório de origem desde a última vez que você fez uma operação de checkout, uma operação de update irá modificar a sua working copy de modo a ficar igual ao estado atual do repositório.

Exemplos:● svn update arquivo1.txt

● svn update -r40

sua working copy agora está no estado como estava após o 40º commit

RevertUma operação do tipo revert descarta as modificações em um arquivo na sua working copy (ou seja, modificações que ainda não sofreram commit), fazendo-o ficar idêntica ao último commit do repositório.

Exemplos:● svn revert arquivo1.txt

● svn revert --depth=infinity .A opção --depth=infinity faz a operação de revert ser feita em diretórios-filhos do diretório atual, recursivamente.

BranchUm branch é um artifício suportado por vários VCSs. Ele representa uma outra linha de desenvolvimento.

Casos de uso:● Você deseja começar a implementar uma funcionalidade nova

(grande e que necessitará de vários commits) mas quer que sua versão principal continue estável enquanto a funcionalidade nova não fica pronta.

● Você deseja fazer experimentos com funcionalidades novas mas não deseja que a versão principal seja afetada.

BranchExemplo de criação um branch:

● svn copy http://example.com/trunk \ http://example.com/branches/my-branch \ -m "criando um novo branch"

Cria um branch do repositório, acessível pela url http://example.com/branches/my-branch. Pode-se fazer checkout deste como se fosse um repositório normal.

Merge● Comando que gera uma versão final de um arquivo a partir de duas versões do

mesmo arquivo.

● Na maioria das vezes, não é necessária intervenção manual do usuário, pois os VCSs conseguem fazer merges automáticos para a maioria dos casos.

● Quando um merge automático não consegue ser feito, é gerado um conflito que deve ser resolvido manualmente.

por exemplo, em dois branches ou em duas revisions diferentes

Merge (cont.)Exemplos:● svn merge http://example.com/branches/branch-a

Se você executar este comando de dentro de uma working copy (e assumindo que o branch branch-a foi criado a partir do mesmo repositório), este comando fará um merge do branch branch-a com a sua working copy atual.

ConflitosConflitos acontecem quando o seu VCS não consegue, de forma automática, fundir em um arquivo novo mudanças oriundas de duas versões diferentes.

Conflitos podem surgir após operações de update ou merge.

Exemplo: conflito após uma operação de update no SVN:$ svn updateUpdating '.':Conflict discovered in 'foo.c'.Select: (p) postpone, (df) diff-full, (e) edit, (mc) mine-conflict, (tc) theirs-conflict, (s) show all options:

ConflitosExemplo de um arquivo com marcadores de conflito (SVN): arquivo1.txt

there are<<<<<<< .minenine=======eight>>>>>>> .r999

planets in the solar system

parte comum às duas versões

versão do branch atual (“minha” versão)

versão do outro branch ou revision (versão “deles”)

Resolvendo conflitosUm método simples de resolver conflitos é simplesmente editar (manualmente) o arquivo com marcadores de conflito e avisar ao SVN que o conflito foi resolvido:

● editar o arquivo arquivo1.txt

● svn resolve --accept working arquivo1.txt

● svn commit -m "conflito resolvido!"

não esquecer de dar commit!

dizer ao SVN que a versão final é a versão é a que está

na working copy

Resolvendo conflitos (cont.)Você também pode mandar o SVN aceitar uma das versões em detrimento da outra:Exemplos:

● svn resolve --accept mine-conflict arquivo1.txtAssumindo que o arquivo arquivo1.txt está em conflito, este comando adota a “minha” versão do conteúdo para todos os conflitos.

● svn resolve --accept theirs-conflict arquivo2.txtA versão do branch remoto (“deles”) é escolhida e a minha versão, bem como os marcadores de conflito, são retirados do arquivo.

N.B.: Outras opções como theirs-full, mine-conflict e theirs-conflict também estão disponíveis.

Melhores práticas● Dê commit frequentemente

○ quanto mais commits, mais lugares para onde você pode fazer revert○ mais fácil fazer merge se as duas versões de um arquivo não estão muito

diferentes entre si.○ você se força a dividir o desenvolvimento em unidades pequenas e

autocontidas de tarefas.○ Ajuda a contar a ‘história’ do projeto através dos commits.

● Dê commit de todos os arquivos relacionados a uma mudança de forma única, incluindo todos eles; em outras palavras, seu commit deve ter unidade lógica.

Melhores práticas (cont.)● Todos os commits devem deixar o software funcionando.

○ Ou seja: todos os testes devem estar passando.○ Ou seja: nunca dê commit antes de testar.

● Não dê commit em arquivos gerados○ Arquivos executáveis (no caso de linguagens compiladas) ou arquivos de

output gerados por ferramentas não devem ser versionados.

● Não dê commit em arquivos de preferências○ Arquivos como .vimrc (vim), .nbproject/ (netbeans) ou .idea/

(IntelliJ) são pessoais e não deve ser versionados.

Melhores práticas (cont.)● Use mensagens de commit descritivas e explicativas

○ Lembre-se que você não se lembrará do que fez hoje daqui a alguns meses.

○ As mensagens de commit servem como documentação do projeto.

● Não dê commit em coisas feitas pela metade○ Divida coisas grandes em unidades lógicas menores e dê commit em

cada uma delas separadamente.○ Senão, espere até o fim da tarefa para dar commit.

XTRA: Comandos úteis para o dia-a-dia (SVN)

● svn delete arquivo1.txtRemove um arquivo da sua working copy e do repositório (quando você der commit, o arquivo vai ser removido do repositório)

● svn delete --keep-local arquivo1.txtRemove um arquivo do repositório mas o deixa na sua working copy (ele fica no estado untracked).

● svn mv arquivo1.txt ../arquivo2.txtMover (e/ou renomear) um arquivo, deixando claro para o SVN que se trata do mesmo arquivo.

XTRA: Repositórios centralizados e descentralizados● Em um VCS centralizado, só há uma cópia do repositório. Cada usuário só tem

acesso à sua cópia dos arquivos (no seu working directory); quando você executa um commit, o repositório central é atualizado.

● Em um VCS descentralizado (DVCS), não há um único repositório; cada usuário guarda uma cópia do repositório inteiro; o comando commit envia suas modificações para a sua cópia do repositório.

● Para interagir com repositórios remotos são usados alguns comandos novos, como fetch, pull e push.

XTRA: push e pullComo VCSs descentralizados podem ter várias cópias do mesmo repositório em existência, há dois comandos extras que definem operações entre um repositório local e um outro repositório remoto:

● comando push○ Envia o seu repositório (com todos os seus commits) para um

repositório remoto, atualizando o mesmo (pode ser rejeitado).

● comando pull○ Tenta atualizar o seu repositório local, incorporando modificações

vindas de um repositório remoto (pode haver conflitos).

XTRA: Migrações - versionamento de bancos de dados● Dois projetos rodando a mesma versão do código mas com bancos de

dados com estruturas diferentes (tabelas e atributos) vão exibir comportamento diferente.

● Hoje em dia (2014) este já é um problema bem resolvido pela maioria dos frameworks em existência.

● Migrações consistem em fazer cada mudança na estrutura do seu banco de dados através de arquivos.

Recommended