Como comprometer a refatoração em andamento?

23

Então, eu tenho esse grande projeto, que está sendo refatorado por mim. Estou mudando muitas coisas, para que não haja chance de compilar em breve. Eu estou morando em um ramo especial do git que eu nomeei cleanup(que será mesclado mastereventualmente, é claro).

O problema é que eu / nós temos a política de nunca confirmar código não-compilável (idealmente, ele também deve funcionar, mas deve compilar e vincular, no mínimo). Portanto, até que eu termine essa tarefa enorme, não poderei comprometer nada (para revisão ou contabilidade).
Não é assim que eu gosto de trabalhar (acredito que a maioria das pessoas se compromete pelo menos uma vez ao dia).

O que você acha? Existe uma solução que estou ignorando?
Mais tarde posso dizer ao git para agregar confirmações ou algo assim? Eu poderia viver com um commit não-compilado enquanto eles permanecerem no cleanupramo.

Editar

Sobre o assunto push / commit: estou ciente de que há uma enorme diferença, mas mais tarde haverá revisões quebradas, quando mesclar minhas coisas master. Portanto, se você navegar pelo histórico (ou git bisect...), as revisões "locais" serão acessíveis mundialmente. Portanto, apenas confirmar localmente e não pressionar não é a melhor solução, pois isso causará problemas mais tarde (quando o assunto for fechado e esquecido por algum tempo).

Em resumo: as confirmações locais serão enviadas eventualmente. O histórico global não deve mostrar confirmações de não compilação.

bitmask
fonte
1
Você pode coletar várias confirmações locais em uma única confirmação global.
@ Thorbjørn é a recomendação de Jim abaixo, ou um mecanismo diferente dentro do Git?
Brian
Eu acredito que sim - não consigo lembrar o comando exato.
5
Você não está refatorando, está fazendo algo maior. Após cada refatoração em uma base de código, seu código deve compilar e ter exatamente o mesmo comportamento observável. Você pode alterar o título da pergunta para refletir que, como minha reação imediata foi "Confirme o que você tem sempre, tudo deve funcionar".
David Thornley
1
@bitmask Que tal reescrever?
precisa

Respostas:

21

O git merge --squashcomando permite criar uma única confirmação sobre a ramificação atual, cujo efeito é o mesmo que mesclar outra ramificação. O comando atualiza a árvore de trabalho e encena as alterações no índice; portanto, tudo o que você precisa fazer a seguir é confirmar:

git checkout master
git merge --squash cleanup
git commit -m "Merge cleanup branch"

O git rebase -icomando também pode esmagar as confirmações, mas exige mais trabalho.

Jim Huang
fonte
14

Uma reescrita não é uma refatoração

Sei que você está interessado em usar o Git, mas eu diria que você deve considerar mudar a maneira de refatorar mais do que a maneira como usa o Git (embora eu ache que o Git possa ajudá-lo).

Martin Fowler define refatoração como :

uma técnica disciplinada para reestruturar um corpo de código existente, alterando sua estrutura interna sem alterar seu comportamento externo.

Seu coração é uma série de pequenos comportamentos que preservam transformações. Cada transformação (chamada de “refatoração”) faz pouco, mas uma sequência de transformações pode produzir uma reestruturação significativa. Como cada refatoração é pequena, é menos provável que dê errado. O sistema é mantido em pleno funcionamento após cada pequena refatoração, reduzindo as chances de um sistema ser seriamente quebrado durante a reestruturação.

Se você aplicar esse método, poderá confirmar (e enviar por push) regularmente.

Você pode argumentar que isso é impraticável e que não funciona para algo em grande escala. É aqui que o método Mikado pode ajudar. Você decompõe uma refatoração grande em uma série de pequenas refatorações criando um gráfico de dependência. O método é recursivo, tente fazer sua alteração, não interrompe nada, faça o check-in, caso contrário, reverta sua alteração e anote os pré-requisitos. Um por um, você corrige essas refatorações pré-requisitos até atingir seu principal objetivo de refatoração.

O Git pode realmente ajudar esse método. Você pode manter sua ramificação local (quebrada). Ao comprometer (e empurrar) os sub-objetivos, você pode rebasealcançar seu objetivo principal, além dos commits que você acabou de fazer, até que não sejam mais quebrados.

Dave Hillier
fonte
5

Confira a página do manual git rebase, principalmente a git rebase -ivariante. Ele permite que você reordene, exclua ou esmague qualquer número de confirmações em seu histórico, o que parece o que você está procurando. Eu o uso o tempo todo exatamente na situação que você descreve: fazendo muitos pequenos commits que não são adequados para consumo público e, em seguida, agrupando-os em um único commit de "refatoração" antes de enviar para o repositório compartilhado.


fonte
3

Você está usando o Git, assim, confirmar não implica necessariamente empurrar suas alterações ....

IMHO, e trabalhando com o Git, é perfeitamente bom confirmar seu trabalho, mesmo que ele não seja compilado ... porque, afinal, depois de confirmar suas alterações, ninguém terá o código disponível (até que você o faça). Obviamente, antes de empurrá-lo, você deve garantir que funcione bem e compile, para que outras pessoas possam buscar e mesclar suas alterações sem problemas.

Além disso, você está trabalhando em uma ramificação diferente da mestre. Então, se você quiser (e eu recomendo isso), você nunca empurrará seu ramo. Depois de concluir a refatoração, basta fazer o checkout da ramificação principal, mesclar suas alterações e pressionar a ramificação principal.

Editar

Nesse caso, você pode usar git cherry-pickou brincar comgit rebase

Cristian
fonte
Uma nota importante, mas considerei isso. Por favor, veja minha edição. Obrigado.
bitmask
Veja minha edição acima.
Cristian
Eu -1 se eu pudesse; os commits estarão disponíveis! As confirmações locais de trabalho em andamento são ótimas, mas nunca as pressionam; torna o código mais difícil de entender, interrompe o git bisect e complica a história. Rebase ou squash.
RJFalconer