Tópicos básicos e avançados para quem já usa Git ou SVN. Inclui comparações com SVN e uso do Git como cliente de SVN. Baixe o arquivo e abra no PowerPoint para ver as animações!
4. Distribuído x Centralizado
Distribuído Centralizado
CVS
Git é Distribuído
• Todo diretório de trabalho é um repositório completo
• Contém todo histórico de alterações
• Principais operações são locais
• Sem dependência de um servidor
• Somente operações de “sincronização” necessitam
acesso a outros repositórios
4
6. Repositórios
Repositório de desenvolvedor
• Usado para se trabalhar no projeto
• Com arquivos do projeto
• Dados do Git no diretório .git na raiz do projeto
Repositório de servidor (bare)
• Usado para compartilhar o projeto
• Sem arquivos do projeto
• Dados do Git diretamente na raiz do projeto
Criação de repositório:
• git init [--bare] DIRETÓRIO
6
7. Git versus SVN
Git: versionamento do projeto como um todo
SVN: versionamento dos arquivos e diretórios
Histórico
• SVN: histórico de alterações se referem a arquivos/diretórios
• Git: histórico de alterações se referem ao projeto inteiro
Branching
• SVN: “branches” são implementados como cópias de diretórios
• Git: branches são “realidades alternativas” do projeto inteiro
Concorrência
• SVN: deixa alterar arquivos concorrentemente, possivelmente introduzindo problemas no
projeto
• Git: só permite atualizar repositório compartilhado após fazer merge (ou rebase)
Navegação em interfaces web:
• SVN: primeiro árvore de diretórios e arquivos, depois histórico de alterações de arquivo
• Git: primeiro histórico de alterações do projeto, depois árvore de diretórios da versão do
projeto
7
8. Renomeação e Cópia
SVN
Comandos move e copy
• Mantêm o histórico associado ao novo arquivo/diretório
• Devem ser usados com diretórios (em vez de usar comandos do sistema operacional)
Git
Comando mv
• Equivale a:
– git rm --cached NOME-ANTES # tira do versionamento mas mantém o arquivo no diretório
– mv NOME-ANTES NOME-DEPOIS
– git add NOME-DEPOIS
Não tem comando para cópia
• Executar:
– cp ARQUIVO NOVO-ARQUIVO
– git add NOVO-ARQUIVO
... mas o Git se esforça para detectar renomeações e cópias!
Parâmetros -M e -C em alguns comandos
8
9. Diretórios
SVN: versiona diretórios vazios
Git: não versiona diretórios vazios
Solução: criar um arquivo não usado dentro do diretório (.gitignore)
Comandos add
svn add DIRETÓRIO – Adiciona todos os itens dentro do diretório. Acusa erro se
houver itens já adicionados
git add DIRETÓRIO – Adiciona todos os itens dentro do diretório sem reclamar
sobre itens já adicionados
9
11. Commit
Commits são representados por hashes SHA1 SVN: revisões são
• 40 caracteres! números sequenciais
• Só é necessário usar caracteres o suficiente para não ser ambíguo, a partir de 4
caracteres
commit 2874505bdb80ee8790296428576d977c28708e7f
Author: Eduardo R. D'Avila <erdavila@gmail.com>
Date: Sat Jul 28 13:48:56 2012 -0300
Force loading order of test scripts
Conforme o comando, um commit representa:
• Um estado do projeto
• OU alterações aplicadas a um estado do projeto para gerar um novo estado (delta / diff)
• OU histórico do início do projeto até o estado do commit
Comandos
• git checkout COMMIT
• git show COMMIT
• git log COMMIT
11
12. Commit
Index / Staging Area / Cache
É um estágio pré-commit
arquivo git add git commit
index commit
alterado
Para identificar arquivos alterados e não-commitados:
git status
Para commitar diretamente todos os arquivos alterados:
git commit -a
SVN: para commitar somente
alguns arquivos, é necessário listá-
los todos na linha de comando
12
13. Comando status
index / staging area / cache
SVN: “git checkout -- ARQUIVO”
corresponde a “svn revert ARQUIVO”
13
15. Branches no SVN
São uma convenção
Estrutura de diretórios:
• trunk/
• branches/ABC/
• branches/XYZ/
• branches/.../
Criar branch:
• svn copy .../trunk .../branches/XYZ
“Mergear” branch:
• svn checkout .../trunk
• svn merge .../branches/XYZ
15
16. Branches no Git
São uma feature obrigatória
Branch master é criado por padrão
• Não tem nada de especial
– Pode ser renomeado
– Pode ser removido
– Pode ser recriado
São locais a cada repositório
• Podem corresponder automaticamente (“track”) a um branch em um repositório remoto
16
17. Branches
São implementados como referências a commits
master
format
master
master
bullets
master
align
clipboard
O nome do branch pode ser usado no lugar do commit em comandos
17
18. Operações com branches
Listar
• git branch
O branch atual é marcado com “*”
Alternar
• git checkout BRANCH SVN: comando switch
Criar
• git branch BRANCH [COMMIT] # somente cria SVN: um novo
commit é criado
• git checkout –b BRANCH [COMMIT] # cria e alterna para o branch
Merge
• git merge OUTRO-BRANCH
Excluir
• git branch –d BRANCH # não deixa apagar branch não-mergeado SVN: um novo
commit é criado
• git branch –D BRANCH
Remove somente a referência. Os commits continuam no histórico.
18
19. Merge
Cria imediatamente um novo commit SVN: após o merge é
preciso efetuar commit
A não ser que:
• Resulte em um “fast-forward”
• Haja algum conflito!
SVN: informações de merge ficam
Facilmente identificável no histórico em propriedades do diretório
HEAD
$ git checkout master
master
$ git merge new-feature
D E F
A B C I
G H
new-feature
19
20. Fast-forward
Simplesmente avança o branch atual para alcançar o outro
branch
$ git checkout master
$ git merge new-feature HEAD
master
A B C
D E
new-feature
20
21. Merge com conflito
// Begin // Begin
function f(x) { function f(x) {
main.js
return 7; <<<<<<< HEAD
function f(x) {
} return 7;
}
// End merge =======
return 2 * x;
function f(x) {
>>>>>>> other-branch
return 2 * x;
}
}
// End
$ git merge other-branch
Auto-merging main.js
CONFLICT (content): Merge conflict in main.js
Automatic merge failed; fix conflicts and then commit the result.
$ git status
# On branch master
# Unmerged paths:
# (use "git add/rm <file>..." as appropriate to mark resolution)
#
# both modified: main.js
#
no changes added to commit (use "git add" and/or "git commit -a")
O que fazer?
• Editar arquivos resolvendo os conflitos
• git add ARQUIVOS
• git commit
21
22. HEAD
HEAD é o estado do histórico sobre o qual se está trabalhando
Implementado como referência a um branch (o branch atual) ou diretamente a
um commit
HEAD
git checkout BRANCH
master
• HEAD referencia o branch, que por sua vez referencia o commit
• HEAD é o commit mais recente do branch
A B C
• Ao fazer um commit, o branch avança
HEAD
git checkout <COMMIT ou BRANCH-REMOTO ou TAG>
• HEAD referencia diretamente um commit A B C
• Repositório fica em “detached HEAD”
• Ao fazer um commit, HEAD avança
• Cuidado! Garbage collector pode eliminar commits sem referência
22
23. Tags
Marcam uma versão do projeto
São implementadas como referências a commits SVN: implementação
idêntica a branches
Não podem ser alteradas
Podem ser assinadas com GPG
Listar
• git tag
Criar
• git tag NOME [COMMIT]
23
25. Repositórios Remotos
Identificados por uma URL ou caminho:
Sistema de arquivos local:
• /git/projeto.git
• ../outro-projeto
• file:///home/fulano/projeto
SSH (Git deve estar instalado no servidor):
• ssh://usuario@servidor/caminho
• usuario@servidor:caminho
Outros protocolos:
• git://servidor/caminho – Serviço do Git no servidor
• http[s]://servidor/caminho – Lento! Se for somente leitura, não precisa ter Git no servidor
• ftp[s]://servidor/caminho
• rsync://servidor/caminho
Usar um nome para referenciar um repositório remoto
• git remote add NOME URL-OU-CAMINHO
Múltiplos repositórios podem ser referenciados – Afinal Git é distribuído!
Listar repositórios remotos:
• git remote –v # Lista repositórios remotos
Clonagem de repositório
• git clone [--bare] URL-OU-CAMINHO [DIRETÓRIO] SVN: comando checkout
Automaticamente define o nome “origin” para referenciar o repositório remoto
25
26. Operações com repositórios remotos
Somente duas operações básicas envolvem comunicação com
repositório remoto
git fetch [--tags] NOME
• Obtém branches e tags (e seus commits) do repositório remoto
• Não toca nos branches locais
• Cada branch remoto é identificado por REPOSITÓRIO/BRANCH
• Para listar branches remotos:
– git branch –r # Lista somente branches remotos
– git branch –a # Lista branches locais e remotos (o atual é marcado com ‚*‛)
git push [--tags] NOME BRANCH-LOCAL:BRANCH-REMOTO
• Atualiza (ou cria) o branch do repositório remoto com o estado do branch local
• Só funciona se for um “fast-forward” (pois não há como fazer um merge remoto)
Extra:
git pull NOME BRANCH-REMOTO
• Executa um fetch do branch remoto e faz merge com o branch atual
26
27. Branches “seguidos” (track)
Cada branch local pode estar associado a um branch remoto
Operações simplificadas no branch atual:
• git pull # Sem mais parâmetros!
• git push # Sem mais parâmetros!
Criar um branch a partir de um branch remoto faz a associação
automaticamente:
• git checkout -b NOVO-BRANCH-LOCAL REPOSITÓRIO/BRANCH-REMOTO
• git branch NOVO-BRANCH-LOCAL REPOSITÓRIO/BRANCH-REMOTO
Associar branch já existente:
• git branch --set-upstream BRANCH-LOCAL REPOSITÓRIO/BRANCH-REMOTO
Listar associações:
• git branch -v -v # Mesmo parâmetro duas vezes!
27
29. Git como cliente de SVN
Git pode ser usado para interagir com servidor SVN
Todas as funcionalidades locais do Git ficam disponíveis
Clonar repositório:
• git svn clone [--username=USERNAME] [SUBDIRS] URL [DIRETÓRIO] # pode demorar!
Atualizar informações de branches do SVN:
• git svn fetch # similar a ‚git fetch‛
Atualizar branch atual com commits do SVN:
• git svn rebase # similar a ‚git pull‛
Enviar commits do branch atual ao SVN:
• git svn dcommit # similar a ‚git push‛
Criar branch ou tag no SVN:
• git svn branch NOME
• git svn tag NOME
29
30. Commits do SVN no Git
Commits do SVN no Git incluem revisão relacionada
Commits feitos no Git são substituídos pelo commit do SVN ao serem enviados
ao SVN
• Após git commit:
commit 70391454621da3b6463aa270c9b75f16268909b4
Author: Eduardo D'Avila <erdavila@gmail.com>
Date: Thu Aug 30 19:38:02 2012 -0300
Commit criado com git-svn
• Após git svn dcommit:
commit 1c566c0d83d0efbd6fa65256827be5f2e23e9b2d
Author: erdavila <erdavila@871847d0-d1a7-405d-8ece-d9976fa2c25e>
Date: Thu Aug 30 22:41:33 2012 +0000
Commit criado com git-svn
git-svn-id: file:///home/erdavila/ll-git/svn-server@5 871847d0-d1a7-405d-8ece-d9976fa2c25e
30
31. Cuidados e restrições
Manter histórico linear
Informações de merge do Git e do SVN não são compatíveis
Diretórios vazios
Git não versiona diretórios vazios.
• Diretórios esvaziados no Git devem ser removidos do SVN com git svn dcommit --rmdir
• Diretórios vazios do SVN podem ser criados com git svn mkdirs
Associação entre branches locais e remotos
Git tenta associar pelo commit mais recente em comum nos branches local e
remoto
Tags do SVN
Aparecem como branches remotos no Git
31
33. Alterações no histórico
Alteração no último commit
git commit --amend
Rebase
Diversos usos:
• Tornar linear parte do histórico
• Alterar commits (editar, eliminar, juntar, separar) anteriores ao último
• “Transplantar” commits para outro branch
Pode ser necessário resolver conflitos durante a operação
origin/master origin/master
C D C D E’ F’
A B A B
E F master
$ git checkout master
master HEAD
$ git rebase origin/master
HEAD
33
34. Alterações no histórico
CUIDADO!
Commits que já foram
compartilhados com
outros repositórios não
devem ser alterados!
Git vai achar que são commits novos e tentar fazer merge, aumentando os
riscos de conflitos que cada usuário vai ter que resolver no seu repositório
34
36. stash
Guarda temporariamente alterações ainda não commitadas
Útil quando se começa uma tarefa e precisa-se alternar para outra tarefa no
Git
SVN: comando shelve
Funciona como uma pilha previsto para versão 1.10.0
Comandos
• git stash [save [‘MENSAGEM’]]
• git stash pop [--index] [STASH]
• git stash apply [--index] [STASH]
• git stash list
• git stash drop [STASH]
• git show STASH
Stashes são identificados como:
• stash@{0} (ou simplesmente “stash”) – no topo da pilha. É o default para pop, apply e
drop
• stash@{1}
• stash@{2}
• ...
37
37. log
Provê MUITAS opções de visualização do histórico
• git log [COMMIT ...] – Histórico a partir do commit mais recente (ou dos especificados)
• git log COMMIT1..COMMIT2 - Histórico do que o COMMIT2 tem de novo em relação ao
COMMIT1
• git log -- ARQUIVO – Histórico de commits que incluem alterações no ARQUIVO
• git log -S STRING – Seleciona commits que removeram ou incluíram STRING em algum
arquivo
Algumas opções:
• --stat – Inclui lista de arquivos que foram alterados em cada commit
• -p – Inclui as alterações de cada arquivo (diffs)
• --graph – Mostra grafo de branches e merges
• --oneline – Mostra somente hash e mensagem de cada commit
• --decorate – Identifica outras referências (branches e tags) no histórico
38
38. Operações em linhas de arquivos
O parâmetro -p em alguns comandos permite selecionar
interativamente partes de arquivos
Seleciona partes a serem adicionadas ao index (e posteriormente commitadas)
• git add -p ARQUIVO
Seleciona partes a serem removidas do index
• git reset -p ARQUIVO
Seleciona partes alteradas a serem descartadas
• git checkout -p ARQUIVO
39
39. show / diff / blame
show – Exibe informações de um commit e/ou alterações e
conteúdo de arquivos
• git show [COMMIT] – Mostra dados do commit e suas alterações de arquivo
• git show COMMIT -- ARQUIVO – Mostra alterações feitas no ARQUIVO no commit
especificado SVN: comando cat
• git show COMMIT:ARQUIVO – Mostra conteúdo do ARQUIVO no commit especificado
diff - Mostra diferenças em conteúdos de arquivos
• git diff – Mostra alterações que ainda não estão no index
• git diff COMMIT1 [COMMIT2] – Mostra diferenças entre os commits
• git diff -- ARQUIVO – Seleciona arquivo para mostrar diferenças
blame – Exibe informações de quando cada linha de um arquivo
foi alterada
• git blame ARQUIVO
40
40. cherry-pick
Caso específico de rebase: re-aplica alterações de um único
commit
$ git checkout master new-feature
$ git cherry-pick E
D E F
A B C
E’
master
HEAD
Pode ser necessário resolver conflitos SVN: cherry-pick é
um tipo de merge
41
41. revert
Inverte as alterações feitas por um commit
$ git checkout master
$ git revert B
HEAD
master
A B C D E B’
Pode ser necessário resolver conflitos
SVN: “git revert” não
corresponde a “svn revert”
42
42. bisect
Efetua uma busca binária para ajudar a identificar commit que
introduziu um bug
Pode ser automatizada
Funciona com históricos não lineares
good bad
E F G H I J K L M N O
good bad bad
BUG!
43
43. Ferramentas gráficas
gitk
Correspondente ao comando git log, mas mais visual e navegável
git gui
Provê funcionalidades de commit, merge, gerência de branches e de
repositórios remotos, entre outras opções
44
Branch “format”Negrito – “format” avançaItálico e sublinhadoBranch “align”“align” avançaMergeBranch “clipboard”“align” avançaBranch “bullets” “bullets” vai usar algo que foi feito na implementação de “clipboard” “clipboard” avança Merge: clipboard + align Fim: “bullets” avança; merge