Caos familiar nos nomes dos commits. Uma imagem familiar?Certamente você conhece o
fluxo git . Este é um ótimo conjunto de convenções de ramificação no Git. Está bem documentado e amplamente distribuído. Geralmente, estamos familiarizados com a ramificação correta e falamos muito sobre isso, mas, infelizmente, prestamos muito pouca atenção à questão dos commits de nomeação, e é por isso que as mensagens no Git geralmente são escritas de forma sistemática.
Meu nome é Yerzhan Tashbenbetov, trabalho em uma das equipes do Yandex.Market. E hoje vou contar aos leitores da Habr quais ferramentas usamos para criar comprometimentos significativos em uma equipe. Convido você a participar da discussão sobre este tópico.
A falta de acordo sobre nomear commits dificulta o trabalho com a história no Git. Isso estava em nossa equipe. Antes de usar regras comuns para todos e implementar a automação, as confirmações típicas eram da seguinte maneira:
SECRETMRKT-700: , . SECRETMRKT-701, SECRETMRKT-702: ...
Primeiro, cada desenvolvedor escreveu as mensagens como ele queria: alguém descreveu a tarefa, alguém listou as alterações feitas, alguém usou um gerador de frases aleatórias. Tudo estava em desacordo. Em segundo lugar, os números de tarefas presentes em confirmações frequentemente encurtam o texto útil. Tudo isso dificultava o trabalho eficaz com a história no Git.
Por esse motivo, implementamos o padrão
Commits Convencionais na equipe, começamos a gerar confirmações no
commitizen do utilitário do console e verificamos o resultado usando o
commitlint . Como resultado, as confirmações foram alteradas e têm a seguinte aparência:
refactor(tutorial): feat(products): fix(products):
Lendo a história e reconhecendo as mudanças, ficou mais fácil. Não nos recusamos a especificar números de tarefas; tudo foi cuidadosamente transferido para confirmações de acordo com a
convenção de confirmações convencionais .
Em seguida, mostrarei como obter um pedido semelhante no Git.
Práticas recomendadas, recomendações e soluções comuns para nomear confirmações
Se você tentar entender quais práticas são usadas no setor, poderá encontrar as seguintes opções:
- Artigos com dicas gerais para escrever confirmações. Na maioria das vezes, eles são bastante lógicos e abrem um bom tópico, mas há uma sensação de desordem e falta de uma solução abrangente para o problema.
- Padrões para confirmação de escrita. Existem alguns deles. São documentos com uma lista clara de regras, muitas vezes escritas especificamente para uma grande biblioteca ou estrutura. Esses padrões impressionam com uma abordagem sistemática, popularidade e suporte na comunidade de código aberto.
Precisamos de mais ordem nos commits!
A
metodologia de compromissos convencionais se destaca de outros padrões e merece uma análise cuidadosa por várias razões:
- Está bem documentado e projetado. Sua especificação fornece respostas para as perguntas mais comuns.
- Os criadores da convenção foram inspirados pelos requisitos para confirmação de escrita, que são usados na estrutura AngularJS popular e testada pelo tempo.
- As regras da convenção são seguidas por várias bibliotecas de código aberto grandes e populares (como yargs e lerna ).
- Para as vantagens, vou tomar os preparativos para a formação automática de notas de versão e log de alterações.
Um exemplo de compromisso com este padrão: fix(products): - . : SECRETMRKT-578, SECRETMRKT-602
Pontos-chave dos compromissos convencionais
- O desenvolvedor deve aderir à seguinte estrutura de consolidação:
<type> (<scope>): <subject>
<body>
<footer>
- O commit deve ter um cabeçalho, talvez um corpo e um rodapé.
- O cabeçalho do commit deve começar com um tipo indicando as especificidades das alterações feitas na base de código e terminar com uma descrição.
- Juntamente com a façanha obrigatória, correção (cujo uso é estritamente regulamentado), outros tipos são permitidos.
- Uma confirmação pode ter um escopo . Caracteriza um pedaço de código que foi afetado pelas alterações. A área segue o tipo de confirmação. O padrão não regula uma lista clara de áreas. Exemplos de áreas: eslint, git, analytics, etc.
- A descrição da confirmação deve ser imediatamente após o tipo / área.
- O corpo da confirmação pode ser usado para detalhar as alterações. O corpo deve ser separado da descrição por uma linha vazia.
- O rodapé deve ser usado para especificar links externos, o contexto do commit ou outras informações meta. O rodapé deve ser separado do corpo por uma linha vazia.
Além das regras listadas na convenção, usamos as seguintes recomendações populares:
- No corpo do commit, escrevemos o que foi alterado e por quê .
- Usamos os seguintes tipos de confirmações:
construir | Construir um projeto ou alterar dependências externas |
ci | Configuração e script de IC |
docs | Atualização da documentação |
façanha | Adicionando nova funcionalidade |
consertar | Bug fix |
perf | Alterações na melhoria de desempenho |
refatorar | Edição de código sem correção de bugs ou adição de novos recursos |
reverter | Reversão para confirmações anteriores |
estilo | Edições de estilo de código (guias, recuos, pontos, vírgulas etc.) |
teste | Adicionando testes |
- Nós escrevemos a descrição em clima imperativo , assim como o próprio Git.
Mesclar ramificação 'fix / SECRETMRKT-749-fix-typos-in-títulos'
- Não faça upload da descrição de confirmação com sinais de pontuação.
Padrão Commits Convencional usado por colaboradores da lerna
Como simplesmente mudar para o nome correto de confirmações?
Precisa adicionar automação e conveniência. Para resolver esse problema, precisamos de duas ferramentas: o gerador de confirmação e a ninhada de confirmação, configurados para verificação antes de enviar para o repositório.
Configurar o utilitário commitizen
Essa ferramenta permite gerar confirmações usando o assistente interno. Além disso, o commitizen é bem suportado pela comunidade e, graças a módulos adicionais, é altamente personalizável.
- Instale o utilitário commitizen globalmente (você pode precisar de direitos de administrador).
npm i -g commitizen
- Em seguida, instale o adaptador cz-personalizável . É necessário configurar o modelo com perguntas usadas pelo utilitário commitizen .
npm i -D cz-customizable
- Vamos criar o arquivo commitizen.js, é necessário configurar o cz-customizáveis. Coloque o arquivo criado no diretório ./config/git. Eu recomendo não desarrumar a raiz do projeto com arquivos de configuração e tentar agrupar os arquivos em uma pasta preparada para isso. Conteúdo:
Mostrar commitizen.js "use strict"; module.exports = {
- Adicione links ao cz-customizáveis e ao arquivo de configuração criado anteriormente em package.json:
Mostrar parte do package.json { "config": { "commitizen": { "path": "node_modules/cz-customizable" }, "cz-customizable": { "config": "config/git/commitizen.js" } }, }
- Vamos verificar o resultado. Digite o seguinte comando no terminal:
git cz
O assistente do commitizen primeiro coletará informações sobre o tipo, a área do commit, depois solicitará sequencialmente o texto que estará na descrição, no corpo, no rodapé e, após o seu consentimento, criará um commit.
Certifique-se de olhar o exemplo do utilitário commitizen configurado e do adaptador cz-cusomizable conectado a ele
Configurar utilitários husky e commitlint
- Instale husky e commitlint no projeto:
npm i -D husky @commitlint/cli
- Com o husky, adicionaremos uma verificação de confirmação. Para fazer isso, em package.json, imediatamente após os scripts, adicione o seguinte gancho e indique nele um link para o arquivo commitlint.js:
Mostrar parte do package.json { "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "husky": { "hooks": { "commit-msg": "commitlint -E HUSKY_GIT_PARAMS -g './config/git/commitlint.js'" } }, "devDependencies": { "@commitlint/cli": "^7.2.1", "husky": "^1.1.3", }
- Crie o arquivo commitlint.js necessário para que o linter funcione corretamente. Coloque o arquivo criado no diretório ./config/git. Conteúdo do arquivo:
Só isso. Agora todas as confirmações serão verificadas antes de serem enviadas ao repositório :)
Certifique-se de olhar o exemplo do utilitário commitlint configurado
Então, o que escolher commitizen ou commitlint?
Tanto isso quanto outro! Em conjunto, eles trazem excelentes resultados: o primeiro gera confirmações, o segundo os verifica.
Por que os padrões recomendam o uso do imperativo?
Esta é uma pergunta extremamente interessante. Uma confirmação é uma alteração de código; uma mensagem em uma confirmação pode ser considerada como instruções para alterar esse código. Faça, altere, adicione, atualize, corrija - estas são instruções específicas para o desenvolvedor.
A propósito, o imperativo é recomendado no
sistema de versão do
Git :
[[imperative-mood]] Describe your changes in imperative mood, eg "make xyzzy do frotz" instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy to do frotz", as if you are giving orders to the codebase to change its behavior.
Por que seguir algumas convenções? Vale a pena o tempo? Qual é o lucro?
Vale a pena. Em geral, notei que estávamos mais dispostos a detalhar as alterações feitas na base de código. No corpo do commit, descrevemos em detalhes por que tivemos que usar essas ou aquelas soluções. Compreender a história se tornou objetivamente mais fácil. Além disso, nosso produto está em desenvolvimento e esperamos reabastecimento na equipe. Estou certo de que, graças à introdução do padrão e da automação, será mais fácil a integração dos iniciantes no processo de desenvolvimento.
Experimente e compartilhe o resultado.
Links úteis: