git

amend e rebase existem.

Pull Requests não.

2019 - Cléber Zavadniak

https://medium.com/@cleber.z

Pull Requests

Pull Request

  • Excelente ferramenta de code review.
  • Serve como uma unidade conceitual.
  • Todavia, é etéreo.

Etéreo
Volátil
Temporário

Etéreo
Volátil
Temporário

Sintomas

Commits devem entregar valor!

  • "create structure to new service"
    • Valor entregue: nenhum.

Péssimo

  • Novo comando no Makefile
  • Criação de nova app
  • Modelagem do banco
  • Migrações
  • Endpoint: GET
  • Endpoint: POST
  • Testes
  • Envio de e-mail de notificação

Ideal

  • Suporte a "esqueci minha senha"
  • Fix: bug#42
  • Endpoint de notificações
  • Migração para Django 2.2.5

Exercício mental

  • Cada commit é enviado e analisado individualmente.
  • Quem analisa não faz ideia de qual é o objetivo final.

Pull Request:

"Você poderia, por favor, mexer nisso e nisso no teu código?"

Reação normal:

  • Pra que diabos uma tabela de tokens OAuth2 se não temos integração com OAuth2?
  • Não entra código sem propósito na base.
    • "Vamos precisar disso no futuro" não é um argumento válido!
Commit: "Nova tabela: oauth2_tokens"

Valor!

  • Suporte a "esqueci minha senha"
    • Feature
  • Fix: bug#42
    • Bugfix
  • Endpoint de notificações
    • Feature
  • Migração para Django 2.2.5
    • Mudança significativa na base de código

Commits, não PRs

  • Ninguém mais vê um "PR" depois que ele é aceito.
  • Cada commit é uma entrega completa.
    • A alteração deve ser relevante.
  • Isso te obriga a planejar direito as tarefas.

"Planejar direito as tarefas?"

Processo

  • Tarefas não podem ser muito grandes.
    • Atômicas, mas no sentido de entrega de valor.
  • Desenvolvedor começa a trabalhar sabendo exatamente o que deseja entregar no final.
  • (Algumas equipes costumam fazer associação 1:1 entre commits e User Stories, inclusive.)

DESIGN

  • Curiosamente, isso afeta os designers, também.
  • As "telas" devem aceitar implementação incremental.

Mas como fazer isso?

Fluxo normal

  • Abre um galho com nome descritivo
  • Faz a parte 1
  • Commit
  • Faz a parte 2
  • Commit
  • Faz a parte 3
  • Commit
  • Push
  • Pull Request

Esse fluxo "normal" é terrível!

Fluxo terrível

  • Pedidos de alteração no PR
  • Altera
  • Commit && push
  • Pedidos de alteração no PR
  • Altera
  • Commit && push
  • Pedidos de alteração no PR
  • Altera
  • Commit && push
  • Pedidos de alteração no PR
  • Altera
  • Commit && push

Resultado

  • Parte 1
  • Parte 2
  • Parte 3
  • Fix
  • Fix
  • Improvements
  • Fix
  • Bugfix
  • Fix
  • Improvements
  • Fix
  • Fix
  • Bugfix

amend ao resgate!

amend

  • Faz a parte 1
  • git add . # Contanto que você tenha um bom .gitignore!
  • git commit -m 'Suporte a "esqueci minha senha"'
  • Faz a parte 2
  • git add . && git commit -amend -C HEAD
  • Faz a parte 3
  • git add . && git commit -amend -C HEAD
  • git push
  • Pull Request

Resultado

  • Entrega feita em 1 commit.
  • Code review ajuda a melhorar o commit.
    • E não "melhorar o Pull Request".
      • Porque o PR não existe.
  • Code review longo não prejudica a legibilidade do histórico.

Em paralelo

Numa equipe

  • Várias pessoas trabalhando na mesma base de código.
  • Galho de origem muda enquanto você trabalha numa tarefa.

Método comum

  • Novo galho a partir do galho-mestre
  • Brás Cubas: Trabalha na feature 1
  • Quincas Borba: Trabalha na feature 2
  • Brás Cubas: merge na master
  • Quincas Borba: merge na master

Problemas

  • Merges geralmente grandes e complicados.
  • Você provavelmente estará trabalhando numa base de código desatualizada por um bom tempo...
  • Coisas imprevisíveis podem acontecer.

Exemplo

  • Novo galho a partir do galho-mestre.
  • Brás Cubas: implementando "esqueci minha senha".
  • Quincas Borba: upgrade para Django 2.2.5 .
  • Quincas Borba: merge no galho-mestre.
  • Brás Cubas: prosseguindo no seu trabalho.
    • Ainda na versão anterior do framework.
    • Muita coisa já deveria estar sendo feita de forma diferente.
    • Só ficará sabendo quando terminar sua tarefa.
    • Potencialmente fará muita coisa pensando em Django < 2.2.5 .

Solução: serialização

Serialização

  • Só se começa a trabalhar a partir da versão mais atual.
  • Uma alteração por vez, sem exceções.
  • Só se faz merge para o galho-mestre.

Exemplo

  • branch do Quincas Borba → Epsilo
  • Delta → branch do Quincas Borba
  • branch do Brás Cubas → Delta
  • Gama → branch do Brás Cubas
  • Beta
  • Alfa

(Leia de baixo para cima)

Certo?

Mas... mas...

As pessoas trabalham paralelamente!

git rebase master

  • Começo do teu commit ← versão mais atual do galho-mestre
  • Eu vou garantindo que "sou o próximo" conforme os outros vão integrando suas mudanças.

Fluxo

  • git checkout master  # Atualiza o
  • git pull             # galho-mestre local
  • git checkout esqueci-minha-senha
  • git rebase master
  • Se houver diferenças, resolvê-las agora.

"Simple Git Workflow For Continuous Delivery"

by leesmith

https://gist.github.com/leesmith/8441773

Processo

  • Atualizar o galho-mestre local todo dia.
  • Se houve alterações, rebase nos feature branches.

Resultado

  • Todo commit:
    • É uma entrega completa.
    • É uma alteração baseada no último commit do galho-mestre.
  • Todo merge é para dentro do galho-mestre.
  • Histórico claro.
  • Merges (durante os rebases) geralmente mais simples.
    • A maioria acaba sendo fast-forwarded, de qualquer forma...

Ademais...

  • Mesmo sem fazer rebase, você faz "rebases".
    • Você criou o feature branch no mês passado.
    • Muita coisa mudou no galho-mestre.
    • Ao fazer o merge:
      • Você será confrontado com toda alteração que não seria fast-forwarded durante os rebases.

Ou seja

  • É o mesmo trabalho.
  • Só que mais implícito.
    • E "explícito é melhor do que implícito".
  • E mais volumoso.
    • A complexidade tende a aumentar de maneira exponencial, não linear.

Fim

  • Pull Requests não existem
  • Commits devem entregar valor completo individualmente
  • git commit -amend -C HEAD
  • git rebase master

https://medium.com/@cleber.z

git

By Cléber Zavadniak