Como facilitar o fluxo de trabalho de desenvolvimento de sua equipe com Git Hooks
Publicados: 2022-03-10Um dos principais requisitos de trabalho para uma equipe ou um projeto de código aberto é usar um sistema de controle de versão (VCS). O Git é um sistema de controle de versão distribuído gratuito e de código aberto para rastrear alterações no código-fonte durante o desenvolvimento de software. Foi criado por Linus Torvalds em 2005 para o desenvolvimento do kernel Linux. É fácil de aprender e tem uma pegada pequena com desempenho extremamente rápido.
Há uma grande chance de você já ter usado o Git (já que é uma das ferramentas VCS mais populares e bem adotadas disponíveis na comunidade de desenvolvimento), e você provavelmente já tem algum conhecimento sobre staging e commit de seu código por push e pull a partir de um repositório remoto. Este artigo não abordará os fundamentos dos fluxos de trabalho do git, mas se concentrará principalmente nos ganchos do git e em como utilizá-los para obter uma melhor colaboração em sua equipe. Com as equipes crescendo em tamanho, está se tornando ainda mais importante manter os colaboradores alinhados e manter regras diferentes sobre o código.
O que são Git Hooks?
Git hooks são scripts que são acionados quando ações ou eventos específicos são executados em um repositório git. Essas ações são sobre partes do fluxo de trabalho de controle de versão, como confirmação e envio. Hooks podem ser realmente úteis automatizando tarefas em seu fluxo de trabalho git. Por exemplo, eles podem nos ajudar a validar a sintaxe de nossa base de código com base em algumas regras específicas ou executar alguns testes antes de confirmar nossas alterações.
Como defini-los?
Git hooks são um recurso interno, o que significa que podemos acessá-los e começar a usá-los desde que um repositório git seja inicializado. Vamos dar uma olhada mais detalhadamente no que isso significa ao tentar defini-los.
Usando seu terminal favorito, crie um novo repositório git.
mkdir my-new-repository && cd my-new-repository git init ls -la
Você notará que um novo diretório oculto acaba de ser criado. Esta pasta .git
é usada do git para armazenar informações relacionadas ao repositório, como hashes de controle de versão, informações sobre commits, endereços de repositórios remotos e assim por diante. Esta também é a pasta onde os hooks realmente ficam para git .git/hooks
. Você pode encontrar alguns scripts de amostra pré-preenchidos criados automaticamente durante a inicialização. Na verdade, esses são os scripts que serão acionados após ações específicas.
ls .git/hooks
Algumas das amostras que você pode encontrar são:
-
pre-commit.sample
: invocado antes de fazer o commit. -
commit-msg.sample
: edita o arquivo de mensagem no local. -
post-receive.sample
: invocado após a atualização do repositório remoto.
Sob o capô
Agora que sabemos onde podemos encontrar ganchos, vamos dar um passo atrás para entender como eles realmente funcionam.
Os ganchos do Git são baseados em eventos, portanto, desde que executemos um comando git no fluxo de desenvolvimento, o git verificará as pastas de ganchos para descobrir se há um script associado a ser executado. Alguns desses scripts serão executados antes ou depois dessas ações de fluxo de desenvolvimento.
Um bom exemplo para analisarmos e entendermos mais especificamente o fluxo sob o qual os ganchos são acionados é o fluxo de trabalho de confirmação, que é um caso de uso bastante familiar.
Sempre que confirmamos qualquer alteração em nossa base de código, alguns desses ganchos relacionados são acionados na seguinte ordem:
-
pre-commit
: inspeciona o snapshot que está prestes a ser confirmado e verifica o que deve ser confirmado. -
prepare-commit-msg
: permite editar a mensagem padrão antes que o autor do commit a veja. -
commit-msg
: configura a mensagem de commit para um template. -
post-commit
: executa uma ação logo após a conclusão do commit e envia uma notificação, por exemplo.
No repositório acima, vamos agora tentar adicionar alguns scripts pré e pós-commit personalizados para visualizar melhor como os git hooks realmente funcionam.
nano .git/hooks/pre-commit
Adicione o seguinte trecho:
#!/bin/sh echo Changes are about to be committed
Certifique-se de que nossos scripts sejam executáveis:
chmod +x .git/hooks/pre-commit
Repita o processo acima para o script post-commit
:
nano .git/hooks/post-commit
#!/bin/sh echo Changes have been committed
chmod +x .git/hooks/post-commit
Agora podemos adicionar um novo arquivo nano index.html
com um pequeno trecho de HTML apenas para fins de demonstração (não há necessidade de informar os validadores de HTML sobre isso).
<h1>Hello world from our new repository!</h1>
Adicionaremos as alterações em nossa base de código por meio de teste e, em seguida, confirmaremos isso:
git add . git commit
Após a confirmação ter sido processada com sucesso, podemos ver a seguinte saída dos dois scripts adicionados acima:
Changes are about to be committed Changes have been committed
Como esperado, o git acionou ganchos no fluxo de confirmação. Os scripts pre-commit
e post-commit
que foram adicionados estão em execução e serão executados na sequência correta (com base na ordem que mencionamos anteriormente).
Esta foi uma demonstração simples para entender como os scripts de workflow de commit funcionam e como eles são executados. Para obter mais detalhes sobre esse fluxo de trabalho, você pode ler mais na documentação.
No exemplo acima, escolhemos escrever esses dois scripts em bash, mas a verdade é que o git suporta hooks que podem ser escritos em qualquer linguagem de script que desejarmos. Ruby, Python ou JavaScript são ótimas alternativas, desde que definamos o shebang correto na primeira linha do nosso script executável.
Por exemplo, podemos reescrever o hook pre-commit
como um script Node.js como abaixo:
#!/usr/bin/env node console.log("Changes are about to be commited")
Ganchos locais e remotos
Hooks são separados entre local e remoto (ou cliente e servidor). Enquanto os ganchos locais são executados antes ou depois de ações específicas no repositório local, os ganchos remotos são executados antes ou depois de pushs para o servidor. Os locais não podem ser usados para impor políticas, pois sua natureza permite que os desenvolvedores os alterem facilmente. Eles são usados principalmente para seguir algumas diretrizes específicas que queremos aplicar em uma equipe. Caso queiramos ser mais rigorosos e impor algumas políticas para nosso repositório, residimos em ganchos remotos.
Ganchos locais
-
pre-commit
-
prepare-commit-msg
-
commit-msg
-
post-commit
-
applypatch-msg
-
pre-applypatch
-
post-applypatch
-
pre-rebase
-
post-rewrite
-
post-checkout
-
post-merge
-
pre-push
Ganchos Remotos
-
pre-receive
-
update
-
post-receive
Compartilhamento de Ganchos
Os ganchos do Git são sobre compartilhá-los dentro da equipe. Esta é a principal razão de sua existência: promover uma melhor colaboração em equipe, automatizar processos prejudiciais e nos permitir focar apenas nas partes importantes da base de código.
Como dito anteriormente, .git/hooks
é a pasta que hospeda nossos ganchos personalizados, mas isso não é muito útil quando precisamos compartilhar esses scripts dentro da equipe, pois essa pasta não é rastreada pelo git.
Uma boa abordagem para resolver isso é adicionar todos os nossos ganchos personalizados em uma pasta separada dentro do nosso repositório. Por exemplo, podemos adicionar uma pasta .githooks
e salvar os scripts executáveis nela. Então, na inicialização do projeto, podemos copiar explicitamente ou fazer um link simbólico desses scripts para a pasta original para manter nossos hooks .git/hooks
.
find .git/hooks -type l -exec rm {} \\; find .githooks -type f -exec ln -sf ../../{} .git/hooks/ \\;
Como alternativa, se você estiver usando a versão mais recente do git (falando de 2.9
e superior), podemos configurar diretamente o caminho dos ganchos do git para nossa pasta personalizada:
git config core.hooksPath .githooks
Git Hooks Made Easy (um caso de uso de base de código JavaScript)
Existem ferramentas que nos ajudam a integrar ainda mais os git hooks às necessidades de nossa base de código. Especificamente para bases de código JavaScript, existe o Husky com o qual podemos personalizar facilmente ações em eventos git por meio da configuração.
Por exemplo, podemos facilmente fazer o lint do nosso código ou executar alguns testes no evento pre-commit
e continuar com o commit com base no sucesso do linting, do teste ou de ambos.
Isso pode ser feito estendendo a configuração do package.json
simplesmente como:
{ "scripts": { "test": "echo Running tests" }, "devDependencies": { "eslint": "5.16.0", }, "husky": { "hooks": { "pre-commit": "eslint . && npm test", } } }
Conclusão
Neste artigo, descobrimos que diferentes ações realizadas em um repositório git podem, opcionalmente, acionar a execução de scripts personalizados. Esses scripts podem estar sob o controle do desenvolvedor localmente ou gerenciados de forma mais centralizada para uma equipe ou projeto remoto. Também aprendemos que os scripts geralmente são escritos em um shell script como o bash, mas na verdade podem usar quase qualquer linguagem de script, até mesmo JavaScript.
Os ganchos do Git podem ser uma parte realmente poderosa de um fluxo de trabalho bem projetado, e eu o encorajo a experimentá-los e ver o que você pode fazer para seus próprios projetos.