Git avançado
boas práticas e como usá-lo com mais eficiência
Matheus Tavares MAC0475
[Link]@[Link]
1
Agenda
1. Como o Git funciona?
2. Como os comandos operam?
a. Checkout e Branch
b. Merge Aumenta
c. Rebase o nível de
3. Boas práticas de commits abstração
4. Trabalhando com remotes
5. Workflows e modelos de branching
6. CI / CD
2
[Link]
3
[Link]
4
[Link]
[Link]
5
Um pouco de como o
Git funciona
6
Uma grande HashTable
.git/objects tree (302a13)
302a1312fe7...
blob (2cb21a)
2cb21a514d3...
co em
commit
m dis
02fe29472ed...
pr
(02fe29)
im co
cb4210e527a...
id
os
f24e8080923... tree (cb4210)
19e541d2227... blob (f24e80)
... commit
(19e541)
7
Relações entre os objetos
$ tree repo
tree (302a13)
repo
├── README README ● blob (2cb21a)
└── src src ●
├── main.c
└── Makefile tree (cb4210) blob (f24e80)
main.c ●
Makefile ●
blob (64f321)
8
Relações entre os objetos
872a12
● Um commit
guarda o tree (302a13)
estado atual do README ● blob (2cb21a)
projeto (uma src ●
tree, não um
diff). tree (cb4210) blob (f24e80)
main.c ●
Makefile ●
blob (64f321)
9
Relações entre os objetos
commit
872a12 (872a12)
autor
● Commits data
também contém tree (302a13) pais[ ]
um conjunto de README ● blob (2cb21a)
metadados. src ●
tree (cb4210) blob (f24e80)
main.c ●
Makefile ●
blob (64f321)
10
Relações entre os objetos
872a12
$ vim README
$ git commit tree (302a13)
README ● blob (2cb21a)
src ●
tree (cb4210) blob (f24e80)
main.c ●
Makefile ●
blob (64f321)
11
Relações entre os objetos
872a12 ab5421
$ vim README
$ git commit tree (302a13) tree (87ae50)
README ● blob (2cb21a) README ●
src ●
src ●
tree (cb4210) blob (f24e80)
main.c ●
Makefile ●
blob (2290a2)
blob (64f321)
12
Grafo Acíclico Dirigido (DAG, pros íntimos)
872a12 ab5421
$ vim README
$ git commit tree (302a13) tree (87ae50)
README ● blob (2cb21a) README ●
src ●
src ●
tree (cb4210) blob (f24e80)
main.c ●
Makefile ●
blob (2290a2)
blob (64f321)
13
Referências
● Branches
● Tags HEAD
● HEAD
master
a02f3d 02fe29 872a12
14
Referências: branches
$ git branch feature
HEAD
master
a02f3d 02fe29 872a12
15
Referências: branches
$ git branch feature
HEAD
master
a02f3d 02fe29 872a12
feature
16
Referências: branches
$ git commit
HEAD
master
a02f3d 02fe29 872a12 65bfe3
feature
17
Referências: branches
$ git checkout feature
master
a02f3d 02fe29 872a12 65bfe3
feature
HEAD
18
Referências: branches
$ git commit
master
a02f3d 02fe29 872a12 65bfe3
330ab0
feature HEAD
19
Referências: branches
$ git checkout 02fe29
HEAD master
a02f3d 02fe29 872a12 65bfe3
330ab0
feature
20
Referências: branches
$ git checkout 02fe29
You are in “detached HEAD” state.
HEAD master
a02f3d 02fe29 872a12 65bfe3
330ab0
feature
21
Referências: branches
$ git commit
HEAD master
a02f3d 02fe29 872a12 65bfe3
330ab0
feature
22
Referências: branches
$ git commit HEAD
002ab2 master
a02f3d 02fe29 872a12 65bfe3
330ab0
feature
23
Referências: branches
$ git checkout master HEAD
002ab2 master
a02f3d 02fe29 872a12 65bfe3
330ab0
feature
24
Referências: branches
$ git gc --auto HEAD
002ab2 master
a02f3d 02fe29 872a12 65bfe3
330ab0
feature
25
Referências: branches
$ git gc --auto HEAD
master
a02f3d 02fe29 872a12 65bfe3
330ab0
feature
26
Referências: tags
$ git tag v1.0 02fe29 HEAD
master
a02f3d 02fe29 872a12 65bfe3
v1.0 330ab0
feature
27
Referências: tags
$ git checkout v1.0
master
a02f3d 02fe29 872a12 65bfe3
v1.0 330ab0
HEAD feature
28
Referências: tags
$ git commit
HEAD
fe2310 master
a02f3d 02fe29 872a12 65bfe3
v1.0 330ab0
feature
29
Merging
30
[Link]
31
Merging
HEAD
$ git merge feature
next
a02f3d 02fe29 872a12 982cd6 62ae6f
b92efd
feature
32
Merging
HEAD
$ git merge feature
next
a02f3d 02fe29 872a12 982cd6 62ae6f
b92efd
feature
33
Merging
HEAD
A tree apontada pelo commit 73ba2d vai conter as
mudanças introduzidas pelos dois commits pais com
next
relação ao primeiro ancestral comum entre eles.
a02f3d 02fe29 872a12 982cd6 62ae6f 73ba2d
b92efd
O chamado “tree-way merge”
feature
34
Three-way merging
Base next feature
... ... ...
if (enemy == “grievous”) if (enemy == “grievous”) if (enemy == “grievous” && am_I_obiwan())
printf(“hello\n”); printf(“hello there\n”); printf(“hello\n”);
Result
...
if (enemy == “grievous” && am_I_obiwan())
printf(“hello there\n”);
35
Three-way merging
Base next feature
... ... ...
if (enemy == “grievous”) if (enemy == “grievous”) if (enemy == “grievous” && am_I_obiwan())
printf(“hello\n”); printf(“hello there\n”); printf(“Olá\n”);
36
Three-way merging
Base next feature
... ... ...
if (enemy == “grievous”) if (enemy == “grievous”) if (enemy == “grievous” && am_I_obiwan())
printf(“hello\n”); printf(“hello there\n”); printf(“Olá\n”);
Result
37
Three-way merging
Base next feature
... ... ...
if (enemy == “grievous”) if (enemy == “grievous”) if (enemy == “grievous” && am_I_obiwan())
printf(“hello\n”); printf(“hello there\n”); printf(“Olá\n”);
Result
38
Resolvendo conflitos
● Entenda porque next e
... feature modificaram aquela
if (enemy == “grievous” && am_I_obiwan()) linha.
<<<<<<< HEAD
printf("hello there\n"); ● Escolha o lado a ser mantido,
======= ou
printf("Olá\n”);
>>>>>>> feature ● Faça uma “mistura” dos dois.
39
Resolvendo conflitos
● Entenda porque next e
... feature modificaram aquela
if (enemy == “grievous” && am_I_obiwan()) linha.
printf("Olá a todos\n”)
● Escolha o lado a ser mantido,
ou
● Faça uma “mistura” dos dois.
40
Resolvendo conflitos
$ git add greetings.c
...
if (enemy == “grievous” && am_I_obiwan())
$ git merge --continue
printf("Olá a todos\n”)
41
Rebase:
alterando o
passado
[Link]
42
Rebase
HEAD
next
a02f3d 02fe29 872a12 982cd6 62ae6f
b92efd
feature
43
Rebase
HEAD
$ git rebase feature
next
a02f3d 02fe29 872a12 982cd6 62ae6f
b92efd
feature
44
Rebase
HEAD
$ git rebase feature
next
a02f3d 02fe29 872a12 982cd6 62ae6f
b92efd
feature
45
Rebase
HEAD
$ git rebase feature
next
a02f3d 02fe29 872a12 982cd6 62ae6f
b92efd 01a2f1 13dd21
feature
46
Rebase
HEAD
$ git rebase origin/master
next
a02f3d 02fe29 872a12 982cd6 62ae6f
b92efd 01a2f1 13dd21
feature
47
Rebase
HEAD
$ git gc
next
a02f3d 02fe29 872a12 982cd6 62ae6f
b92efd 01a2f1 13dd21
feature
48
Rebase
HEAD
$ git gc
next
a02f3d 02fe29 872a12
b92efd 01a2f1 13dd21
feature
49
Rebase
HEAD
● O resultado final é parecido com o merge.
next
a02f3d 02fe29 872a12
b92efd 01a2f1 13dd21
feature
50
Rebase
HEAD
● O resultado final é parecido com o merge.
● Mas o histórico de next foi alterado!! next
next
a02f3d 02fe29 872a12 982cd6 62ae6f
b92efd 01a2f1 13dd21
feature
51
Regra de ouro do Rebase
● Alterar o histórico de uma branch local,
antes de um push, para organizar seus
commits, é uma ótima prática!
● Alterar o histórico de uma branch
pública, já utilizada por outros como
base para seus trabalhos, é uma má
prática! [Link]
52
$ git rebase -i
Te permite as seguintes operações sobre os commits passados:
● Adicionar
● Remover
● Reordenar
● Editar
● Juntar dois ou mais commits em um
● Executar um comando para cada commit
(muito útil para rodar os testes para cada commit em uma branch)
53
Boas práticas de
Commits
54
Parece uma boa ideia...
$ vim file.c
$ git add .
$ git commit -m “Update file.c”
$ git push origin master
55
… até que você precise
relembrar o que fez.
[Link]
ads/2018/10/[Link]
56
Dissecando um bom commit
1. Mudanças não correlacionadas pertencem a commits separados.
2. Não commitar blocos de trabalho incompletos.
3. Invista na escrita de mensagens de commit informativas.
57
1. Mudanças não correlacionadas pertencem a commits
separados.
● Mais fácil de revisar (→ melhores revisões → melhor código)
● Mais fácil de reverter
● Mais fácil de integrar com outros commits e branches. (i.e. é mais
fácil de resolver conflitos de merge)
58
1. Mudanças não correlacionadas pertencem a commits
separados.
59
2. Não commitar blocos de trabalho incompletos.
● Commits devem ser justificáveis por si só. (Embora um commit possa
depender de outro)
● É legal garantir que cada commit seja compilável e passe os testes.
(→ melhor usabilidade do git-bisect)
60
2. Não commitar blocos de trabalho incompletos.
Esses commits podem ser unidos em um.
61
3. Invista na escrita de mensagens de commit
informativas.
“a well-crafted Git commit message is the best way to communicate
context about a change to fellow developers (and indeed to [your future
self]). A diff will tell you what changed, but only the commit message can
properly tell you why.”
- Chris Beams ([Link]
62
3. Invista na escrita de mensagens de commit
informativas.
● Descreva o problema: o que não está legal no código atual?
● Justifique como as mudanças resolvem o problema: porque o
estado do projeto após este commit é melhor do que o atual?
● Alternativas descartadas [opcional]: existem outros modos de
implementar a mudança? Se sim, porque este foi escolhido?
Dica:
git commit -v ou
git config --global [Link] true
63
O formato da mensagem também é importante
Título resumindo as mudanças em até 50 chars
Corpo, separado do título por uma linha em branco, e
justificado em 72 colunas. Explica a mudança em mais
detalhes, como descrito no slide anterior. (Para mudanças
triviais, pode ser omitido.)
Normalmente:
O corpo pode ter múltiplos parágrafos e também: ● No imperativo
● Não pontuado
- Bullet points
● Primeira letra
- Tabelas ou outros
em maiúsculo
Trailers
64
O formato da mensagem também é importante
Trailers:
○ Closes #21
○ Fix #53
○ Signed-off-by: A U Thor <author@[Link]>
○ Co-authored-by: A U Thor <author@[Link]>
○ Reviewed-by: A U Thor <author@[Link]>
○ Reported-by: A U Thor <author@[Link]>
○ Acked-by: A U Thor <author@[Link]>
65
Dissecando um bom commit
Exemplo 1)
66
Porque isso é importante mesmo?
Vamos para um Exemplo!
(entendendo uma linha de código com git-blame + git-show)
67
Trabalhando com
Remotes
68
Remote
● Um repositório remoto relativo ao mesmo projeto. (e.g. “origin”)
○ $ git push origin master → “envie p/ a branch ‘master’ do
repositório remoto ‘origin’”
● Você pode ter vários remotes (e.g. o repositório upstream, o seu
fork, o fork de um colega, ...)
○ $ git remote add john [Link]
69
Remote Branches
● .git/refs/heads/* (local branches) Nota: pode estar
também em
● .git/refs/remotes/* (remote branches)
.git/packed-refs
○ e.g. .git/refs/remotes/origin/master (formato mais eficiente)
70
Remote Branches
$ git clone
master local branch
a02f3d 02fe29 872a12
origin/master remote branch
71
Remote Branches
$ git commit (2x)
master
a02f3d 02fe29 872a12 982cd6 62ae6f
origin/master
72
Remote Branches
$ git fetch origin
master
a02f3d 02fe29 872a12 982cd6 62ae6f
b92efd
origin/master
73
Remote Branches
$ git merge origin/master
master
a02f3d 02fe29 872a12 982cd6 62ae6f 73ba2d
b92efd
origin/master
74
Remote Branches
● O que acabamos de fazer é exatamente o que faz o
comando git pull :) master
a02f3d 02fe29 872a12 982cd6 62ae6f 73ba2d
b92efd
origin/master
75
Remote Branches
● Alternativa: $ git pull --rebase
a02f3d 02fe29 872a12 master
b92efd 982cd6 62ae6f
origin/master
76
Workflows & Modelos
de Branching
77
Git Flow
● Mecanismo de “graduação” de branches.
Possivelmente, com branches de acesso
restrito.
● Topic branches de longa-duração.
● Custo de integração é consideravelmente
alto.
[Link]
● A master só contém código já validado e
lançado.
78
Trunk Based Development (TBD)
● Desenvolvedores trabalham mais próximo à
branch principal.
● Topic branches de curta-duração.
● Integração rápida e contínua → garante
integrações mais fluidas e menos merge conflicts.
● A master frequentemente contém features
[Link]
incompletas, geralmente escondidas com feature
flags.
79
TBD: algumas ressalvas
● Alguns defendem pushs direto na origin/master. Se for usar este modelo:
○ Pair programming é fundamental.
○ Também um bom CI / bateria de testes.
○ É interessante usar git pull --rebase
● Alternativamente, use topic branches de curta duração, com Pull/Merge
Request e revisões
○ Use git rebase -i para corrigir problemas em sua branch.
○ Use git push -f para a respectiva branch remota, para atualizar o P/MR.
80
CI / CD no GitLab
(similar p/ GitHub e outros)
81
Continuous Integration, Delivery e Deployment
● Continuous Integration: integrar as mudanças dos desenvolvedores à base
de código de forma contínua e rápida (até mesmo múltiplas vezes ao dia).
○ Objetiva evitar problemas de integração tardia, quando os códigos já
divergiram muito.
○ Viabilizada pelo uso de testes (unitários e de integração) automatizados.
Geralmente com uma infraestrutura própria para testar cada commit e
informar se ele é integrável.
82
Continuous Integration, Delivery e Deployment
● Continuous Delivery: “manter a base de código entregável (deliverable) a
qualquer momento”.
○ Nesta fase, o servidor roda processos automatizados de build e
packaging, permitindo que a aplicação esteja pronta para ser lançada,
quando desejado.
● Continuous Deployment: Um passo além: não só constrói o deliverable como
também faz o deploy da aplicação de forma automática e contínua.
83
Continuous Integration, Delivery e Deployment
● Automatizar fases do processo de desenvolvimento.
○ Mitiga possibilidades de erros e bugs
○ Acelera o desenvolvimento
○ Integração muito boa com Métodos Ágeis
84
CI / CD no GitLab
● [Link]
odologies
● Arquivo YAML “.[Link]”:
before_script: <install dependencies>
job1:
script: <run tests> “pipeline”
job2:
script: <build application>
85
Exemplo 1) CI p/ teste de programas em lua
86
Exemplo 2) CI / CD p/ GitLab Pages c/ Jekyll
87
Referências
1. Pro Git, Scott Chacon and Ben Straub:
[Link]
2. Git Docs: [Link]
3. How to Write a Git Commit Message,
Criss Beans:
[Link]
4. Developer Tip: Keep Your Commits
“Atomic”, Sean Patterson:
[Link]
ommits/
5. The Zen of Git, Tianyu Pu:
[Link]
n-of-git
88
Referências II
6. Git For Computer Scientists, Tommi
Virtanen:
[Link]
r-scientists/
7. [Link]
8. Trunk-based Development vs. Git Flow,
Konrad Gadzinowski:
[Link]
based-development-git-flow
9. What is Continuous Integration, Max
Rehkopf:
[Link]
very/continuous-integration
89
Obrigado!
[Link]
90
Some Extra Git Tips
● $ git help glossary contém definições sobre nomenclaturas usadas no Git.
● $ git help workflows contém dicas de workflows no estilo Git Flow.
● Sempre rode status antes de um reset
● Use o git-config para definir configurações default (e.g. [Link])
● Use o git-reflog. Muito útil para recuperar o que aparentemente foi perdido!
● Quando tiver problemas, leia com calma a mensagem de erro. Entendendo as
nomenclaturas e estruturas do Git, as mensagens são intuitivas.
91