¿Qué debo hacer cuando ya he esperado demasiado entre confirmaciones?

100

Fui travieso ... Demasiado "código vaquero", no me comprometí lo suficiente. Ahora, aquí estoy con un enorme compromiso. Sí, debería haber estado comprometiéndome todo el tiempo, pero ya es demasiado tarde.

¿Qué es mejor?

  1. Haga una confirmación muy grande que enumere todas las cosas que cambié
  2. Intente dividirlo en confirmaciones más pequeñas que probablemente no se compilarán, ya que los archivos tienen múltiples correcciones, cambios, nombres de métodos adicionales, etc.
  3. Intente realizar reversiones parciales de archivos solo para las confirmaciones apropiadas, luego vuelva a colocar los nuevos cambios.

Nota: a partir de ahora soy el único programador que trabaja en este proyecto; la única persona que analizará cualquiera de estos comentarios de compromiso soy yo, al menos hasta que contratemos más programadores.

Por cierto: estoy usando SVN y Subclipse. Creé una nueva rama antes de hacer cualquiera de estos cambios.

Más información : hice una pregunta por separado relacionada con cómo me metí en esta situación en primer lugar: cómo prepararse para reescribir el pegamento de una aplicación

durron597
fuente
2
¿Qué programa de control de versiones estás usando? Muchos tienen módulos que le permiten dividir sus ediciones en "trozos", es decir, grupos de líneas modificadas, que le permitirán agrupar sus ediciones de la manera que desee y distribuir las modificaciones de un archivo a varios conjuntos de cambios. Por ejemplo, mercurial tiene la extensión "dejar de lado". Por supuesto, aún debe verificar si cada lote de cambios se compila, si eso es importante para su proceso. Si todo vale la pena, depende de usted y de su tienda.
alexis
66
Al menos verifíquelo en la sucursal, para que no pierda sus cambios.
Rory Hunter
2
Puedes seguir haciéndote la pregunta y esperar aún más, o realmente comprometerte y lidiar con cualquier desorden que cree ... Y luego ... ¡no lo vuelvas a hacer!
haylem
40
# 1, ora por perdón, y luego ve y no peques más :)
Peteris
55
La pregunta más importante que debe hacerse es: "¿Cómo cambio mis malos hábitos para evitar que esto vuelva a ocurrir?". No debería haber ninguna razón para comprometerse no al menos una vez al día, mejor más a menudo.
Doc Brown

Respuestas:

52

Para responder, debe preguntarse cómo espera utilizar los resultados de estas confirmaciones en el futuro. Las razones más comunes son:

  • Para ver qué versión se introdujo un error.
  • Para ver por qué una determinada línea de código está presente.
  • Para fusionarse en otra rama.
  • Para poder consultar una versión anterior para solucionar un problema que un cliente o probador está viendo en esa versión.
  • Para poder incluir o excluir ciertas partes de un lanzamiento.

Las dos primeras razones pueden servirse de la misma manera con un gran check-in, suponiendo que pueda crear un mensaje de check-in que se aplique igualmente bien a cada línea de código modificado. Si usted es el único programador, las confirmaciones más pequeñas no harán que su fusión sea más fácil. Si no planea hacer una versión o prueba con solo una parte de sus cambios no enviados, entonces las dos últimas razones no se aplican.

Hay otras razones para hacer pequeños commits, pero son para cuando estás en medio de los cambios, y ese tiempo ha pasado. Esas razones hacen que sea más fácil retroceder un error o un cambio experimental, y que sea más fácil mantenerse sincronizado con colegas sin grandes fusiones de miedo.

Según tengo entendido de su situación tal como la describió, parece que hay poco o ningún beneficio en dividir su compromiso en este momento.

