O que devo fazer quando já esperei muito tempo entre confirmações?

100

Eu era travesso ... Muita "codificação de cowboy", não basta cometer. Agora, aqui estou eu com um enorme comprometimento. Sim, eu deveria estar cometendo o tempo todo, mas agora é tarde demais.

O que é melhor?

  1. Faça um commit muito grande listando todas as coisas que eu mudei
  2. Tente dividi-lo em confirmações menores que provavelmente não serão compiladas, pois os arquivos têm várias correções, alterações, nomes de métodos adicionais etc.
  3. Tente fazer reversões parciais dos arquivos apenas para confirmações apropriadas e, em seguida, coloque as novas alterações de volta.

Nota: a partir de agora eu sou o único programador trabalhando neste projeto; a única pessoa que analisará algum desses comentários de commit sou eu, pelo menos até contratarmos mais programadores.

A propósito: eu estou usando SVN e Subclipse. Eu criei uma nova ramificação antes de fazer qualquer uma dessas alterações.

Mais informações : Fiz uma pergunta separada relacionada a como entrei nessa situação em primeiro lugar: Como se preparar para reescrever a cola de um aplicativo

durron597
fonte
2
Qual programa de controle de versão você está usando? Muitos possuem módulos que permitem dividir suas edições em "blocos", ou seja, grupos de linhas modificadas, que permitem agrupar suas edições da maneira que desejar e distribuir as modificações de um arquivo para vários conjuntos de alterações. Por exemplo, mercurial tem a extensão "arquivar". Obviamente, você ainda deve verificar se cada lote de alterações é compilado, se isso importa para o seu processo. Se vale a pena, o problema é com você e sua loja.
27414 Alexis
6
Pelo menos faça o check-in na ramificação, para não perder as alterações.
Rory Hunter
2
Você pode continuar se perguntando e esperar ainda mais, ou realmente se comprometer e lidar com qualquer bagunça que criar ... E então ... não faça de novo!
27514 haylem
40
# 1, rezar por perdão, e, em seguida, ir adiante e não peques mais :)
Peteris
5
A pergunta mais importante que você deve se fazer é: "como mudo meus maus hábitos para evitar que isso aconteça novamente". Não deve haver nenhuma razão para cometer não, pelo menos uma vez por dia, melhor, mais frequentemente.
Doc Brown

Respostas:

52

Para responder, você deve se perguntar como espera usar os resultados desses commits no futuro. Os motivos mais comuns são:

  • Para ver qual versão um bug foi introduzido.
  • Para ver por que uma certa linha de código está presente.
  • Para mesclar em outro ramo.
  • Para poder verificar uma versão anterior para solucionar um problema que um cliente ou testador está vendo nessa versão.
  • Ser capaz de incluir ou excluir determinadas partes de uma liberação.

Os dois primeiros motivos também podem ser atendidos com um grande check-in, supondo que você possa criar uma mensagem de check-in que se aplique igualmente bem a cada linha de código alterado. Se você é o único programador, confirmações menores não facilitarão sua mesclagem. Se você não planeja fazer uma liberação ou testar apenas parte de suas alterações não enviadas, os dois últimos motivos não se aplicam.

Existem outras razões para fazer pequenas confirmações, mas elas ocorrem enquanto você está no meio das mudanças e esse tempo já passou. Esses motivos estão facilitando a recuperação de um erro ou alteração experimental e facilitando a sincronização com colegas sem grandes fusões assustadoras.

Pelo meu entendimento de sua situação como você a descreveu, parece que há pouco ou nenhum benefício em dividir seu commit neste momento.

Karl Bielefeldt
fonte
Excelente resposta! Embora não me sinta menos arrependido por não fazer pequenos compromissos, sinto-me muito melhor com o que devo fazer para voltar ao bom comportamento da maneira mais produtiva possível.
durron597
1
A outra coisa sobre 3 e 5 é que, qualquer trabalho que você faça agora para permitir que eles aconteçam, você pode esperar até precisar dele e, em seguida, fazer o mesmo trabalho. Provavelmente será um pouco mais difícil no futuro, porque sua memória do que você fez se foi. Mas, novamente, você provavelmente nunca precisará disso.
9608 Steve JobsMay
Na minha experiência, é problemático e frágil confiar nos comentários do controle de versão para contar uma história do motivo pelo qual o código existe (por exemplo, razões 1 e 2). Se você estiver usando o SVN com uma ramificação, o histórico de consolidação será perdido na mesclagem (você ficará melhor com coisas mais modernas, como o git). Então, esses são IMHO melhor servidos com comentários.
Hans-Peter Störr 5/03/2014
1
@hstoerr - se você estiver no Subversion 1.5 ou posterior, poderá preservar o histórico com a opção --reintegrate ao mesclar.
Dustin Kendall
1
O git add -p é seu melhor amigo aqui. Eu me apaixonei por esse recurso. Dessa forma, eu posso confirmar minhas modificações padrão de codificação em confirmações separadas e manter isoladas as alterações de código relevantes.
Spidey
39

