porcellis.com

commit 3a508f3951fb512ead2e62ac13001e33b6a8abb8

Author: Pedro Lucas Porcellis <porcellis@eletrotupi.com>

Add article about git-rebase

I have an english version but will finish later

 content/blog/a-magia-do-git-rebase.md | 130 +++++++++++++++++++++++++++++


diff --git a/content/blog/a-magia-do-git-rebase.md b/content/blog/a-magia-do-git-rebase.md
new file mode 100644
index 0000000000000000000000000000000000000000..f8318465907057dc2624585c1a723fea142b1201
--- /dev/null
+++ b/content/blog/a-magia-do-git-rebase.md
@@ -0,0 +1,130 @@
+---
+title: "A Magia do git rebase"
+date: 2021-04-29
+draft: false
+tags: ["git"]
+---
+
+Uma das ferramentas que eu acho das mais úteis no `git`, e da qual eu [mais
+amo][toot] é o `git-rebase(1)`. Ela se baseia na premissa que trouxe o git para
+o mundo dos sistemas de controle de versão: de que você *pode e deve* alterar a
+história do teu repositório de forma a tornar ele mais legível e organizado.
+
+[toot]: https://alfazema.club/@eletrotupi/105984543604974096
+
+Ao redor do mundo, cada projeto estabelece sua convenção de como trabalhar com o
+git, alguns utilizam técnicas como o git-flow, outros, apenas uma branch e tags,
+outros dividem em duas branchs principais, `master/main` e `production/release`.
+A convenção no meu trabalho, é de sempre criar uma _branch_ específica para
+trabalhar em uma nova funcionalidade, correção de algum erro ou melhoria num
+geral. Feito isso, eu adoto a disciplina de (1) manter ela atualizada com a
+_branch_ pai usando `git pull --rebase origin/branch_pai` e (2) conforme for
+trabalhando nela, procuro manter ela organizada usando o `git rebase -i HEAD~N`.
+
+## Rebase
+
+O rebase tem um funcionamento bastante simples, em essência, ao contrário de
+executar um _merge_ (ou seja, criar um _commit_ que puxa as mudanças para a tua
+branch), o rebase: temporariamente remove os teus patches, puxa os commits da
+_branch_ pai e aplica os teus patches em sequência em cima dessa branch
+atualizada. O benefício aqui é claro: a branch contém apenas uma lista de
+commits com o seu trabalho novo, de forma legível e coerente.
+
+Utilizando o parâmetro `-i` no comando, inicia um _rebase_ interativo, iniciando
+a partir do commit que eu pedi. [^1] Por exemplo, `git rebase -i HEAD~5`, vai
+iniciar um rebase até os meus últimos 5 commits. O _rebase_ vai mostrar o
+seguinte:
+
+[^1]: `HEAD~N`, significa essencialmente a partir do ultimo commit disponível
+  nessa branch até N commits anteriormente.
+
+```ini
+pick 9fdd140 hooks: Flesh out the Hook::Destroy service test
+pick ecb296e resource: Flesh out the resource test
+pick bd115a0 hooks: Generate token when subscribing
+pick fcaba9d hooks: Flesh out the handler test
+pick 3926d4b doc: Add document about testing
+
+# Rebase bed2ff9..3926d4b onto bed2ff9 (5 commands)
+#
+# Commands:
+# p, pick <commit> = use commit
+# r, reword <commit> = use commit, but edit the commit message
+# e, edit <commit> = use commit, but stop for amending
+# s, squash <commit> = use commit, but meld into previous commit
+# f, fixup <commit> = like "squash", but discard this commit's log message
+# x, exec <command> = run command (the rest of the line) using shell
+# b, break = stop here (continue rebase later with 'git rebase --continue')
+# d, drop <commit> = remove commit
+# l, label <label> = label current HEAD with a name
+# t, reset <label> = reset HEAD to a label
+# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
+# .       create a merge commit using the original merge commit's
+# .       message (or the oneline, if no original merge commit was
+# .       specified). Use -c <commit> to reword the commit message.
+#
+# These lines can be re-ordered; they are executed from top to bottom.
+#
+# If you remove a line here THAT COMMIT WILL BE LOST.
+#
+# However, if you remove everything, the rebase will be aborted.
+#
+```
+
+Ou seja, vai me mostrar meus últimos 5 commits, e me pedir para eu escolher
+(`pick` ou `break`), remover (`drop`), editar (`edit` ou `reword`) ou juntar
+eles (`fixup` e `squash`).
+
+## Disciplina
+
+Meu plano de trabalho, em geral é o seguinte: conforme eu avanço no trabalho que
+eu tenho que fazer, commito localmente de forma que eu vagamente consiga
+explicar o que eu fiz. No momento que eu sinto que terminei e já vale de
+apresentar esse trabalho, utilizo o _rebase_ para reescrever, quebrar/juntar
+esses commits em uma narrativa de passos sequenciais mais legíveis e coerente.
+
+Buscando escrever essa narrativa, procuro criar mudanças atômicas que por si só
+sejam responsáveis por responder a pergunta de _o que foi feito?_ e _isso não
+quebra os testes?_ [^2].
+
+[^2]: Ou seja, sem `fix tests`, `fix typo`.
+
+Uma experiência que me ajudou muito nesse propósito, foi o de contribuir com
+projetos que utilizam uma lista de e-mail pública [^3], enviando patches ao
+invés de criar _Pull Requests_. Em especial, porque a lógica de trabalho muda. A
+forma de trabalho apresentada por ferramentas como Github, GitLab e outras
+derivações similares é de criar um PR e infinitamente seguir adicionando commits
+nele até que o trabalho esteja pronto, a interface que se vire para mostrar o
+que realmente é importante. Contudo, a lógica de trabalho do git por email é de
+tentar ser o mais assertivo possível, evitando patchsets [^4] gigantes e com
+mudanças em lugares diferentes. Uma das vantagens de lidar com patchsets, é que
+é possível aplicar uma seleção de patches de um patchset, e pedir revisão dos
+outros que não façam sentido ou necessitem de um trabalho maior naquele momento.
+
+[^3]: Que é o formato de contribuição do qual o git foi feito para funcionar
+  originalmente, exemplos notáveis são a lista de email do Kernel, Alpine Linux,
+  git, cgit, dwm e outras ferramentas da suite suckless, coreutils, musl-libc,
+  freedesktop, vim, emacs, sistemas BSD e por aí vai.
+
+[^4]: Um patch é um commit, e um patchset é uma coleção de patches.
+
+Aplicando essa lógica, procuro sempre quebrar um patchset muito grande em vários
+patchsets diferentes [^5] e com patches atômicos, descritivos, geralmente
+organizado em módulos ou partes [^6].
+
+[^5]: Um exemplo aqui poderia ser organizar _includes_, remover espaços em
+  branco, ou qualquer mudança estética no código que não tenha relação direta
+  com a funcionalidade/correção que seja necessário originalmente.
+
+[^6]: Geralmente adoto o seguinte formato para meus commits: `módulo:
+  sub-módulo, descrição do que esse commit faz` e descrevo o porque essa mudança
+  foi feita e qual abordagem eu tomei no corpo do commit.
+
+Em resumo, o git é fantástico. Ter disciplina para utilizá-lo e aprender como
+ele funciona é uma obrigação de qualquer programador. Uma das principais
+diferenças dele para os outros sistemas de controle de versão que vieram antes é
+justamente que a história de trabalho daquele repositório não é escrita em
+pedra, não é apenas leitura. Aliado a isso o git tem uma extensiva documentação
+offline, disponível para você estudá-lo a respeito nos seus manuais. Recomendo
+fortemente a leitura dessas man pages: git-rebase(1), giteveryday(7) e
+gitrevisions(7).