Para que serve o comando `git send-email`?
Tags: github, git, braziliandevs
Published: 2021-04-14 02:51:10

O GIT nasceu em um momento que era muito comum programadores e entusiastas se reunirem em comunidades e fóruns para debater e programar. Apesar de existir softwares de versionamentos como o [Bitkeeper](https://www.bitkeeper.org/)(na época pago), não existia (até onde sei) um sistema integrado ao *Git* (lançando em 2005) como o [Github](https://github.com/valdeirpsr), GitLab e Bitbucket, por exemplo.

Em vez disso, alguns programadores utilizavam as trocas de e-mails para enviar correções e novos códigos, através do protocolo SMTP/IMAP, para outros desenvolvedores ou fóruns. Com isso, eles podiam compartilhar seus códigos e ajudar a comunidade.

A vantagem, na época, era a velocidade de transmissão de dados e o custo.

# Como o comando funciona?

Basicamente, ele envia uma coleção de correções feitas por você para o destinatário, que vai poder mesclar as alterações utilizando o comando `git-am`.

O comando permite o uso de dois formatos para envio das correções:

 - Formato *mbox* (veremos adiante)
 - Formato criado por Greg Kroah-hartman (Use por sua conta em risco. Palavras do autor 😁)

# É possível enviar anexos com o comando?

Não. Ele envia apenas texto. Caso queira enviar seu repositório por e-mail, basta usar o comando `git archive` (para comprimir os arquivos com *zip*, *gzip*, *bzip2* ou *xz*) ou `git bundle` (para criar um arquivo compactado com todas as alterações).

# Como enviar correções via e-mail?

### Requisitos

 - Um repositório. Irei usar o https://github.com/valdeirpsr/dotfiles

 - Servidor de e-mail. Irei utilizar o [Mailtrap](https://mailtrap.io/) para simulação de envio.

 - Conhecimento básico de GIT

### Preparando envio

Antes de fazer o envio, precisamos preparar as correções utilizando o comando `git-format-patch` como no exemplo abaixo.

```bash
# No comando abaixo, você pode informar um <commit hash> ou <revision range>
git format-patch 0ac05bd5a72f8d4e6f2d7313689153851a4809e5

# O comando cria um arquivo por <commit>, que será nomeado com "<id>-<assunto do commit>.patch"
# 0001-Update-.bash_aliases.patch
# 0002-Create-.functions.patch
```

> **Observação:** Para incluir um arquivo, use o comando `git format-patch --root -- <file>`

### Conteúdo dos arquivos *.patch

Ao abrir ou imprimir o conteúdo do arquivo na tela, podemos ver que ele possui os cabeçalhos de e-mail (*FROM*, *SUBJECT*, *DATE*) e o corpo da mensagem informando onde ocorreram as alterações.

*OBS.:* Os comentários iniciados com *#* não existem no arquivo original e foram adicionados por motivos didáticos

```bash
# Na linha abaixo temos o <commit-hash>
From 28f8dabbc894ec75a1d8bee86f9de18ad1e7ccd1 Mon Sep 17 00:00:00 2001

# Informações autor
From: Valdeir S. <contact@valdeir.dev>

# Data de criação do <commit>
Date: Sat, 20 Mar 2021 16:17:48 -0300

# Assunto do <commit> (a primeira linha dele)
Subject: [PATCH 1/3] Update .bash_aliases

# Estatísticas das alterações, que
# Apresenta a quantidade de arquivos alterados, criados e deletados
# E a quantidade de caracteres removidos e adicionados
---
 .bash_aliases | 3 ---
 1 file changed, 3 deletions(-)

# Abaixo são destacadas as diferenças entre o snapshot anterior do arquivo com o atual
diff --git a/.bash_aliases b/.bash_aliases

# Index da árvore de trabalho.
# Compare `git show 450e3a9` com `git show 1cdcd5e`
index 450e3a9..1cdcd5e 100644
--- a/.bash_aliases
+++ b/.bash_aliases

# A linha iniciada com "-" significa que a linha foi removida
# A linha iniciada com "+" significa que a linha foi adicionada
# A linha iniciada SEM "-" e SEM "+" significa que não sofreu alterações
@@ -27,9 +27,6 @@ alias myip="dig +short myip.opendns.com @resolver1.opendns.com"
 # Outros
 alias diff="git diff --no-index"

-# Comandos
-command -v calc >> /dev/null || function calc(){ awk "BEGIN{ print $* }" ;}
-
 # Finaliza todos os containers do Docker
 function dockerStopAll() {
   for c in $(docker ps | tail -n +2 | cut -d' ' -f1); do
--
2.31.1.windows.1
```

### Enviando alterações

Para enviar as coleções de correções por e-mail, você pode usar um serviço/servidor de SMTP.
No comando abaixo, são definidas as configurações para o envio; no entanto, elas podem ser armazenadas no arquivo de configuração `~/.gitconfig`

```bash
git send-email \
  --smtp-encryption tls \
  --smtp-server smtp.mailtrap.io \
  --smtp-server-port 587 \
  --smtp-user <hash> \
  --smtp-pass <hash> \
  *.patch
```

### Saída do comando

>     # Lista de arquivos
>     0001-Update-.bash_aliases.patch
>     0002-Create-.functions.patch
>     0003-refactor-remove-o-arquivo-de-configura-o-do-navegado.patch
>     (mbox) Adding cc: Valdeir S. <contact@valdeir.dev> from line 'From: Valdeir S. <contact@valdeir.dev>'
>     
>     # Cabeçalho e corpo do e-mail
>     From: example@valdeir.dev
>     To: exemplo@valdeir.dev
>     Cc: Valdeir S. <contact@valdeir.dev>
>     Subject: [PATCH 1/3] Update-.bash_aliases.patch
>     Date: Mon, 12 Apr 2021 23:29:20 -0300
>     Message-Id: <20210413022926.1198-1-example@valdeir.dev>
>     X-Mailer: git-send-email 2.31.1.windows.1
>     MIME-Version: 1.0
>     Content-Transfer-Encoding: 8bit
>     
>         The Cc list above has been expanded by additional
>         addresses found in the patch commit message. By default
>         send-email prompts before sending whenever this occurs.
>         This behavior is controlled by the sendemail.confirm
>         configuration setting.
>     
>         For additional information, run 'git send-email --help'.
>         To retain the current behavior, but squelch this message,
>         run 'git config --global sendemail.confirm auto'.
>     
>     Send this email? ([y]es|[n]o|[e]dit|[q]uit|[a]ll):

Caso queira enviar as alterações, pressione <kbd>y</kbd> ou <kbd>a</kbd>; e, <kbd>ENTER</kbd>

# Para que serve o comando `format-patch`

Ele é o responsável por preparar os arquivos para cada *commit*, já com os cabeçalhos necessários e o a saída do comando `git diff <commit B>..<commit A>`.

# O que é *MBOX*?

De acordo com a documentação do [FreeBSD](https://www.freebsd.org/cgi/man.cgi?query=mbox), o MBOX é "um arquivo de texto que contém um número arbitrário de mensagens de e-mail. Cada mensagem consiste em um carimbo do correio, seguido por uma mensagem de e-mail formatado de acordo com RFC822 e RFC2822. As linhas são separadas por caracteres de alimentação de linha (ASCII 10)."

# Alguém, em sã consciência, usa isso?

Esta é a única forma de contribuir com alguns projetos como o kernel do Linux ou o próprio GIT.

Caso alguém tenha interesse em contribuir com o Kernel ou apenas queira saber como o fazer, basta acessar a página [enviando correções: o guia essencial para colocar seu código no kernel](https://www.kernel.org/doc/html/latest/process/submitting-patches.html)

# Exemplo de configuração no arquivo `~/.gitconfig`

```
[sendemail]
    smtpEncryption = tls
    smtpServer = smtp.gmail.com
    smtpUser = you@email.com
    smtpServerPort = 587
    smtpPass = Your-pass (Não é recomendável)
    confirm = auto
    replyTo = reply@email.com
```

# Alternativa

Desde a versão [v1.3.0-rc1](https://github.com/git/git/commit/f2561fda364ad984ef1441a80c90b0ee04f1a7c4), o GIT disponibiliza a ferramenta `git-imap-send`. As diferenças são:

**`imap-send`**

 - Envia as alterações para seu programa/provedor de e-mail e salva como rascunho *(é possível configurar outra pasta)*
 - Envia alterações recebidas pela entrada (STDIN) e geradas pelo `format-patch`
 - Comando: `git format-patch --stdout --attach origin <hash> | git imap-send`

**`send-email`**

 - Envia as alterações para o destinatário
 - Envia alterações dos arquivos gerados pelo `format-patch`
 - Comando: `git format-patch -o patches/ <hash> && git send-email patches/*`

# Referências

 - https://public-inbox.org/git/
 - https://github.com/torvalds/linux/pull/805
 - https://git-scm.com/book/pt-br/v2/Distributed-Git-Contributing-to-a-Project
 - https://git-scm.com/book/pt-br/v2/Come%C3%A7ando-Uma-Breve-Hist%C3%B3ria-do-Git
 - https://github.com/gregkh/kroah.com/blob/master/linux/send_lots_of_email.pl
 - https://git-scm.com/docs/git-format-patch/
 - https://www.cisco.com/c/pt_br/support/docs/security/email-security-appliance/117912-qa-cdc-00.html
 - https://en.wikipedia.org/wiki/Mbox