Karl Bielefeldt
fuente
Excelente respuesta! Si bien no me siento menos arrepentido de no haber hecho pequeños compromisos, me siento mucho mejor acerca de lo que debo hacer para volver a tener un buen comportamiento lo más productivo posible.
durron597
1
La otra cosa sobre 3 y 5 es que cualquier trabajo que haga ahora para permitir que suceda, puede esperar hasta que realmente lo necesite y luego hacer el mismo trabajo. Probablemente será un poco más difícil en el futuro porque su memoria de lo que hizo desapareció. Pero, de nuevo, probablemente nunca lo necesite.
Steve Jessop
En mi experiencia, es problemático y frágil confiar en los comentarios de control de versiones para contar una historia de por qué está el código (es decir, las razones 1 y 2). Si está utilizando SVN con una rama, el historial de confirmación se pierde al fusionar, de todos modos (estará mejor con cosas más modernas como git). Así que, en mi humilde opinión, esos son los mejores comentarios.
Hans-Peter Störr
1
@hstoerr: si está en Subversion 1.5 o posterior, puede conservar el historial con la opción --reintegrate al fusionarse.
Dustin Kendall
1
git add -p es tu mejor amigo aquí. Me enamoré de esa característica. De esta manera, puedo confirmar mis modificaciones estándar de codificación en confirmaciones separadas y mantener aislados los cambios de código relevantes.
Spidey
39

Creo que hagas lo que hagas, trata de evitar registrar el código que sabes que no se compilará.

Si cree que su tercera opción es factible, esa podría ser una buena manera de hacerlo, siempre y cuando pueda asegurarse de que su secuencia de confirmaciones no cree un sistema no compatible. De lo contrario, solo haz el gran compromiso. Es feo, pero es simple, rápido y lo hace. En el futuro, comprométase más a menudo .

FrustratedWithFormsDesigner
fuente
La opción tres es posible, pero llevaría mucho tiempo. Creo que voy a hacer la opción 1
durron597
3
¿Cuáles son las desventajas de cometer código que no compilará o construirá en una rama de características (o similar) que sean tan terribles como para obligar a alguien a evitar "hacer lo que sea que hagan"? Me imagino que otros compromisos realmente terribles podrían ser evitados por otros, que es la única razón real por la que los evitaría en primer lugar (suponiendo, por supuesto, que los compromisos no se están lanzando ).
Kenny Evitt
3
La opción "evitar registrar código que no se compilará" solo se aplica a una base de código / rama compartida. En un proyecto unipersonal o en una rama de desarrollo unipersonal, afirmo que es más importante simplemente llevar tus cambios a VC para que no pierdas cosas.
Stephen C
3
@StephenC, por ejemplo, porque rompe herramientas como git-bisect. Si el código se compila / ejecuta todo el tiempo y necesita encontrar una regresión si se compila todo el tiempo, solo puede realizar una búsqueda binaria (sin mencionar que si hay una regresión en el fragmento de código, queda un gran cambio para leer en lugar de reducir) abajo).
Maciej Piechotka
@MaciejPiechotka - Bueno, obviamente, si necesita usar herramientas específicas en sus sucursales privadas y requieren que el código sea compilable, hágalo. Pero eso no es típico para un proyecto / sucursal de una sola persona.
Stephen C
19

La razón más importante para realizar confirmaciones frecuentes, pequeñas y significativas es ayudar a comprender la historia del código. En particular, es muy difícil entender cómo ha cambiado el código si es difícil generar diferencias comprensibles.

La opción 1 ofusca el historial de cambios que ha realizado, pero de lo contrario no causará ningún problema.

La opción 2 ofusca el historial de cambios que ha realizado, posiblemente algo menos que la opción 1, pero podría causar otros problemas para usted u otros si asumen o concluyen que las confirmaciones son distintas, por ejemplo, pueden fusionarse en otras ramas de forma independiente. A menos que haya una razón práctica sólida por la que se prefiere esto a la opción 1, es menos ideal.