Eu acho que o que você faz, tente evitar o código de entrada que você sabe que não será compilado.

Se você acha que sua terceira opção é viável, pode ser uma boa maneira de fazê-lo, desde que você possa garantir que sua sequência de confirmações não crie um sistema não-compilável. Caso contrário, faça o único grande commit. É feio, mas é simples, rápido e o faz. No futuro, comprometa-se com mais frequência .

FrustratedWithFormsDesigner
fonte
A opção três é possível, mas seria extremamente demorada. Eu acho que só vou fazer a opção 1
durron597 27/02
3
Quais são as desvantagens de confirmar código que não compila ou cria em um ramo de recurso (ou similar) que são tão terríveis que obrigam alguém a evitar fazê-lo "faça o que fizerem"? Eu imagino que quaisquer confirmações realmente terríveis possam ser evitadas por outras pessoas, que é a única razão real pela qual eu as evitaria em primeiro lugar (supondo, é claro, que as confirmações não estejam sendo liberadas ).
Kenny Evitt 27/02
3
O "evitar o check-in de código que não será compilado" se aplica apenas a uma base / ramificação de código compartilhada. Em um projeto individual ou em um ramo de desenvolvimento individual, eu afirmo que é mais importante inserir as alterações no VC para que você não perca nada.
Stephen C
3
@StephenC, por exemplo, porque quebra ferramentas como o git-bisect. Se o código compilar / executar o tempo todo e você precisar encontrar uma regressão, se ele compilar o tempo todo, basta pesquisar binariamente (sem mencionar que, se houver regressão no pedaço de código, você terá uma grande alteração para ler em vez de restringir para baixo).
Maciej Piechotka
@MaciejPiechotka - Bem, obviamente, se você precisar usar ferramentas específicas em suas filiais particulares, e elas exigirem que o código seja compilável, faça-o. Mas isso não é típico para um projeto / filial de uma pessoa.
Stephen C
19

O motivo mais importante para fazer confirmações frequentes, pequenas e significativas é ajudar a entender o histórico do código. Em particular, é muito difícil entender como o código mudou, se é difícil gerar diferenças compreensíveis.

A opção 1 ofusca o histórico de alterações que você fez, mas, caso contrário, não causará problemas.

A opção 2 ofusca o histórico de alterações que você fez, possivelmente um pouco menor que a opção 1, mas pode causar outros problemas para você ou para outras pessoas se eles assumirem ou concluirem que os commits são distintos, por exemplo, podem ser mesclados em outros ramos independentemente. A menos que haja uma forte razão prática pela qual isso é preferível à opção 1, isso é menos ideal do que isso.

A opção 3 é a melhor, sendo tudo igual, mas, como você descreveu em outro lugar, isso exigiria quantidades "extremas" de tempo ou incorreria em outros custos significativos, você terá que ponderar esses custos com os benefícios esperados de criando confirmações mais limpas.

Com base nas informações que você forneceu, eu optaria pela opção 1. Talvez você deva configurar lembretes solicitando que você efetue suas alterações?

Prototipagem e Reescrita

Outra consideração a ter em mente, especialmente à luz de sua observação sobre ser o único programador, e minha suspeita de que você esteja trabalhando em uma base de código relativamente nova, é que provavelmente é bom desenvolver hábitos diferentes com relação a confirmar alterações quando você está criando um novo código para a criação de protótipos em vez de manter ou estender o código existente. Provavelmente não existe uma divisão muito nítida entre os dois, mas acho que ainda é uma distinção útil.

Ao criar um novo código para criação de protótipo, confirme sempre que desejar salvar suas alterações, quase certamente em uma ramificação, mas talvez em um projeto separado. Ou talvez apenas trabalhe completamente fora do controle de versão. Em vez disso, você pode se concentrar em reunir evidências sobre a viabilidade de várias hipóteses ou projetos que estiver considerando. Costumo escrever pequenos protótipos usando ferramentas diferentes, por exemplo, LINQPad em vez de código do Visual Studio para C #.

