¿Por qué no cometer cambios no resueltos?


15

En un VCS tradicional, puedo entender por qué no comprometerías archivos sin resolver porque podrías romper la compilación. Sin embargo, no entiendo por qué no debe comprometer los archivos sin resolver en unos DVCS (algunos de ellos en realidad evitar que se cometan los archivos).

En cambio, creo que su repositorio debería estar bloqueado de empujar y tirar , pero no comprometerse.

Ser capaz de comprometerse durante el proceso de fusión tiene varias ventajas (como lo veo):

  • Los cambios reales de fusión están en la historia.
  • Si la fusión fue muy grande, podría realizar confirmaciones periódicas.
  • Si cometió un error, sería mucho más fácil retroceder (sin tener que rehacer toda la fusión).
  • Los archivos pueden permanecer marcados como no resueltos hasta que se marquen como resueltos. Esto evitaría empujar / tirar.

También podría tener un conjunto de conjuntos de cambios que actúen como la combinación en lugar de solo uno. Esto le permitiría seguir utilizando herramientas como git rerere.

Entonces, ¿por qué cometer con archivos no resueltos está mal visto / impedido? ¿Hay alguna otra razón que no sea la tradición?


1
¿Por quién está mal visto o impedido?
pdr

@pdr Algunos desarrolladores con los que trabajé lo desaprobaron. Al menos hg 1.6después de una fusión, los archivos se marcan como no resueltos. hgserá no dejará enviar hasta que se haya marcado como resuelto (no necesariamente significa que realmente tiene que resolverlos, pero que supongo que esa es la idea).
Píldoras de explosión

1
Entonces, por "archivos no resueltos", ¿quiere decir realmente "fusiones no resueltas"?
pdr

@pdr no, en hgrealidad mantiene una lista de archivos que se han marcado o no como "resueltos" (usando hg resolve). Si hay Uarchivos en esta lista, no le permitirá comprometerse.
Píldoras de explosión

1
hg resolvese usa específicamente para fusiones con conflictos; ver selenic.com/mercurial/hg.1.html#resolve . Note that Mercurial will not let you commit files with unresolved merge conflicts. You must use hg resolve -m ... before you can commit after a conflicting merge.
Mike Partridge

Respuestas:


6

El mayor problema que puedo ver es que crea una ventana de confirmaciones donde las cosas están medio fusionadas y (probablemente) no funcionan correctamente. Cuando empuja el conjunto final de confirmaciones locales, todas esas confirmaciones intermedias también aparecerán para todos los demás. En el mundo ideal, debería poder extraer cualquier commit y el código debería funcionar. Si comienza a comprometerse en medio de fusiones, el estado del código no está bien definido.

Una cosa que podría hacer es realizar confirmaciones locales para su fusión, y luego agruparlas en una gran confirmación cuando presiona (aunque no estoy seguro de cómo (¿si?) Alguna vcs admite esto). Si bien esto podría generar algunos de los beneficios que mencionó, no estoy seguro de que valga la pena la complejidad adicional (ya estamos tratando con un área bastante confusa y compleja).


55
No sé si estoy de acuerdo con la capacidad de hacer un commit y hacer que funcione. Gran parte del punto de comprometerse en un DVCS es comprometer su progreso , por lo que las cosas se romperán o se incompletarán la mayor parte del tiempo. .
Píldoras de explosión

2
Siempre tener compromisos de trabajo tiene algunos buenos beneficios. Por ejemplo, si está intentando rastrear cuándo se introdujo un error, es útil poder atravesar el historial para ver cuándo se rompió algo (vcs incluso tienen comandos para realizar búsquedas binarias en el historial). Si no tiene confirmaciones de trabajo, no podrá rastrear errores tan eficazmente.
Oleksi

1
Git admite confirmaciones agrupadas.
deltree

3

Estoy más familiarizado con Git, por lo que responderé por esa perspectiva.

No veo una razón por la cual usted o cualquier buen VCS deseen permitir la confirmación de un archivo no fusionado, especialmente si se trata de código. Debe mantener el repositorio en un estado coherente, y lo que sugiere violaría la atomización de commit. Muchos VCS cambian físicamente el archivo para mostrar dónde están los conflictos: Git, SVN y CVS usan marcadores de tipo >>>> <<<<. En un VCS con compromisos y fusiones de nivel de repositorio atómico, simplemente habría creado un nodo que no tiene sentido para nadie más que para usted. En el desarrollo de software, su proyecto no se pudo construir. En el documento de un grupo, nadie sabe qué cambios son correctos.

Ahora, Git proporciona algunas herramientas que podrían facilitar esto, si fuera el tipo de confirmación que sugieres permitido. Podría aplastar todos los commits combinados antes de presionar, por ejemplo. Eso termina siendo lo mismo que un típico compromiso de fusión.

Preocupaciones específicas sobre su lista de beneficios:

  1. Los cambios reales de fusión están en la historia. ¿Por qué necesitas información adicional? Los DVCS son muy buenos para limitar conflictos a áreas confinadas. Una vez que elija qué conjunto de cambios mantener, comparar la copia del nodo de confirmación de fusión con la copia anterior le dará exactamente esto.
  2. Si la fusión fue muy grande, podría realizar confirmaciones periódicas. Esta es una preocupación válida, pero nunca deberías llegar aquí en primer lugar. Las sucursales deben estar constantemente introduciendo cambios aguas arriba para que esto nunca suceda. Las herramientas como rebaseseleccionar un compromiso a la vez también pueden ayudarlo aquí en algunas situaciones.
  3. Si cometió un error, sería mucho más fácil retroceder (sin tener que rehacer toda la fusión). Vea arriba: sus conflictos no deberían volverse tan inmanejables.