La opción 3 es la mejor, todo lo demás es igual, pero si, como ha descrito en otra parte, hacerlo requeriría cantidades de tiempo "extremas" o incurriría en otros costos significativos, tendrá que sopesar esos costos con los beneficios esperados de creando compromisos más limpios.

De acuerdo con la información que ha proporcionado, optaría por la opción 1. ¿Quizás debería configurar recordatorios para que confirme los cambios?

Creación de prototipos y reescritura

Otra consideración a tener en cuenta, especialmente a la luz de su nota sobre ser el único programador, y mi sospecha de que está trabajando en una base de código relativamente nueva, es que probablemente sea bueno desarrollar diferentes hábitos con respecto a cometer cambios para cuando estamos creando prototipos de código nuevo en lugar de mantener o ampliar el código existente. Probablemente no haya una división terriblemente aguda entre los dos, pero creo que sigue siendo una distinción útil.

Cuando esté creando prototipos de código nuevo, confirme cada vez que desee guardar sus cambios, casi con seguridad en una rama, pero tal vez en un proyecto separado. O tal vez incluso simplemente trabajar fuera del control de versiones por completo. En su lugar, puede concentrarse en reunir evidencia sobre la viabilidad de varias hipótesis o diseños que está considerando. A menudo escribo prototipos pequeños usando diferentes herramientas, por ejemplo, LINQPad en lugar de Visual Studio para el código C #.

Cuando haya validado una hipótesis o diseño en particular, vuelva a escribirlo en su proyecto principal, idealmente en una rama, y ​​realice los compromisos pequeños y significativos que ayudarán mejor a la comprensión de los demás (incluido el futuro) en cuanto a la naturaleza de los cambios estás haciendo

Kenny Evitt
fuente
1
Buena respuesta; Kenny, ¿tiene un buen artículo u otra base de conocimiento para vincular con detalles más específicos sobre la creación de prototipos? Mi versión de creación de prototipos es "boceto en cuaderno o en pizarra"
durron597
@ durron597, no puedo pensar en ningún enlace (incluso para buscar) fuera de mi cabeza. ¡He jugado con suficientes lenguajes de programación interpretados (y compilados dinámicamente) que ni siquiera pensé que la idea de 'creación de prototipos' podría ser nueva! Y he reescrito tantos programas C, C ++ y Java (una y otra vez) que no pensé que eso también podría ser poco común, o al menos novedoso para algunos.
Kenny Evitt
12

Aunque la única respuesta razonable es nunca romper el tronco , algunas veces no es posible. Por ejemplo, svn puede romper el compromiso si se compromete demasiado (tal vez una opción o una característica, no estoy seguro). En tales casos especiales, solo regístrese en pedazos. Como usted es un programador único, no molestará a nadie.

Por lo tanto, elegiría la opción 1. Si no es posible, entonces la opción 2.

La opción 3 requiere mucho esfuerzo, y simplemente no vale la pena.

BЈовић
fuente
1
o etiquete las versiones que no compilan como "NO COMPILA"
fanático del trinquete
2
@ratchetfreak: Supongo que una "etiqueta" en SVN no ayudará mucho, ya que las etiquetas no funcionan como "comentarios" en el tronco.
Doc Brown
@DocBrown me refería a agregarlo al mensaje de confirmación
fanático del trinquete
55
@ratchetfreak Lo haría como "PARTE X / N: registro en ABC - NO COMPILA"
B 27овић
La opción 3 no requiere mucho esfuerzo. Otra respuesta explica cómo hacerlo de manera rápida y fácil usando git add --patchy git stash. La situación solo parece difícil debido a las herramientas y el conocimiento obsoletos de control de fuentes.
Ron MacNeil
7

Intente dividirlo en confirmaciones más pequeñas que probablemente no se compilarán, ya que los archivos tienen múltiples correcciones, cambios, nombres de métodos adicionales, etc.

