Dividir o progresso da codificação em confirmações significativas sem muita sobrecarga

23

Ao trabalhar em uma correção ou recurso, às vezes me deparei com outros pequenos problemas que podem ser melhorados rapidamente em questão de segundos. Quando eu os faço imediatamente e, em seguida, confirmo o recurso / correção finalizado, o commit inclui mais de uma coisa. Por exemplo "add feature X and code clean up"ou "fix bug X and improved logging". Seria melhor dividir isso em dois commits. Caso as duas alterações ocorram no mesmo arquivo, não posso simplesmente adicionar um arquivo, confirmar, adicionar o outro e confirmar novamente. Então, eu vejo as três opções a seguir:

  1. Ignore deliberadamente coisas não relacionadas ao trabalhar em alguma coisa.

  2. Copie o arquivo com duas alterações, revertê-lo, incluir uma alteração, confirmar, incluir a outra alteração, confirmar novamente.

  3. Não altere pequenas coisas não relacionadas, mas adicione-as a uma lista de tarefas e faça-as mais tarde.

Eu realmente não gosto de todas as três opções, pelos seguintes motivos:

  1. A qualidade do código pode sofrer se não se resolver pequenos problemas. E me sinto mal se perder conscientemente a chance de melhorar algo sem muito esforço.

  2. Isso aumenta o trabalho manual e é propenso a erros.

  3. Isso é bom para todos não tão pequenos, mas adicionar um item minúsculo a uma lista de tarefas e revisitá-lo mais tarde geralmente leva muito mais tempo do que apenas corrigi-lo imediatamente.

Como você lida com essas situações?

Tobias Hermann
fonte
7
O git não permite que você faça check-in de linhas individuais em vez de arquivos inteiros?
Kilian Foth
Eu uso git add -pmuito, o que me permite selecionar interativamente as partes dos arquivos que quero confirmar. Se a limpeza for suficientemente separada, isso é fácil. Se a separação for mais difícil, confirmo o estado em uma ramificação temporária e adiciono manualmente as alterações à minha ramificação real até que não haja diferenças na ramificação temporária. Isso requer muito mais trabalho, mas me permite verificar se cada confirmação funciona por conta própria.
amon
1
@gnat: obviamente, não é um idiota. O OP não está perguntando sobre o tamanho correto de uma confirmação - ele quer fazer pequenas confirmações. Ele está apenas procurando uma maneira mais eficiente de fazer isso.
Doc Brown
2
@gnat: top answer não diz nada (!) sobre como lidar com diferentes alterações em um arquivo e como dividi-las em confirmações separadas.
Doc Brown

Respostas:

11

Eu acho que você precisa ser muito pragmático ao programar. Mesmo que seja possível formular o esquema, o fluxo de trabalho ou a implementação perfeitos, às vezes você só precisa concluir o trabalho. Aqui está o que eu faço:

Uso a capacidade do git de preparar / cometer blocos e linhas individuais, sempre que possível, para separar mudanças não relacionadas, embora, ocasionalmente, isso possa introduzir problemas temporários, se a separação não for feita adequadamente. Como as alterações serão adjacentes, geralmente não é um problema enorme, a menos que você tenha uma política de testar todas as alterações individuais no pipeline de IC.

Quando a mudança não relacionada for muito grande, eu a colocarei em uma lista de tarefas, e geralmente a levarei logo depois, enquanto estiver fresca em minha mente. Às vezes, pode demorar um ou dois dias para eu voltar a isso, depende da minha tarefa atual e linha de pensamento. Ocasionalmente, simplesmente colocarei um TODO: próximo ao código incorreto, se não tiver uma boa solução pronta.

Acontece que simplesmente não é prático separar as coisas e vou fazer um pequeno ajuste junto com o trabalho original.

O tamanho da mudança geralmente é o fator determinante quando eu escolho o caminho a seguir, mas no final eu preferiria ignorar uma regra de fluxo de trabalho do que deixar um cheiro para trás.