Quando você validar uma hipótese ou design específico, reescreva-o em seu projeto principal, idealmente em uma ramificação, e faça os pequenos e significativos commits que ajudarão melhor a compreensão dos outros (incluindo você futuro) quanto à natureza das mudanças você está fazendo.

Kenny Evitt
fonte
1
Boa resposta; Kenny você tem um bom artigo ou outra base de conhecimento para vincular a detalhes mais específicos sobre prototipagem? Minha versão da prototipagem é "sketch in notebook or on whiteboard"
durron597 27/02
@ durron597, não consigo pensar em nenhum link (nem mesmo procurar) em cima da minha cabeça. Eu brinquei com linguagens de programação interpretadas o suficiente (e compiladas dinamicamente) que nem pensei que a idéia de 'prototipagem' pudesse ser nova! E reescrevi tantos programas em C, C ++ e Java (repetidamente) que não achei que isso fosse incomum também, ou pelo menos novo para alguns.
Kenny Evitt
12

Embora a única resposta razoável seja nunca quebrar o tronco , algumas vezes isso não é possível. Por exemplo, o svn pode interromper o commit se você confirmar demais (talvez uma opção ou recurso, não tenho certeza). Nesses casos especiais, basta fazer o check-in em pedaços. Como você é um programador único, isso não vai incomodar ninguém.

Portanto, eu iria para a opção 1. Se não for possível, então a opção 2.

A opção 3 requer muito esforço e simplesmente não vale a pena.

BЈовић
fonte
1
ou marque as versões que não são de compilação como "NÃO COMPILA"
catraca freak
2
@ratchetfreak: Eu acho que uma "tag" no SVN não vai ajudar muito, pois as tags não funcionam como "comentários" no porta-malas.
Doc Brown
@DocBrown eu quis dizer adicioná-lo à mensagem de commit
catraca aberração
5
@ratchetfreak Eu faria isso como "PARTE X / N: check-in no ABC - NÃO COMPILA"
#
A opção 3 não requer muito esforço. Outra resposta explica como fazê-lo com rapidez e facilidade usando git add --patche git stash. A situação só parece difícil por causa de ferramentas e conhecimentos desatualizados de controle de origem.
Ron MacNeil
7

Tente dividi-lo em confirmações menores que provavelmente não serão compiladas, pois os arquivos têm várias correções, alterações, nomes de métodos adicionais etc.

Quando me encontrei em uma situação semelhante, usei a seguinte técnica:

  1. Adicione apenas o código relevante para um recurso específico: git add --patch
  2. Esconda todas as outras alterações: git stash save --keep-index
  3. Execute testes / tente compilar
  4. Confirme as alterações se estiver tudo bem, se não for, vá para 1

Eu não estou familiarizado com o SVN, então não sei se isso é aplicável à sua situação específica, mas a base deve ser a mesma - isole pequenas partes do código e teste-as individualmente.

Milos
fonte
Eu gosto disso, mas infelizmente uma das muitas coisas na minha lista de tarefas (existem muitas quando você é o único técnico em uma empresa) é mudar do SVN para o git, e eu ainda não cheguei a isso ainda .
durron597
1
Como não tenho o suficiente para usar --patch, uso Desfazer em vários painéis do editor, para chegar aos estados de trabalho anteriores e os comprometo. Depois refizo para o próximo commit. Devido à tentação de fazer pequenas adições ao código quando no estado Desfeito, sempre faço um backup antes de iniciar esse processo!
Joeytwiddle 28/02
Com o git, você também pode adicionar interativamente (adicionar -i) antes de confirmar e ramificar depois para validar seus commit independentemente.
28414 riezebosch
3

Que tal a opção 4: faça backup do estado atual do seu repositório em um local temporário, reverta-o ao estado original, faça uma lista de todas as alterações que você fez (você ainda pode ver o backup temporário) e reimplemente manualmente (e compile e testá-los!) como confirmações separadas.

Isso deve ser mais fácil, porque você já escreveu o código, é apenas um pouco para descobrir quais partes copiar e colar do seu backup temporário.

Quando você reimplementar todas as alterações de forma limpa e, assim, garantir que as confirmações sejam independentes, pequenas e compiladas, você poderá excluir o backup temporário e tudo será quase exatamente como (exceto a hora / data das confirmações) teria sido se você fizesse isso desde o início.