Cuando me encontré en una situación similar, utilicé la siguiente técnica:

  1. Agregue solo el código que sea relevante para una característica particular: git add --patch
  2. Guarda todos los demás cambios: git stash save --keep-index
  3. Ejecute pruebas / intente compilar
  4. Confirmar cambios si todo está bien, si no, vaya a 1

No estoy familiarizado con SVN, por lo que no sé si esto es aplicable a su situación específica, pero la base debería ser la misma: aislar pequeñas partes del código y probarlas individualmente.

Milos
fuente
Me gusta esto, pero desafortunadamente una de las muchas cosas en mi lista de tareas pendientes (hay muchas cuando eres el único técnico en una empresa) es cambiar de SVN a git, y todavía no he llegado a eso. .
durron597
1
Como no tengo el tiempo suficiente para usar --patch, uso Deshacer en varios paneles del editor, para llegar a estados de trabajo anteriores y comprometerlos. Luego rehago para la próxima confirmación. Debido a la tentación de hacer pequeñas adiciones al código cuando estoy en estado Deshecho, ¡siempre hago una copia de seguridad antes de comenzar este proceso!
joeytwiddle
Con git también puede agregar interactivamente (agregar -i) antes de confirmar y bifurcar después para validar sus confirmaciones de forma independiente.
riezebosch
3

¿Qué tal la opción 4 ?: Haga una copia de seguridad del estado actual de su repositorio en un lugar temporal, revierta su repositorio a su estado original, haga una lista de todos los cambios que hizo (aún puede ver la copia de seguridad temporal), luego vuelva a implementar manualmente (y compile y probarlos!) como commits separados.

Esto debería ser más fácil, porque ya ha escrito el código, es solo un poco averiguar qué partes copiar y pegar desde su copia de seguridad temporal.

Cuando haya vuelto a implementar cada cambio de manera limpia y, de este modo, se haya asegurado de que las confirmaciones sean independientes, pequeñas y compiladas, puede eliminar la copia de seguridad temporal, y todo será casi exactamente como (excepto la hora / fecha de las confirmaciones) hubiera sido si lo hicieras desde el principio.

Superbest
fuente
Esta es solo una forma de hacer la opción # 3. Probablemente la mejor manera, cierto, pero aún así consume bastante tiempo.
durron597
Hubo 149 líneas de Agregar / Eliminar / Enviar mensajes cuando hice la gran confirmación. Eso es al menos medio día para hacer esto.
durron597
@ durron597 No estoy de acuerdo, creo que esto es diferente del # 3. Con respecto a 149 líneas, ¿cuánto valora un historial de confirmación limpio? ¿Vale la pena pasar medio día? De todos modos, no es como si los otros métodos no requirieran averiguar qué línea debería estar en qué confirmación, por lo que tendrá que pasar por las 149 líneas de cualquier manera. La diferencia en el tiempo será pequeña.
Superbest
Je Tengo suficiente experiencia para saber cómo usar el control de versiones, pero no lo suficiente como para haberlo salvado nunca. Así que las razones prácticas para hacer las cosas siguen siendo un poco académicas, si sabes a lo que me refiero.
durron597
No tiene que hacer una copia de seguridad de todo su repositorio . Puede realizar una confirmación de "copia de seguridad" y luego hacer retroceder el HEAD con git reset HEAD~. Su confirmación seguirá activa git reflogsi decide que la necesita más tarde. Incluso podría bifurcar una bifurcación (y luego volver a la bifurcación de trabajo) antes de reiniciar, para darle un nombre a su "copia de seguridad". Elimine la rama más tarde si no la necesita. Editar: Lo siento, no me di cuenta de que OP está en svn!
joeytwiddle
3

Eres el único programador; solo haz un registro masivo detallado que detalla las partes importantes de lo que hiciste.

¿Es probable que revierta "partes" de lo que hizo? Si no, entonces continúe con la opción 1.

