Os commits são uma das partes principais de um repositório Git, e mais ainda, a mensagem de confirmação é um registro de vida para o repositório. Conforme o projeto / repositório evolui ao longo do tempo (novos recursos sendo adicionados, bugs sendo corrigidos, arquitetura sendo refatorada), as mensagens de commit são o lugar onde se pode ver o que foi alterado e como. Portanto, é importante que essas mensagens reflitam a mudança subjacente de uma maneira curta e precisa.
Por que um histórico de commit do Git significativo é importante
O que o commit do Git faz? Mensagens de commit do Git são as impressões digitais que você deixa no código em que toca. Qualquer código que você enviar hoje, daqui a um ano, quando olhar para a mesma mudança; você ficaria grato por uma mensagem de confirmação clara e significativa que escreveu, e também facilite a vida de seus colegas desenvolvedores. Quando os commits são isolados com base no contexto, um bug que foi introduzido por um certo commit se torna mais rápido de encontrar, e mais fácil é reverter o commit que causou o bug em primeiro lugar.
Ao trabalhar em um grande projeto, frequentemente lidamos com muitas partes móveis que são atualizadas, adicionadas ou removidas. Garantir que as mensagens de confirmação sejam mantidas em tais casos pode ser complicado, especialmente quando o desenvolvimento se estende por vários dias, semanas ou até meses. Para simplificar o esforço de manter No histórico de commits, este artigo usará algumas das situações comuns que um desenvolvedor pode enfrentar ao trabalhar em um repositório Git.
- Situação 1: eu preciso alterar o commit mais recente
- Situação 2: eu preciso alterar um commit específico
- Situação 3: eu preciso adicionar, remover ou combinar commits
- Situação 4: Meu histórico de commits não funciona sentido, eu preciso começar do zero!
Mas antes de começarmos, vejamos rapidamente como um fluxo de trabalho de desenvolvimento típico se parece em um nosso aplicativo Ruby hipotético.
Nota: Este artigo assume que você conhece os fundamentos do Git, como os branches funcionam, como adicionar mudanças não confirmadas de um branch ao estágio e como fazer o commit das mudanças. Se você não tiver certeza desses fluxos, nossa documentação é um ótimo ponto de partida.
Um dia na vida
Aqui, estamos trabalhando em um pequeno projeto Ruby on Rails, onde precisa adicionar uma visualização de navegação na página inicial e isso envolve atualizar e adicionar vários arquivos. A seguir está uma análise passo a passo de todo o fluxo:
- Você começa a trabalhar em um recurso com a atualização de um arquivo ; vamos chamá-lo de
application_controller.rb
- Este recurso requer que você também atualize uma visualização:
index.html.haml
- Você adicionou uma parcial que é usada na página de índice:
_navigation.html.haml
- Os estilos da página também precisam ser atualizados para refletir a parcial que adicionamos:
styles.css.scss
- O recurso agora está pronto com as mudanças desejadas, é hora de também atualizar os testes; os arquivos a serem atualizados são os seguintes:
-
application_controller_spec.rb
-
navigation_spec.rb
-
- Os testes estão atualizados e passando como esperado, agora é hora de confirmar as alterações!
Como todos os arquivos pertencem a diferentes territórios da arquitetura, nós nos comprometemos as alterações isoladas umas das outras para garantir que cada confirmação represente um determinado contexto e seja feita em uma determinada ordem. Eu geralmente prefiro back-end – > ordem de front-end em que a maioria das alterações centradas em backend é confirmada primeiro, seguida pela camada do meio e, em seguida, por alterações centradas em frontend nos commits da lista Git.
Agora que confirmamos nossas alterações, criamos uma solicitação de mesclagem com o branch. Depois de abrir a solicitação de mesclagem, ela normalmente é revisada por seu colega antes que as alterações sejam mescladas no branch repo “s master
. Agora vamos aprender em que situações diferentes podemos acabar durante a revisão do código.
Situação 1: preciso alterar o commit mais recente
Imagine um caso em que o revisor olhou styles.css.scss
e sugeriu uma mudança. Nesse caso, é muito simples fazer a mudança, pois as mudanças da folha de estilo são parte do último commit em seu branch. Veja como podemos lidar com isso;
- Você faz diretamente as alterações necessárias em
styles.css.scss
em seu branch. - Uma vez você concluiu as alterações, adicione essas alterações ao palco; execute
git add styles.css.scss
. - Uma vez que as mudanças são testadas, precisamos adicionar essas mudanças ao nosso último commit; execute
git commit --amend
.- Divisão do comando: aqui, estamos pedindo ao comando
git commit
para corrigir quaisquer alterações presentes em estágio para o commit mais recente.
- Divisão do comando: aqui, estamos pedindo ao comando
- Isso abrirá seu último commit em seu editor de texto definido pelo Git, que tem a mensagem de commit Adicionar estilos para navegação.
- Como apenas atualizamos a declaração CSS, não precisamos alterar a mensagem de confirmação.Neste ponto, você pode simplesmente salvar e sair do editor de texto que o Git abriu para você e suas mudanças serão refletidas no commit.
Já que você modificou um commit existente, essas mudanças são necessárias para ser enviado à força para seu repositório remoto usando git push --force-with-lease <remote_name> <branch_name>
. Este comando substituirá o commit Add styles for navigation
no repositório remoto com o commit atualizado que acabamos de fazer em nosso repositório local.
Uma coisa para manter em mente ao forçar o envio de branches é que se você está trabalhando no mesmo branch com várias pessoas, force push pode causar problemas para outros usuários quando eles tentam normalmente enviar por push suas alterações em um branch remoto que tem novos commits force enviados. Portanto, use esse recurso com sabedoria. Você pode aprender mais sobre as opções de push de força do Git aqui.
Situação 2: eu preciso alterar um commit específico
Na situação anterior, a correção era bastante simples porque tivemos que modificar apenas nosso último commit do Git, mas imagine se o revisor sugerisse mudar algo em _navigation.html.haml
. Neste caso, é o segundo commit do topo, então alterá-lo não será tão direto quanto foi na primeira situação. Vamos ver como podemos lidar com isso:
Sempre que um commit é feito em uma ramificação, ele é identificado por uma string hash SHA1 exclusiva. Pense nisso como um ID único que separa um commit do outro. Você pode ver todos os commits, junto com seus hashes SHA1 em um branch executando git log
. Com isso, você veria uma saída parecida com a seguinte, onde os commits mais recentes estão no topo;
É aqui que o comando git rebase
entra em ação. Sempre que desejamos editar um commit específico com git rebase
, precisamos primeiro realocar nosso branch movendo HEAD de volta ao ponto antes do commit que desejamos editar. Em nosso caso, precisamos alterar o commit que lê Page Navigation View
.
Aqui, observe o hash do commit que está logo antes do commit que queremos modificar; copie o hash e execute as seguintes etapas:
- Rebase o branch para mover para o commit antes de nosso commit de destino; execute o
git rebase -i 8d74af102941aa0b51e1a35b8ad731284e4b5a20
- Quebra do comando: aqui estamos executando o comando Git “s
rebase
com modo interativo com o hash SHA1 fornecido como commit para rebase para.
- Quebra do comando: aqui estamos executando o comando Git “s
- Isso executará o comando rebase para Git no modo interativo e abrirá seu editor de texto mostrando todos os seus commits que vieram após o commit para o qual você fez o rebase . Será mais ou menos assim:
Observe como cada commit tem uma palavra pick
na frente dele, e no conteúdo abaixo, existem todas as palavras-chave possíveis que podemos usar. Visto que queremos editar um commit, precisamos mudar pick 4155df1cdc7 Page Navigation View
para edit 4155df1cdc7 Page Navigation View
. Salve as mudanças e saia do editor.
Agora seu branch foi realocado para o ponto no tempo antes do commit que você fez, que incluiu _navigation.html.haml
. Abra o arquivo e execute as alterações desejadas de acordo com o feedback da revisão. Quando terminar de fazer as alterações, teste-as executando git add _navigation.html.haml
.
Já que testamos as alterações, é hora de mover o branch HEAD de volta para o commit que tínhamos originalmente (enquanto também incluímos as novas alterações que adicionamos), execute git rebase --continue
, isso abrirá seu editor padrão no terminal e mostrará a mensagem de commit que editamos durante o rebase; Page Navigation View
. Você pode alterar esta mensagem se desejar, mas deixaríamos como está por enquanto, então salve e saia do editor. Neste ponto, o Git irá repetir todos os commits que seguiu após o commit que você acabou de editar e agora o branch HEAD
está de volta ao commit principal que tínhamos originalmente, e também inclui as novas mudanças que você fez em um dos commits.
Uma vez que modificamos novamente um commit que já está presente no repo remoto, precisamos forçar o push deste branch novamente usando git push --force-with-lease <remote_name> <branch_name>
.
Situação 3 : Eu preciso adicionar, remover ou combinar commits
Uma situação comum é quando você fez vários commits apenas para consertar algo previamente confirmado. Agora vamos reduzi-los o máximo que pudermos, combinando-os com os commits originais.
Tudo que você precisa fazer é iniciar o rebase interativo como faria nos outros cenários.
Agora imagine que você deseja combinar todas essas correções em c22a3fa0c5c Render navigation partial
. Você só precisa:
- Mova as correções para cima para que fiquem logo abaixo do commit que você deseja manter no final.
- Altere
pick
parasquash
oufixup
para cada uma das correções.
Observação: squash
mantém as mensagens de commits na descrição. fixup
irá esquecer as mensagens de commit das correções e manter o original.
Você acabará com algo assim:
Salve as alterações e saia do editor , e pronto! Este é o histórico resultante:
Como antes, tudo que você precisa fazer agora é git push --force-with-lease <remote_name> <branch_name>
e as mudanças estão acontecendo.
Se você deseja remover o commit do branch completamente, em vez de squash
ou fixup
, apenas escreva drop
ou simplesmente exclua essa linha.
Evite conflitos
Para evitar conflitos, certifique-se de enviar seus commits “mover para cima na linha do tempo não está tocando nos mesmos arquivos tocados pelos commits deixados depois deles.
Dica profissional : Correções rápidas
Se você sabe exatamente qual commit deseja corrigir, ao fazer um commit não precisa desperdiçar ciclos cerebrais pensando em bons nomes temporários para “Correção 1”, “Correção 2”,…, “Fix 42”.
Etapa 1: Conheça --fixup
Depois de fazer as alterações corrigindo tudo o que precisa ser corrigido, apenas Git compromete todas as mudanças como esta:
(Observe que este é o hash para o commit c22a3fa0c5c Render navigation partial
)
Isso irá gerar esta mensagem de commit: fixup! Render navigation partial
.
Etapa 2: E o ajudante --autosquash
Rebase interativo fácil. Você pode git
colocar os fixup
s automaticamente no lugar certo.
git rebase -i 4155df1cdc7 --autosquash
A história será mostrada assim:
Pronto para você apenas revise e prossiga.
Se você estiver se sentindo aventureiro, pode fazer um rebase não interativo git rebase --autosquash
, mas apenas se você gosta de viver perigosamente, pois ” não tenho oportunidade de revisar os squashes que estão sendo feitos antes de serem aplicados.
Situação 4: Meu histórico de commits do Git não faz sentido, eu preciso de um novo começo!
Se nós “Ao trabalhar em um grande recurso, é comum ter várias alterações de correção e feedback de revisão que estão sendo confirmadas com frequência. Em vez de rebasing constantemente o branch, podemos deixar a limpeza dos commits até o final do desenvolvimento.
É aqui que a criação de arquivos de patch é extremamente útil. Na verdade, os arquivos de patch eram a principal forma de compartilhar código por e-mail durante a colaboração em grandes projetos de código aberto antes que serviços baseados em Git como o GitLab estivessem disponíveis para desenvolvedores. Imagine que você tenha um tal branch (por exemplo; add-page-navigation
) onde há toneladas de commits que não transmitem as mudanças subjacentes claramente. Veja como você pode criar um arquivo de patch para todos as mudanças que você fez neste branch:
- A primeira etapa para criar o arquivo de patch é ter certeza de que seu branch possui todas as alterações presentes em
master
branch e não tem conflitos com o mesmo. - Você pode executar
git rebase master
ougit merge master
enquanto você “verifica noadd-page-navigation
branch para obter todas as alterações demaster
em seu branch. - Agora crie o arquivo de patch ; execute
git diff master add-page-navigation > ~/add_page_navigation.patch
.- Quebra de comando: aqui, estamos usando o recurso diff do Git e pedindo uma diferença entre
master
branch eadd-page-navigation
branch, e redirecionando a saída (por meio do símbolo>
) para um arquivo chamadoadd_page_navigation.patch
em nosso nós er diretório inicial (normalmente~/
em sistemas operacionais * nix).
- Quebra de comando: aqui, estamos usando o recurso diff do Git e pedindo uma diferença entre
- Você pode especificar qualquer caminho que deseja manter este arquivo em e o nome do arquivo e a extensão podem ser o que você quiser.
- Assim que o comando for executado e você não ver nenhum erro, o arquivo de patch é gerado.
- Agora verifique
master
branch; executegit checkout master
. - Exclua o branch
add-page-navigation
do repositório local; executegit branch -D add-page-navigation
. Lembre-se, já temos mudanças deste branch em um arquivo de patch criado. - Agora crie um novo branch com o mesmo nome (enquanto
master
é retirado); executegit checkout -b add-page-navigation
. - Neste ponto, este é um novo branch e não tem nenhuma de suas alterações.
- Por fim, aplique suas alterações do arquivo de patch;
git apply ~/add_page_navigation.patch
. - Aqui, todas as suas alterações são aplicadas em um branch e elas aparecerão como não confirmadas, como se todas as suas modificações onde feito, mas nenhuma das modificações foi realmente confirmada no branch.
- Agora você pode prosseguir e enviar arquivos individuais ou arquivos agrupados por área de impacto na ordem que você deseja com mensagens de confirmação concisas.
Assim como nas situações anteriores, basicamente modificamos todo o branch, então é hora de forçar o push!
Conclusão
Embora tenhamos coberto as situações mais comuns e básicas que surgem em um fluxo de trabalho diário com Git, reescrever a história do Git é um tópico vasto e conforme você se familiariza com dicas acima, você pode aprender conceitos mais avançados sobre o assunto na documentação oficial do Git. Feliz git “ing!
Foto de pan xiaozhen no Unsplash