Superbest
fonte
Esta é apenas uma maneira de fazer a opção # 3. Provavelmente o melhor caminho, é verdade, mas ainda consome bastante tempo.
durron597
Havia 149 linhas de adição / exclusão / envio de mensagens quando fiz uma grande confirmação. Isso é pelo menos meio dia para fazer isso.
durron597
@ durron597 Não concordo, acho que isso é diferente do # 3. Em relação a 149 linhas, quanto você valoriza um histórico de consolidação limpo? Vale a pena gastar meio dia? De qualquer forma, não é como se os outros métodos não precisassem descobrir qual linha deveria estar em qual commit, então você terá que passar pelas 149 linhas de qualquer maneira. A diferença no tempo será pequena.
Superbest 27/02
Heh. Sou experiente o suficiente para saber usar o controle de versão, mas não experiente o suficiente para salvá-lo :) Portanto, razões práticas para fazer as coisas ainda são um pouco acadêmicas, se é que você me entende.
durron597
Você não precisa fazer backup de todo o seu repositório . Você pode fazer uma confirmação de "backup" e reverter o HEAD com git reset HEAD~. Seu commit ainda estará ativo git reflogse você decidir que precisa mais tarde. Você pode até dividir uma ramificação (e depois voltar para a ramificação em funcionamento) antes de fazer a redefinição, para dar um nome ao seu "backup". Exclua a ramificação mais tarde, se você não precisar. Edit: Desculpe, não percebi que o OP está no svn!
Joeytwiddle 28/02
3

Você é o único programador; basta fazer um único check-in massivo detalhando os bits importantes do que você fez.

É provável que você reverta "partes" do que fez? Caso contrário, continue com a opção 1.

Existem algumas razões para verificar o código em um sistema de controle de versão. E TODOS eles, quando você é o único desenvolvedor, giram em torno da segurança - ou seja, se você estragar, a máquina morre ou o que for, você sempre pode voltar ao último ponto de verificação.

É improvável que um programador que entre no projeto mais tarde queira reverter para uma versão que não seja compilada. Então, IMHO, a opção 2 é loucura.

A opção 3 parece um sumidouro de tempo: se eu fosse seu chefe e o visse perdendo horas fazendo isso, conversaria um pouco com você sobre quanto vale seu tempo.

Para iterar: ao verificar seu código, você está cobrindo / salvando seu bumbum em caso de falha em sua máquina. Todo o resto, em uma equipe de um homem, é vitrine.

Eu não
fonte
1
A reversão não é a única razão para usar pequenas confirmações. Nem sequer é um motivo particularmente bom. O principal motivo é poder ver quando e por que uma alteração foi introduzida e facilitar a solução de problemas quando você se deparar com um problema de origem desconhecida. Outro programador que entra no projeto mais tarde quase certamente encontrará , pelo menos ocasionalmente, linhas de código que o fazem usar o "WTF" e se referir novamente ao commit onde foi escrito ou modificado pela última vez. Se esse commit é um gigantesco commit que altera 500 coisas, é impossível obter informações úteis da história.
Aaronaught
Aliás, é por isso que as equipes que usam o Git geralmente odeiam commits de mesclagem e solicitam / exigem rebase; mesclagem confirma interrupção bisecte outras técnicas comumente usadas para isolar problemas, porque muitas alterações são agrupadas em uma grande confirmação.
Aaronaught
1
Em nível pessoal, eu concordo que você não deve fazer grandes confirmações, a menos que esteja alterando radicalmente uma base de código. Nesse ponto, você deve ter ramificado de qualquer maneira. No entanto, estamos falando de um único programador que está trabalhando essencialmente desconectado e agora está tentando voltar a fazer a coisa certa. Nesse caso, acredito que um grande commit é preferível.
NotMe
1
@Aaronaught Eu acrescentaria que você mesmo 3 meses depois pode constituir um 'outro programador'.
Maciej Piechotka
1
Também tenho que discordar da ramificação como uma estratégia viável para mudanças arquiteturais ou outras mudanças "destrutivas". Isso apenas leva a um pesadelo de conflitos de mesclagem e erros pós-mesclagem. No longo prazo, é muito menos doloroso descobrir uma maneira de dividir a principal mudança em mudanças menores e compatíveis com versões anteriores ou, no pior dos casos, usar o que Fowler, Humble e o resto chamam de Branch Por abstração (que não é realmente uma ramificação). Ambas as estratégias implicam compromissos pequenos e focados.
precisa saber é o seguinte
2

Minha regra é: nenhum check-in sem uma séria revisão de código. Se eu estiver sozinho, terei que revisar o código pessoalmente, mas ele será revisado. Você parece ter uma quantidade de alterações de código que alguém não pôde revisar, portanto, você não pode revisá-lo (revisar seu próprio código é mais difícil e requer mais disciplina, porque você assume automaticamente que o seu próprio código está correto )