Hay un par de razones para verificar el código en un sistema de control de versiones. Y TODOS ellos, cuando eres el único desarrollador, giran en torno a la seguridad, es decir, si te equivocas, la máquina muere o lo que sea, siempre puedes volver a ese último punto de control.

Es poco probable que un programador que ingresa al proyecto más tarde quiera volver a una versión que no se compila. Entonces, en mi humilde opinión, la opción 2 es la locura.

La opción 3 suena como una pérdida de tiempo, que si yo fuera tu jefe y te viera desperdiciando horas haciendo esto, hablaría contigo sobre lo que vale tu tiempo.

Para iterar: al registrar su código, está cubriendo / guardando su trasero en caso de falla en su máquina. Todo lo demás, en un equipo de un solo hombre, es escaparatismo.

Yo no
fuente
1
Retroceder no es la única razón para usar pequeños commits. Ni siquiera es una razón particularmente buena. La razón principal es poder ver cuándo y por qué se introdujo un cambio, y facilitar la solución de problemas cuando se enfrenta a un problema de origen desconocido. Otro programador que ingrese al proyecto más tarde, casi con seguridad , al menos ocasionalmente encontrará líneas de código que lo harán ir a "WTF" y volver a consultar el commit donde se escribió por primera vez o se modificó por última vez. Si esa confirmación es una confirmación gigante que cambia 500 cosas, es imposible obtener información útil del historial.
Aaronaught
Por cierto, esta es la razón por la cual los equipos que usan Git generalmente odian los compromisos de fusión y solicitan / requieren rebases en su lugar; fusionar commits break bisecty otras técnicas comúnmente utilizadas para aislar problemas, porque tantos cambios se agrupan en una gran confirmación.
Aaronaught
1
A nivel personal, estoy de acuerdo en que no debe realizar grandes confirmaciones a menos que cambie radicalmente una base de código ... en ese punto, debería haberla ramificado de todos modos. Sin embargo, estamos hablando de un único programador que ha estado trabajando esencialmente desconectado y ahora está tratando de volver a hacer lo correcto. En ese caso, creo que es preferible una gran confirmación.
NotMe
1
@Aaronaught Agregaría que 3 meses después puede constituir un "otro programador".
Maciej Piechotka
1
También tengo que estar en desacuerdo con la ramificación como estrategia viable para cambios arquitectónicos u otros cambios "destructivos". Eso solo conduce a una pesadilla de conflictos de fusión y errores posteriores a la fusión. A la larga, es mucho, mucho menos doloroso, encontrar una manera de dividir el cambio principal en cambios más pequeños y compatibles con versiones anteriores, o, en el peor de los casos, usar lo que Fowler, Humble y el resto de ellos llaman Branch Por abstracción (que en realidad no es una rama). Ambas estrategias implican compromisos pequeños y específicos.
Aaronaught
2

Mi regla es: no registrarse sin una revisión seria del código. Si estoy solo, tendré que revisar el código yo mismo, pero será revisado. Parece que tiene una cantidad de cambios en el código que otra persona no pudo revisar, por lo tanto, no puede revisarlo usted mismo (revisar su propio código es más difícil y requiere más disciplina, porque automáticamente asume erróneamente que su propio código es correcto )

La regla totalmente inquebrantable de todos es: nunca registre un código que ni siquiera se construye, y evite seriamente registrar un código que no funciona.

Solución: copie el código modificado y vuelva al punto original. Combine un cambio a la vez en el código original, revíselo, pruébelo, verifíquelo. Con el método de programación que describió, seguramente encontrará algunos errores graves de esa manera.

También es una buena manera de capacitarse en buenos hábitos de programación.

gnasher729
fuente
Esto es lógicamente lo mismo que la respuesta anterior basada en Git ( git add --patchy git stash) y un buen ejemplo de un escenario que los DVCS modernos pueden manejar fácilmente pero los sistemas más antiguos no pueden.
Ron MacNeil
1