La única forma en que esta sugerencia podría funcionar es si la rama fuera si toda la fusión fuera atómica: podría ver una serie de confirmaciones, pero serían simplemente pasos en una confirmación de fusión más grande que debe tratarse como un nodo en el árbol de confirmación . No creo que ningún VCS actual tenga soporte para este tipo de flujo de trabajo, y no creo que sea necesario.


Los conflictos probablemente no deberían volverse tan inmanejables, pero a menudo lo son (al menos en mi experiencia). Creo que toda la fusión debería ser atómica; eso es lo que estoy sugiriendo. Puede que no sea necesario, solo me pregunto por qué no se ha hecho. Tampoco puede elegir necesariamente una u otra opción en un conflicto; a veces es una combinación de ambos cambios. Esto es especialmente confuso.
Píldoras de explosión

"Debe mantener el repositorio en un estado coherente". No creo que sea verdad. Un repositorio local es un espacio de trabajo , no un santuario. Si ayuda a comprometerse en medio de una fusión, hágalo en mi humilde opinión. Si haces esto porque no sabes nada mejor, te sugiero que no lo hagas. Sin embargo, si eres un programador experimentado, debes hacer lo que sea mejor para ti. No seas dogmático acerca de mantener tu repositorio local prístino.
Bryan Oakley

1

Mi experiencia principal radica en Mercurial, aunque también uso git esporádicamente.

Mercurial no le permite cometer archivos no resueltos, solo lo desalienta . El mismo trato con presionar antes de hacer cambios que no tienes.

Todo lo que necesita hacer en Mercurial es, una vez que tenga los archivos de la forma en que desea enviarlos:

hg resolve --mark --all
hg commit -m "I'm such a rebel"

--marcar ... marcará los archivos como resueltos sin preguntarle con la herramienta de fusión. --todos se encargarán de seleccionar todos los archivos marcados con conflictos.

Si quieres empujar sin tirar (y consecuentemente tener que fusionar los cambios de otros) haz como un Jedi :

hg push --force

El siguiente tipo que tire obtendrá +1 cabeza (sin juego de palabras)

Estoy seguro de que hay una manera de hacer lo mismo con Git (aunque probablemente sea más complicado).


1

Cuando me fusiono en git, inmediatamente confirmo todos los cambios (incluidos los conflictos de fusión). Luego, en mi próximo commit (s), resuelvo los conflictos de fusión a través de un editor de texto. Después de que se resuelven los conflictos, presiono si lo desea.

Honestamente, no entiendo por qué otros no lo hacen de esta manera, o git no lo hace cumplir.

  • El "compromiso de fusión" es ahora un historial limpio de exactamente lo que se necesitaba fusionar.
  • Las siguientes confirmaciones muestran exactamente lo que hizo para resolver los conflictos de fusión.
  • Cuando presiona, los conflictos se resuelven y la compilación no se rompe en la punta de la rama.
  • En cualquier momento, si arruinas la resolución del conflicto, simplemente puedes volver a una de las confirmaciones de "post fusión" e intentar nuevamente.

Una gran desventaja del flujo de trabajo estándar de resolución de conflictos antes de comprometerse es que los cambios de su copia local pueden colarse. Las adiciones están ocultas de la revisión del código por la diferencia de fusión masiva, por lo que no se da cuenta de que ha cometido accidentalmente una API clave o etc.

Mi flujo de trabajo descrito anteriormente evita este problema de copia local y también permite que los revisores de código examinen (solo) los detalles de su resolución de fusión en un commit diff que se ve exactamente como un diff de commit estándar.


0

Creo que es mejor impulsar pequeños cambios y presionar a menudo, cuando sea posible (y, por supuesto, no siempre), y no comprometer el código que no se construye o está a medio completar (todos cometemos errores, pero no No lo hagas a propósito). También vengo de git, y una de las mejores cosas que creo es el hecho de que puede tener una copia viable del repositorio en su escritorio ... que luego puede modificar a su gusto. Cuando termines tus grandes cambios, envíalo lejos.

Hacer una gran cantidad de código abierto con git, la mayor frustración para mí fue obtener el código a medio terminar en el repositorio e intentar hacer una compilación, pero no pude, porque el tipo hizo la mitad del trabajo y dijo "Estoy ocupado ahora , Lo terminaré en una semana ". Así que terminaría teniendo que desecharlo (lo que molestaría al chico), o tomarme el tiempo para terminarlo e integrarlo por completo.

Supongo que desde mi perspectiva, guarda las cosas del medio culo localmente, envía las cosas buenas por cable.


0

No seas esclavo de tus herramientas.

El objetivo de un VCS es permitirle hacer su trabajo. Su trabajo no es mantener un repositorio local prístino, su trabajo es escribir código. Si comprometerse temprano ya menudo localmente le permite trabajar mejor, hágalo.

Sin embargo, no debe empujar el código roto en sentido ascendente.


0

Porque fundamentalmente es una mala idea: lo llevará a un repositorio que se encuentra en un estado lamentable (y es precipitado suponer que alguna vez presionará en cualquier lugar, aunque uno argumentaría que siempre debe tener al menos una copia).

Puedo ver que, en el caso de una fusión grande / compleja, es posible que desee guardar su trabajo en progreso y establecer un punto de referencia, pero aún así dejaría el sistema en un estado desordenado que debe resolverse.

Y hay alternativas, tiene la opción de fusionarse desde antes que la cabeza, que bien pueden darle la capacidad de adaptarse a los cambios sin fusiones épicas (o al menos con fusiones más grandes que son más fáciles de comprender).

Este es el caso que encuentro que el rebase de git es particularmente útil (sujeto a las advertencias habituales sobre el rebase) porque estás reproduciendo tus cambios por encima del estado actual que tienes para arreglar los conflictos en partes más pequeñas.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.