A regra totalmente inquebrável de todo mundo é: nunca faça check-in de código que nem cria e evite seriamente fazer check-in de código que não funciona.

Solução: copie seu código alterado e volte ao ponto original. Mesclar uma alteração de cada vez no código original, revisá-lo, testá-lo e fazer check-in. Com o método de programação que você descreveu, é provável que você encontre alguns erros sérios dessa maneira.

Também é uma boa maneira de treinar bons hábitos de programação.

gnasher729
fonte
Isso é logicamente o mesmo que a resposta baseada em Git acima ( git add --patche git stash) e um bom exemplo de um cenário que os DVCS modernos podem lidar com facilidade, mas os sistemas mais antigos não.
Ron MacNeil
1

Eu acho que você está se preocupando demais. Se você é o único programador e não possui uma folha de especificações contra a qual trabalhar, depende inteiramente de você o que você faz. Suponho que ninguém o castigará por fazer um commit grande, portanto os únicos problemas com os quais você se deparará são tecnológicos, como não conseguir reverter as alterações de arquivos individuais dentro do commit. Como você está no controle do repo neste momento, isso também não deve ser uma grande preocupação.

Há uma linha a ser traçada entre pragmatismo e dogmatismo. O que você fez não seria uma boa idéia em uma equipe e provavelmente não deveria ser repetido daqui para frente, mas na sua situação eu apenas enviaria o commit grande.

Roy
fonte
1
este não parece acrescentar nada substancial sobre o que já foi publicada em prévia de 12 respostas
mosquito
-1

O problema não está nos longos atrasos entre as confirmações, mas no fato de você manter o código em estado não compilável por muito tempo. Primeiro de tudo, qual é a sua definição de 'longo'? Para algumas pessoas, 5 minutos para o estado de transição são demais, mas alguns podem polir seu código por dias sem tentar executar o compilador.

Na verdade, isso não importa - o que importa é que você perdeu o controle do seu código, seu código se tornou incontrolável. Isso é normal, apenas significa que você tem dívida tecnológica e é hora de pensar em refatoração. Então você está frustrado? Seu código não é compilado, você nem tem testes de unidade? Como você pode pensar em refatorar nesse caso? Não se preocupe. Termine sua "codificação de cowboy" e comece a limpá-la. Idealmente, tente escrever alguns testes. Você não tem tempo para isso? Ok, comece com pequenas melhorias.

Algumas alterações não requerem testes. Mude o nome da variável para mais adequado, mova o código de repetição para uma função separada, etc ... Você terá uma melhor idéia do seu código. Depois disso, você pode fazer alterações maiores. Mais uma vez, tente escrever testes, se possível. Torne seu código gerenciável.

Depois disso, você verá que a próxima mudança não demorará "demais" (o que quer que isso signifique).

AlexT
fonte
2
Ele não disse que estava mantendo o código compilável por um longo tempo. O código no repositório não foi modificado por um longo tempo - mas ainda pode ser compilado. O código em sua cópia de trabalho foi atualizado com frequência, mas não confirmado. Nada na questão sugere seu código pode exigir refatoração - aqui "codificação cowboy" refere-se ao seu fluxo de trabalho SCM, não para a qualidade do código real
Idan Arye
@IdanArye Da pergunta original ...Try to break it into smaller commits that likely won't compile...Se algo impedindo você de confirmar seu código do que já é bom, é difícil gerenciar esse código. "Confirmar" é apenas uma das maneiras de manter seu trabalho. Podemos pensar em um caso mais extremo - "se algo me impedir de salvar o arquivo de origem". Então, o que poderia ser? Eu acho que é medo de suas próprias mudanças. Por que pode ser? ... Acho que você entendeu o ponto #
AlexT
2
Para mim, parece mais que o que o impediu de cometer foi mera preguiça.
Idan Arye 27/02
@IdanArye Você está correto em todos os aspectos. Isso além de não fazer TDD suficiente, o que é uma questão separada.
durron597
O @AlexT considera um cenário em que você corrige dois erros, e um deles requer um método recém-desenvolvido. Se você estava cometendo corretamente, você corrige um erro, confirma e depois o outro. Se não estiver, quando você confirmar, precisará incluir as duas alterações no mesmo commit ou confirmar a primeira correção de bug com as alterações da segunda, exceto que a versão confirmada não possui a nova chamada de método e, portanto, não compila.
durron597