Creo que te estás preocupando demasiado. Si usted es el único programador y no tiene una hoja de especificaciones para trabajar, entonces depende completamente de usted lo que haga. Supongo que nadie lo va a castigar por realizar una gran confirmación, por lo que los únicos problemas con los que se encontrará son tecnológicos, como no poder deshacer los cambios de archivos individuales dentro de la confirmación. Sin embargo, dado que usted tiene el control exclusivo del repositorio en este momento, tampoco debería ser una gran preocupación.

Hay una línea entre el pragmatismo y el dogmatismo. Lo que hiciste no sería una buena idea en un equipo y probablemente no debería repetirse en el futuro, pero en tu situación, simplemente enviaría el gran compromiso.

Roy
fuente
1
Esto no parece agregar nada sustancial sobre lo que ya se publicó en las 12 respuestas anteriores
mosquito
-1

El problema no está en los largos retrasos entre confirmaciones, sino en el hecho de que mantiene el código en estado no compilable durante demasiado tiempo. En primer lugar, ¿cuál es su definición de 'largo'? Para algunas personas, 5 minutos para el estado de transición es demasiado, pero algunos pueden pulir su código durante días sin siquiera intentar ejecutar el compilador.

De hecho, no importa: lo que importa es que perdió el control de su código, su código se volvió inmanejable. Esto es normal, solo significa que tiene una deuda tecnológica y es hora de pensar en la refactorización. ¿Entonces estás frustrado? Tu código no se compila, ¿ni siquiera tienes pruebas unitarias? ¿Cómo puedes pensar en refactorizar en este caso? Sin preocupaciones. Termine su "codificación de vaquero" y comience a limpiarla. Lo ideal es intentar escribir algunas pruebas. ¿No tienes tiempo para eso? Ok, comienza con pequeñas mejoras.

Algunos cambios no requieren pruebas. Cambie el nombre de la variable por una más adecuada, mueva el código repetido a una función separada, etc. Obtendrá una mejor idea de su código. Después de eso puedes hacer cambios más grandes. Nuevamente, intente escribir pruebas si es posible. Haz tu código manejable.

Después de eso, verá que el próximo cambio no le toma "demasiado tiempo" (lo que sea que signifique).

AlexT
fuente
2
No dijo que mantuvo el código no disponible durante mucho tiempo. El código en el repositorio no se modificó durante mucho tiempo, pero todavía es compilable. El código en su copia de trabajo se actualizó con frecuencia pero no se confirmó. Nada en la pregunta sugiere que su código pueda requerir refactorización: la "codificación de vaquero" aquí se refiere a su flujo de trabajo SCM, no a la calidad real del código
Idan Arye
@IdanArye De la pregunta original ...Try to break it into smaller commits that likely won't compile...Si algo le impide cometer su código, entonces ya es una buena señal de que el código es difícil de administrar. "Comprometerse" es solo una de las formas de persistir en su trabajo. Podemos pensar en un caso más extremo: "si algo me impide guardar el archivo fuente". Entonces, ¿qué podría ser? Supongo que es miedo a tus propios cambios. ¿Por qué puede ser? ... Supongo que
entendiste bien
2
A mí me parece más que lo que le impidió cometer fue mera pereza.
Idan Arye
@IdanArye Tienes razón en todos los aspectos. Eso además de no hacer suficiente TDD, que es un tema separado.
durron597
@AlexT considera un escenario en el que corrige dos errores, y uno de ellos requiere un método recientemente desarrollado. Si se había estado comprometiendo correctamente, corrige un error, se compromete y luego corrige el otro error. Si no lo está, entonces cuando se compromete, debe incluir ambos cambios en el mismo compromiso, o confirmar la primera corrección de errores con los cambios para el segundo, excepto que la versión confirmada no tiene la nueva llamada al método y, por lo tanto, no compila
durron597