Slides do mini curso de colaboração com Git, apresentado na semana da computação da Unesp Rio Claro (SECCOMP). O mini curso introduz os sistemas de controle de versão, apresenta um guia básico e avançado de Git, discute estratégias de workflows de desenvolvimento e por fim discute diversos assuntos relacionados a colaboração como: permissões, licenças, forks, pull requests, issue trackers, continuous integration.
3. Agenda
1. Motivação
2. Guia de Git do básico ao avançado:
a. Instalação e configuração
b. Estrutura do repositório
c. Compilado com os comandos mais importantes
d. Submodules
e. Hooks
f. Reescrevendo a história
3. Workflows:
a. Modelo de branching
b. Git flow
c. Planos de SCM
4. Agenda
4. Colaboração:
a. Repositórios na nuvem
b. Colaboradores e permissões
c. Forks e pull requests
d. Licenças de software
e. Issue Tracker
f. Continuous Integration
g. Webhooks
5. Prática
a. Git
b. Colaboração
5. Motivação
Como você armazena seu código-fonte?
O que você faz para distinguir as diferentes versões do seu código?
O que você faz para distinguir o código nas fases de
● desenvolvimento
● homologação
● produção?
8. Motivação
O que você faria, se precisasse trabalhar em um código com várias pessoas ao
mesmo tempo?
Imagine um cenário onde as pessoas precisam trabalhar em cima da mesma
versão de um software, mas desenvolvendo funcionalidades diferentes. Como
garantir que essas funcionalidades sejam integradas ao código original de
forma eficiente?
11. Motivação
Por falar em eficiência. Suponha que essas pessoas não trabalhem juntas
fisicamente:
● Todos moram relativamente longe e precisam trabalhar em cima do
código remotamente.
● Utilizam sistemas operacionais diferentes, o que pode implicar em
diferenças na representação da quebra de linha.
○ (Windows -> CR+LF ; Linux, macOS -> LF)
12. Motivação
Como garantir a distribuição desse código-fonte?
● As pessoas precisam do código-fonte e todas as suas versões, sempre
disponível
● Esse código precisa ser visualizado corretamente independente do
sistema operacional
● Tudo que é desenvolvido, precisa ficar registrado para que qualquer um
tenha acesso
13. Motivação
Como desfazer um erro no código? Isto é, voltar para um estado que um dia
funcionou corretamente.
Como saber exatamente qual a diferença entre duas versões do seu software?
Por exemplo, antes de gerar a versão 2, seria interessante saber quais arquivos
novos foram introduzidos, quais foram removidos, quais foram modificados.
Dos que foram modificados, quais foram essas modificações: algumas linhas
foram adicionadas, outras foram removidas, outras foram modificadas. Das
linhas modificadas, o que exatamente mudou?
14. Motivação
Sabendo o que foi modificado, é possível validar se algo está faltando, se tem
algo lá que não deveria estar naquele momento, se tem algo digitado errado.
Além disso, comparar apenas as diferenças é muito mais eficiente do que
tentar comparar o projeto por completo.
A capacidade de comparar estados diferentes do seu código, também pode
ser útil na hora de tentar encontrar um bug, que foi introduzido em algum
momento no passado.
15. Indo além
Além de todos esses problemas apresentados:
Como associar esse gerenciamento de código-fonte com a implantação do
software (por exemplo: o deploy de um site, publicação de uma app, etc.)?
Como associar esse gerenciamento de código-fonte com o backlog / issue
tracker do projeto?
16. Indo além
Qual seria a melhor forma para a colaboração em um projeto open-source:
● Possui um time de desenvolvedores capazes de manipular o código
diretamente
● Toda release ainda precisa passar pela aprovação de um desenvolvedor
"dono" do código-fonte
● O código, por ser aberto, pode acessado por uma infinidade de pessoas na
internet, que não tem o mesmo acesso direto, mas ainda querem poder
mandar as suas contribuições para o projeto
17. Git
Git é um sistema de controle de versão distribuído, gratuito e open source,
criado para pequenos e grandes projetos, com velocidade e eficiência em
mente.
https://git-scm.com/
29. Git guide - Workspace e Index
Adicionar novos arquivos / mudanças no index: git add file1 file2 file3
Escolher mudanças antes de adicionar: git add -p file1 file2 file3
(Stage this hunk [y,n,q,a,d,/,s,e,?]?)
Remover do index: git reset file1 file2 file3
Remover do index e descartar todas as mudanças: git reset --hard
Descartar mudanças no workspace: git checkout -- file1 file2 file3
30. Git guide - Commit
Commitar mudanças do index: git commit
Commitar mudanças do index (com mensagem):
git commit -m "commit message"
Adicionar mudanças no index e commitar: git commit -am "commit message"
32. Git guide - Branches
Criar branch nova: git branch branch-name
Alternar para branch: git checkout branch-name
Criar branch nova e alternar para ela: git checkout -b branch-name
Alternar para um commit específico: git checkout commit-hash
33. Git guide - Enviar dados para remote
Enviar um novo branch: git push -u origin branch-name
Enviar novos commits: git push
34. Git guide - Receber dados de remote
Clonar um repositório: git clone https://github.com/user/test.git
Obter um branch do repositório remoto:
git pull
git checkout branch-name
Obter commits de repositório remoto: git pull
35. Git guide - Helpers
Mostrar status do workspace / index: git status
Mostrar status do workspace / index (versão curta): git status -s
Mostrar log de commits: git log
Mostrar log de commits (versão mais completa): git log --graph --decorate --oneline
Criar um alias: git config --global alias.lg "log --graph --decorate --oneline"
36. Git guide - Diff
Diff do workspace para o último commit: git diff
(equivale a git diff HEAD)
Diff do workspace para os N últimos commits: git diff HEAD~N
Diff do index ao invés do workspace: git diff --staged
Diff entre dois commits/branches/tags: git diff identifier1..identifier2
37. Git guide - Diff
Diff para arquivos específicos: git diff HEAD -- file1 file2 file3
Diff usando ferramenta visual ao invés do terminal: git difftool
Informações adicionais: https://git-scm.com/docs/git-diff
38. Git guide - Diff drivers
As ferramentas que fazem diff entre arquivos são muito boas para comparar
arquivos de texto, logo são muito úteis com arquivos de código fonte.
Entretanto elas perdem a utilidade quando com outros tipos de arquivos, como
arquivos binários, imagens, etc.
39. Git guide - Diff drivers
Felizmente é possível configurar o git para utilizar ferramentas diferentes
dependendo do tipo do arquivo. Seguem alguns exemplos:
Para iOS, ferramenta para comparar arquivos do Core Data (*.xcdatamodel):
https://github.com/chaitanyagupta/XCDataModelPrinter
Ferramenta para comparar diferenças entre imagens:
http://www.akikoskinen.info/image-diffs-with-git/
48. Git guide - Stash
Salvar mudanças no stash: git stash
Salvar mudanças no stash com mensagem: git stash save "stash message"
Listar mudanças no stash: git stash list
Remover última mudança no stash: git stash drop
Remover mudança específica do stash: git stash drop stash-code
Aplicar última mudança do stash: git stash apply
Aplicar mudança específica do stash: git stash apply stash-code
Aplicar última mudança e remover do stash: git stash pop
49. Git guide - Tags
Criar tag: git tag tag-name
Listar tags: git tag
Alternar para tag: git checkout tag-name
Enviar tags para repositório remoto: git push --tags
50. Git guide - Submodules
Submodules é um recurso do Git, que pode ser usado quando um projeto tem
dependência de outro projeto, que por sua vez, possui repositório específico.
Isso permite analisar o histórico desse projeto de forma independente, dentro
do contexto do seu projeto principal. Isso também permite que a dependência
receba atualizações de forma simplificada.
52. Git guide - Hooks
Hooks são scripts que podem ser escritos em diversas linguagens (shell script,
python, etc.) e então adicionados ao repositório na pasta:
.git/hooks
Esses scripts serão executados sempre que uma ação específica acontecer,
como por exemplo, antes de um commit ser executado ou antes de um push
ser executado.
53. Git guide - Hooks
Isso permite diversas customizações como: modificar uma mensagem de commit
incluindo informações adicionais, impedir um commit cuja mensagem não siga um
padrão específico, rejeitar um push em determinadas situações, etc.
Informações adicionais: https://git-scm.com/book/it/v2/Customizing-Git-Git-Hooks
54. Git guide - Alterando a história
O repositório "conta" a história de um projeto. A habilidade de manipular essa
história pode ser muito interessante:
● Modificar mensagem de commits
● Modificar commits
● Deletar commits
● Juntar 2 commits em 1
● Quebrar um commit em 2 partes
● Trocar ordem de commits
● Deletar branches antigas ou
indesejadas
● Reverter um commit
● Desfazer um commit recente e
colocá-lo de volta no index
55. Git guide - Deletando branches
Deletar branches antigas ou indesejadas: git branch -d branch-name
(Obs.: vai falhar se não tiver sido feito um merge para algum outro lugar)
Forçar deletação de branch: git branch -D branch-name
Deletar branch remota: git push origin :branch-name
56. Git guide - Reverter um commit
git commit -m "commit message"
git revert HEAD
58. Git guide - Deletar commit
Deletar commit recente e colocá-lo de volta no index:
git reset HEAD^
Deletar commit recente:
git reset --hard HEAD^
59. Git guide - Rebase interativo
É possível utilizar o comando de rebase no modo interativo para efetuar
diversas tipos de modificações (modificar mensagem do commit, remover
commit, editar commit, juntar 2 commits em 1, dividir commit em múltiplos
commits, trocar ordem de commits):
git rebase -i HEAD~2
pick 75ff03b commit message 1
pick a060de1 commit message 2
60. Git guide - Rebase interativo
p, pick = use commit
r, reword = edit the commit message
e, edit = use commit, but stop for amending
s, squash = use commit, but meld into previous commit
f, fixup = like "squash", but discard this commit's log message
x, exec = run command (the rest of the line) using shell
d, drop = remove commit
61. Git guide - Force push
Sempre que for feita uma alteração em algo que já esteja no repositório
remoto, o push provavelmente será rejeitado. Entretanto é possível forçar o
push utilizando o comando a seguir:
git push --force
62. Git guide - Force push
Forçar um push pode ser perigoso em branches compartilhadas por outras
pessoas, por isso é algo que deve ser evitado.
Cenários problemáticos:
63. Git guide - Force push
● Uma pessoa remove um commit e manda para o repositório remoto. Outra
pessoa que ainda tinha esse commit localmente faz o push novamente e o
commit "ressurge". Nessa situação utilizar um revert teria sido muito melhor.
● Modificar a estrutura das branches utilizando rebase, considerando que a
branch já estava no repositório remoto. Nesse caso todo tipo de bagunça pode
acontecer. Pois pessoas diferentes poderiam enxergar as branches de forma
diferente. Idealmente devemos utilizar o rebase apenas em alterações que ainda
estão apenas locais. Caso contrário, utilizar o merge.
64. Git guide - Alterando a história
Alterar a história de um repositório deve ser feito com muita cautela. Uma ação
descuidada pode causar dor de cabeça. Por sorte, com Git é possível desfazer
quase todas as ações, mesmo as que envolvam deletar branches e commits.
Um guia muito interessante sobre isso:
https://github.com/blog/2019-how-to-undo-almost-anything-with-git
Muito útil em situações de emergência
65. Qual o workflow ideal para meu projeto?
Ferramentas de controle de versão fornecem uma série de recursos e
garantias para um projeto de software, mas definir como a ferramenta deve ser
utilizada é muitas vezes mais importante do que ter a ferramenta disponível.
O git por exemplo, pode ser utilizado de diversas formas, auxiliando projetos
com necessidades diferentes.
Partindo dessas necessidades, o ideal é encontrar qual a forma de trabalho
mais eficiente e moldar o workflow de desenvolvimento e implantação em
torno disso.
66. Qual o workflow ideal para meu projeto?
Alguns pontos para se considerar:
● Como as branches devem ser utilizadas? Devemos ter branches para cada sprint
do projeto? Ou devemos criar branches para tasks específicas?
● Teremos branches para diferenciar o código de desenvolvimento, homologação,
produção? Qual a política para criação de tags?
● Que fluxo deve ser seguido para corrigir um bug em produção ou em
homologação?
● Temos alguma política para as mensagens de commit?
● Devemos referenciar um ticket do issue tracker no commit? Ou no nome de uma
branch?
67. A successful Git branching model
Muitas propostas de modelos de branching foram propostas. Uma das mais
famosas é a chamada "A successful Git branching model" proposta por
Vincent Driessen em 2010:
http://nvie.com/posts/a-successful-git-branching-model/
68.
69. Git flow
O modelo é bastante genérico e permite que ele seja incorporado a diversos
tipos de projetos.
Esse modelo fez tanto sucesso que criaram uma ferramenta específica
chamada Git flow:
http://danielkummer.github.io/git-flow-cheatsheet/
O git flow é instalado como uma ferramenta de linha de comando e estende a
capacidade do Git, fornecendo novos comandos que permitem simplificar o
uso do Git e forçar o uso do modelo de branching de Vincent Driessen.
70. Git flow
Inicializando o repositório: git flow init
Começando uma feature: git flow feature start myfeature
Finalizando uma feature: git flow feature finish myfeature
Publicando uma feature: git flow feature publish myfeature
Obtendo uma feature: git flow feature pull origin myfeature
Começando uma release: git flow release start release
Publicando uma release: git flow release publish release
Finalizando uma release: git flow release finish release
71. Plano de SCM
Apesar do git flow e o modelo de branching de sucesso serem muito
interessantes, eles podem ainda não cobrir cenários específicos de um projeto
ou então podem complicar demais um projeto que requer um modelo muito
mais simples.
Muitos projetos preferem definir o chamado plano de SCM (software
configuration management) com regras mais customizadas para aquele
projeto em específico.
72. Plano de SCM
Geralmente é uma tarefa atribuída a um arquiteto de software e cobre diversas
quesitos como:
● Modelo de branching e gerenciamento do código fonte
● Pessoas envolvidas e seus respectivos papéis
● Ambientes de desenvolvimento / homologação / produção
● Processo de implantação
● Auditoria e métricas
● Testes automatizados
73. Colaboração
Git é uma ferramenta muito interessante para desenvolvimento de software de
forma colaborativa, devido a simplicidade, eficiência, além dos inúmeros
recursos disponíveis.
Ele ganhou bastante destaque em projetos open-source, se tornando o sistema
mais utilizado no mundo.
74. Repositórios na nuvem
● É o mais usado por projetos open source
● Gratuito para repositórios abertos
● Pago para projetos privados
● Possui issue tracker integrado
● Permite a criação de uma wiki
75. Repositórios na nuvem
● Usado em muitas empresas, principal
concorrente do Github
● Gratuito para repositórios abertos e fechados,
porém com limitação de número de usuários
● Permite a criação de uma wiki
● Possui issue tracker simples integrado
● Permite integração com JIRA, um dos
issue trackers pagos mais conhecidos do
mercado
76. Repositórios na nuvem
● Gratuito para repositórios abertos e fechados,
sem restrição de número de repositórios ou
usuários
● Suporte dedicado pago
● Permite criação de wiki
● Possui integração com issue tracker e kanban
● Permite integração com sistema de CI
77. Colaboradores e permissões
Uma vez criado o repositório, este estará visível para todo mundo caso tenha
sido criado como aberto. Essa visibilidade permite que todo mundo consiga
clonar o repositório e ter acesso ao código, mas não permite que nenhum push
seja efetuado. Para conseguir dar um push no repositório o criador deverá
adicionar o usuário como um colaborador do projeto.
Repositórios privados só serão visíveis para o dono do repositório e para os
usuários que este adicionar como colaborador do projeto.
80. Colaboradores e permissões
O criador do repositório ainda pode conceder e revogar permissões de push
para branches específicas.
Também permite conceder e revogar permissões para efetuar o merge em um
pull request.
Isso permite um maior controle e auditoria sobre o que está acontecendo no
repositório.
82. Forks e Pull requests
Pessoas que não são colaboradoras do projeto ainda podem mandar suas
contribuições para o projeto através de um fork do repositório.
Um fork é uma cópia do repositório original, onde o usuário tem total poder e
permissão para modificá-lo (devendo ainda obedecer as regras da licença de
software definida)
83. Forks e Pull requests
Muitas pessoas discordam do caminho que um projeto de software está
tomando e pode utilizar um fork para tomar um repositório como base mas
continuar a mantê-lo da forma que achar mais adequada.
Forks também são criados para dar continuidade em um projeto de software
que parou de receber suporte por um bom tempo.
84. Forks e Pull requests
Por fim, muitos forks são criados como forma de submeter contribuições ao
repositório original:
● O usuário cria um fork
● Efetua as modificações desejadas
● Abre um pull request de uma branch em seu repositório, para uma branch
no repositório oficial
● Um ou mais colaboradores com as devidas permissões consegue analisar
as mudanças e aprovar ou não o pull request. Uma vez aprovado um
merge pode ser efetuado persistindo essas modificações.
85. Forks e Pull requests
Diversos recursos estão disponíveis na criação de um pull request. O usuário pode
adicionar texto, screenshots e até linkar o pull request com uma issue específica na
ferramenta de issue tracker.
O repositório pode ser configurado para que um número mínimo de pessoas precise
aprovar o pull request, antes do merge ser efetuado.
Usuários podem comentar no pull request como um todo, mas também podem
comentar em trechos específicos do código que está sendo submetido.
Isso permite um debate aberto, do porquê algo ser ou não aprovado. Se tornando
inclusive, uma ferramenta interessantíssima para auditoria e Code Review.
86. Forks e Pull requests
Os pull requests também são usados nos casos onde um usuário é
colaborador, mas não tem permissão de push em determinada branch.
Nesse caso ele deverá desenvolver em uma branch à parte e no final criar um
pull request de uma branch para outra no mesmo repositório.
Por fim, algum usuário com permissão conseguirá aprovar e efetuar o merge
das mudanças.
87.
88. Licença de software
A maioria dos repositórios remotos possuem mecanismos simplificados para
adicionar uma licença de software.
Por padrão, caso nenhuma licença seja adicionada, as regras de copyright se aplicam,
isto é, ninguém tem o direito de reproduzir, distribuir e modificar o seu trabalho.
Logo, caso queira que pessoas possam colaborar com seu código, adicione uma
licença de software mais permissiva.
Informações adicionais:
https://help.github.com/articles/open-source-licensing/
http://choosealicense.com/
89.
90. Issue tracker
Os repositórios remotos costumam permitir integrações com sistemas de
issue tracker, que podem ser usados para criar tickets que fazem parte de um
backlog de um projeto.
Os tickets podem ser classificados como tasks, enhancements, bugs, dentre
outros e podem ter um colaborador responsável por ele. Os tickets podem
seguir fluxos complexos desde sua abertura até o fechamento, tudo
dependendo da ferramenta utilizada.
91. Issue tracker
A maioria do repositórios remotos, permite que o ticket seja manipulado
indiretamente através da mensagem de commit ou título/descrição em um pull
request. Exemplo de mensagens capazes de fechar um ticket:
● Close #2
● Fixes #3
● Resolves #1
92.
93. Continuous Integration
Existem inúmeras ferramentas disponíveis no mercado que visam
proporcionar integração / entrega contínua de software, que permitem uma
forma mais automatizada e sem intervenção direta para a geração das builds
de um projeto: Deploy de um site, publicação de uma app, etc. ou até mesmo
para a execução de teste unitário, teste de UI, etc.
Tem se tornado muito comum o uso dessas ferramentas em conjunto com
sistemas de controle de versão como Git.
94. Continuous Integration
Os cenários mais comuns:
● Builds programadas para disparar em intervalos de tempo regulares. Nesse caso,
a cada build a ferramenta irá clonar o repositório novamente ou apenas fazer um
pull para trazer as informações mais recentes.
● Builds configuradas para fazer "pooling" no sistema de controle de versão. A
ferramenta irá consultar o repositório em intervalos de tempo regulares, mas só
vai gerar uma build caso hajam novos commits desde a última build.
● Builds geradas manualmente. Esse tipo de configuração visa apenas tirar o
esforço de gerar builds na máquina do desenvolvedor, mas também permite
customizações através de parâmetros da build.
95. Continuou Integration
● Ferramenta open source
● Disponível para instalação no seu próprio
servidor
● Altamente customizável
● Possui diversos plugins disponíveis para
os mais variados tipos de tecnologias
● Possui capacidades de controle de acesso
e armazenamento de credenciais
96. Continuous Integration
● Integração com Github
● Disponível na nuvem
● Gratuito para repositórios abertos
● Solução mais utilizada por projetos
open source
97. Webhooks
A maioria dos repositórios remotos, ainda permitem adicionar os chamados
webhooks, através de uma interface disponível na web. Os webhooks
permitem que uma URL arbitrária seja chamada quando algum evento no
repositório aconteça, por exemplo:
● Eventos de push do repositório
● Pull request criado
● Issue criada
98. Conteúdo adicional
Cursos do Code School:
● Try Git
● Git real 1 e 2
● Mastering Github
Livros:
● Pro Git -> https://git-scm.com/book
100. Conteúdo adicional
Documentação e ajuda:
● Documentação oficial -> https://git-scm.com/documentation
● Help do Github -> https://help.github.com/
● Atlassian Tutorials -> https://www.atlassian.com/git/tutorials/
101. Prática Git
1. Iniciar um novo repositório
2. Adicionar um arquivo novo
3. Commitar o arquivo
4. Adicionar um arquivo novo
5. Commitar o arquivo
6. Deletar todos os arquivos
7. Commitar a deleção
102. Prática Git
8. Voltar em commits antigos para visualizar os arquivos que foram
apagados
9. Adicionar um novo arquivo
10. Commitar o arquivo
11. Fazer modificações no arquivo
12. Verificar o que está sendo introduzido utilizando um diff
13. Commitar as modificações
14. Criar um repositório no bitbucket
15. Adicionar um remote e fazer o push da branch master
103. 16. Modificar o arquivo novamente
17. Commitar a modificação
18. Fazer push desse commit
19. Criar uma tag
20. Fazer push das tags
21. Criar uma segunda branch e fazer push dela
22. Efetuar 2 commits nessa segunda branch
23. Fazer merge desses 2 commits para a branch master e verificar o fast
forward
24. Efetuar 2 commits na segunda branch
Prática Git
104. 25. Efetuar um commit na branch master, que não dê conflitos com a segunda
branch
26. Fazer merge da segunda branch com a branch master e verificar o commit
de merge
27. Efetuar 2 commits na segunda branch
28. Efetuar um commit na branch master que dê conflitos com a segunda
branch
29. Fazer merge da segunda branch com a branch master e resolver conflitos
30. Efetuar 2 commits na segunda branch
Prática Git
105. 31. Efetuar um commit na branch master, que não dê conflitos com a segunda
branch
32. Efetuar um rebase da segunda branch sobre a branch master
33. Efetuar 2 commits na segunda branch
34. Efetuar um commit na branch master que dê conflitos com a segunda
branch
35. Efetuar um rebase da segunda branch sobre a branch master e resolver
conflitos
Prática Git
106. 36. Efetuar um merge da segunda branch sobre a branch master e verificar
que não há mais conflitos por causa do rebase anterior
37. Clonar um segundo repositório, simulando outro desenvolvedor
38. Efetuar um commit
39. Efetuar um git pull (sem rebase) e verificar o merge feito
40. Clonar um terceiro repositório, simulando outro desenvolvedor
41. Efetuar um commit
42. Efetuar um git pull (com rebase) e verificar a diferença para pull com
merge
Prática Git
107. 43. Modificar um arquivo existente
44. Adicionar parte da mudança com git add -p
45. Salvar a mudança no stash
46. Recuperar a mudança do stash
47. Efetuar um commit da mudança
48. Reverter o último commit
49. Bônus: brincar de alterar a história do repositório local e remoto
Prática Git
108. 1. Criar issues no repositório remoto
2. Fechar issues através da mensagem de commit
3. Criar um pull request de uma branch para outra dentro do mesmo
repositório
4. Criar um fork
5. Criar um pull request de um repositório para outro
6. Criar uma build num sistema de integração contínua e configurar para
utilizar o repositório
Prática Colaboração