axl
fonte
7

Meu editor possui um plug - in que facilita a preparação de partes individuais de um arquivo. Eu imagino que outros editores de programadores possam ter plugins semelhantes, embora você sempre possa fazer isso da maneira manual git add --patch | -p. Então eu uso o git stash para salvar minhas outras alterações e testar meu pequeno commit isoladamente. Depois que eu me comprometo, faço git stash pope continuo de onde parei. É exatamente para isso que esses recursos foram projetados.

Karl Bielefeldt
fonte
2

O truque é não fazer alterações, a menos que você esteja preparado para fazer o máximo esforço possível.

O que eu costumo fazer é adicionar a uma lista de tarefas (às vezes adicionando comentários ao código, às vezes em uma nota em um ticket de bug e às vezes atualizando o código em uma ramificação separada, sabendo que a correção será mesclada eventualmente). Se não houver um ticket de bug para um acúmulo de problemas menores de qualidade, eu levanto um especificamente para isso, para que eu e todos os outros possamos dizer qual foi o motivo dessas alterações de código quando a filial foi mesclada. Eu nunca faço alterações apenas por diversão, tudo fica rastreado para que meus colegas não fiquem muito surpresos quando o código for alterado.

Então, resumindo - sim, ignore-os ao codificar. Se você estiver adicionando um recurso, não fique tentado a adicionar dois recursos, por menor que seja. Se alguém decidir reverter sua ramificação (porque seu recurso não é mais necessário, por exemplo), você também perderá todas as suas mini-correções. Da mesma forma, você não deseja fazer uma pequena 'correção' em algum código crítico que estava funcionando corretamente.

gbjbaanb
fonte
1
O OP não sugeriu mesclar duas alterações em uma confirmação, pelo contrário.
Doc Brown
1
@DocBrown, ele sugere misturar 2 alterações em um único ramo, que pode ser confuso para cancelar mais tarde, embora obviamente não seja tão confuso quanto 2 alterações em um único commit.
gbjbaanb 8/16
Ok, entendo o que você tem em mente no seu parágrafo final.
Doc Brown
2

Uma opção que utilizo bastante é adicionar TODOcomentários e realizar muitas confirmações "parciais" frequentes, usando git add --patchpara selecionar as partes relevantes do arquivo. Em seguida, use git rebase --interactivepara reordenar e mesclar as confirmações parciais no recurso final e as confirmações de correção antes de enviá-las.

Isso mantém seu commit principal limpo e ainda permite que você corrija outros problemas encontrados imediatamente.

Não há nada errado com a git rebasenesse contexto, pois você está reescrevendo apenas confirmações locais.

Tom
fonte
1

Outra opção poderia ser "git stash", suas alterações atuais. O fluxo de trabalho ficaria assim:

  1. Comece a fazer alterações relacionadas ao Recurso A
  2. Descubra o Bug B e decida corrigi-lo imediatamente
  3. Na linha de comando em seu repo, execute git stash (Após o qual seu código retornará ao estado em que estava antes de começar a trabalhar no Recurso A )
  4. Nesse ponto, suas alterações não confirmadas no recurso A são armazenadas no "stash"
  5. Faça as alterações de código necessárias para corrigir o erro B e faça uma confirmação novamente no repositório
  6. Na linha de comando, execute git stash pop
  7. Suas alterações não confirmadas no Recurso A agora são retiradas do stash e restauradas no código em andamento, ao lado da correção (já confirmada) do Bug B
Zach
fonte
Você poderia expandir um pouco mais sobre como esse fluxo de trabalho funcionaria? Qual é o estado do repositório em cada ponto? Você poderia orientar alguém no processo de usar o git stash?
0

Estacione (e confirme) separadamente as alterações relacionadas à correção de erros. Nas extensões Git, isso é extremamente fácil de fazer. Na linha de comando, acho que você precisa fazer git add -p.

Andrew Coleson
fonte