- Las revisiones de PR al estilo GitHub facilitan seguir apilando commits de corrección sobre el cambio original, lo que genera el problema de mezclar el proceso de revisión con el historial final del código
- Una buena serie de parches debería poder leerse en orden como commits separados lógicamente, por ejemplo refactorización, agregado de una nueva API y migración de usuarios existentes
- Cuando se acumulan commits como “fix review” o
"minor", la intención del cambio se vuelve menos clara y aumenta el costo de encontrar la causa de un problema con git blame y git bisect
- Una revisión con interdiff publica una nueva versión de la serie de parches y compara las diferencias por commit con
git range-diff main..v1 main..v2
- El revisor puede revisar solo un incremento de 50 líneas en lugar de releer las 500 líneas completas, y el autor puede conservar la estructura final de commits sin commits ruidosos como “address review”
Herramientas de revisión de código y punto de partida
- Gerrit Code Review es una herramienta open source de revisión de código que funciona junto con repositorios Git y soporta el flujo de enviar parches, permitir que otras personas revisen el código y dejar comentarios
- Hay muchas formas de hacer revisión de código: Gerrit, GitHub y Phabricator, pero también subir archivos
.patch a un bug tracker, usar git send-email o guiar una implementación tras una larga discusión con colegas
- El lenguaje de programación Go usa Gerrit, KDE y LLVM usaron Phabricator, y Jujutsu alguna vez evaluó usar Gerrit
- El kernel de Linux usa de una manera particular un flujo de trabajo basado en correo electrónico, y muchos proyectos eligen GitHub porque es fácil de usar y tiene bajo costo de entrada
- El problema central es que las herramientas no ofrecen el mismo modelo de revisión, y la experiencia predeterminada de GitHub no siempre es suficiente
Condiciones de una buena serie de parches
- Una serie de parches ideal consiste en enviar un cambio grande dividido en pasos lógicos
- Primero, se hace una limpieza de código encontrada incidentalmente
- Luego, se agrega una nueva API
- Por último, se migra a los usuarios de la API existente hacia la nueva API
- Cada parche debe tener una razón independiente y, al aplicarlos en orden, debe verse cómo el código evoluciona paso a paso
- Esta estructura es útil no solo para el autor y los revisores, sino también para los mantenedores que más adelante tengan que buscar el motivo de un cambio con
blame o bisect
- El tamaño real de un parche depende de la situación
- Puede que no haya refactorización
- Puede ser de 100 líneas
- Si se trata de un cambio central de API que obliga a corregir todos los puntos de llamada, puede llegar a 500 líneas
El historial mezclado que genera la “diff soup” al estilo GitHub
- Al incorporar comentarios de revisión, GitHub incentiva de forma explícita e implícita un flujo en el que se agregan nuevos commits encima de los commits originales
- En el ejemplo, después de los 3 commits originales se van apilando, en orden, commits que atienden las revisiones de Alice y Bob, agregan pruebas e implementan un cambio
"minor"
- Como en el grafo de commits solo quedan relaciones padre-hijo, no queda claro qué problema de qué commit original corrigió cada commit de revisión
- Si un único commit “fix review” toca varios commits originales a la vez, el modelo conceptual se vuelve más complejo
- Se podría hacer que cada commit de corrección refleje exactamente un solo señalamiento, pero eso aumenta la cantidad de commits fixup
- Esta forma en que un paquete grande de cambios y las correcciones de revisión quedan mezclados en un mismo recipiente es la “diff soup”
Se enturbia la señal de git blame y git bisect
- Como
git blame opera por línea, si un commit de revisión cambia aunque sea una pequeña parte de una línea existente, el origen de esa línea puede aparecer como un commit del estilo "fix alice review"
- Para encontrar la razón real del cambio, se vuelve necesaria una arqueología de commits que siga de nuevo tanto el commit original como el commit de corrección de revisión
- En
git bisect, también puede volverse ambiguo si el commit "minor" fue la causa real o si era un bug presente desde que se agregó por primera vez la nueva API y recién se manifestó más tarde
- Si la nueva API ofrece una gran mejora de rendimiento, revertirla podría no ser deseable o incluso no ser posible
- Si la regresión aparece semanas después, en una situación urgente como una reunión P1, surge el costo de tener que investigar más a partir de un mensaje de commit que solo dice
"minor"
- Incluso en un ejemplo con solo dos idas y vueltas de revisión, el historial se vuelve complejo; en proyectos open source donde la revisión se repite varias veces, el problema crece aún más
Cómo la UX de GitHub refuerza este flujo
- En GitHub, para hacer una revisión incremental, en la práctica lo más fácil es agregar nuevos commits encima
- Para el revisor, es menos pesado ver un parche
"fix alice review" de +/- 10 líneas que releer 500 líneas de una nueva API
- La pestaña de diff del PR muestra por defecto todos los commits combinados en un único diff
- Es parecido a ver
git diff master..foo-branch
- No encaja bien con la forma en que la gente escribe y lee cambios
- La UX de GitHub está fuertemente adaptada al modelo de ramas con nombre, lo que dificulta ver diferencias entre unidades que no sean ramas
- Después de un force push, se puede ver un diff con el botón “Compare” en la línea “Force Push” del PR
- Pero solo muestra el diff completo entre el head anterior de la rama y el head actual de la rama
- Para una comparación más granular, hay que buscar directamente los IDs de commit y ponerlos en la URL
Revisión con interdiff y git range-diff
- Una revisión con interdiff no agrega commits de corrección encima de los 3 commits originales, sino que publica una nueva versión compuesta por los mismos 3 commits
- Por ejemplo, si hay que incorporar un comentario de Bob a la serie de parches
v1, se modifican el primer y el tercer commit para crear la serie v2
- Aunque después se incorporen del mismo modo los comentarios de Alice, se agreguen pruebas y se haga el cambio
"minor", el resultado final sigue quedando en 3 commits
- Si los commits A, B y C de
v1 evolucionaron a X, Y y Z en v2, git range-diff muestra la diferencia entre los commits de cada posición
git range-diff \
main..v1 \
main..v2
- Este comando muestra el diff por pares entre los 3 commits de la rama
v1 y los 3 commits de la rama v2
- El primer commit es
diff(A, X)
- El segundo commit es
diff(B, Y)
- El tercer commit es
diff(C, Z)
Efectos prácticos del enfoque interdiff
- A diferencia de GitHub, que normalmente muestra el diff completo de la rama, como
diff(main, C) o diff(main, Z), interdiff muestra las diferencias entre versiones de commits
- El revisor puede revisar solo las 50 líneas modificadas, sin releer el cambio de API de 500 líneas que ya vio
- El autor no necesita apilar en el historial 30 commits ruidosos como “address review”
git blame tiene más probabilidades de conectar las líneas con el commit del cambio original, con menos ruido
git bisect tiene más probabilidades de apuntar la regresión a una unidad más significativa, como el commit de la nueva API
- Como resultado, mejora la relación señal-ruido de las herramientas básicas de diagnóstico
Nota sobre estrategias de merge y rebase
- La explicación sobre estrategias de merge de parches quedó como TODO
- La postura es que
git rebase está bien siempre que no se trate de una rama pública sobre la que se espera que otras personas basen commits
- Un sistema de revisión con interdiff fomenta parches más pequeños y que puedan mergearse más rápido
- No hace falta esperar a que los 5 commits estén listos
- Si los primeros 3 están bien y los 2 últimos necesitan más trabajo, se pueden mergear solo los 3
- El objetivo es hacer que la gente trabaje sobre la rama main, no sobre ramas de larga duración, para reducir situaciones en las que varias ramas remotas se entrelazan y se mergean entre sí
- También hay proyectos, como el kernel de Linux, que mergean ramas públicas con otros repositorios o las publican explícitamente encima de otras ramas
- Los desarrolladores de Linux pueden usar
git rebase al crear y pulir una serie de parches
- Pero una vez que crean una rama pública, como puede ser mergeada en el árbol de alguien, no hacen force push y crean una nueva rama con nuevos commits
1 comentarios
Opiniones de Hacker News
En GitHub suelo usar más o menos este flujo; la desventaja es que me da más trabajo y no es intuitivo para mis colaboradores.
Aun así, mantiene las ventajas de que el revisor puede ver solo la diferencia que incorpora sus comentarios, y de que no rompe
git blamenigit bisect.Cuando incorporo feedback de la revisión, hago commit con
git commit --fixupy, después de hacer push, dejo el hash del commit fixup en la respuesta al comentario de revisión.Cuando el PR ya fue aprobado y está justo antes de fusionarse, ejecuto
git rebase --interactive origin/main --autosquashpara combinar los commits fixup con los commits originales, y por último hagogit push --force-with-leasey lo fusiono.Hay que tener cuidado con hacer force push antes de que termine la revisión. Si lo haces, el revisor ya no podrá ver lo que se agregó desde su última revisión.
Dependo bastante del autocompletado de la terminal, así que con teclear algo como
git repuedo llegar hasta el comando largo, pero es un poco tosco; sería bueno tener una herramienta que soporte y fomente este flujo. Aun así, si estás atado a GitHub, con esto alcanza bastante.Eso sí, en la práctica suele usarse solo en equipos de ingeniería disciplinados que aprenden deliberadamente funciones avanzadas de git.
~/.gitconfig:[rebase] autosquash = trueAsí, de ahí en adelante, con solo
git rebase -i origin/main, los commits fixup/squash se reordenan automáticamente. Es una configuración pequeña, pero mejoró mucho mi flujo de trabajo.Es un terreno parecido a cuando necesitas
--update-refsal hacer rebase de una serie de commits con varias ramas encima. ¿Por qué tendría una persona que rastrear las relaciones del grafo, insertar commits manualmente y mover ramas? Las computadoras manejan bien los grafos; dejémoselo a ellas.También existe
git absorb, pero no es tan robusto como la implementación de Sapling[1].El verdadero problema no es si se usa rebase interactivo o no, sino, en general, la experiencia de usuario de la herramienta de revisión y los ciclos que induce. Por ejemplo, los commits fixup no resuelven el problema de que GitHub muestre diferencias entre puntos de referencia, y si el punto de referencia es grande puede arruinar por completo la revisión. Por ejemplo, cuando hiciste rebase encima de 10 commits nuevos.
También tengo quejas sobre la UX del propio Git, pero el texto original es más que nada una queja sobre GitHub.
[1] En este issue de GitHub hay un ejemplo que muestra la diferencia entre los dos algoritmos base: https://github.com/martinvonz/jj/issues/170
Estoy 100% de acuerdo en que este enfoque es el ideal. La forma de GitHub es realmente horrible, y es una tragedia que tanta gente haya llegado a aceptarla como normal.
Antes lo hacía así con Phabricator, y gracias a una macro de línea de comandos que actualizaba todas las revisiones de una vez, era posible hacerlo de forma más o menos manual. Aun así, sería mejor tener una UI explícita.
Exacto. Esto es justo lo que imaginaba en mi cabeza como un verdadero estilo de revisión de código, y no lo que hace GitHub. Me alegra saber que tiene nombre.
Además, sería bueno que el sistema de revisión pudiera empujar “hacia afuera” de la revisión los parches que ya están listos. Una pequeña corrección de bug hecha mientras trabajas en una funcionalidad grande debería ser un parche pequeño e independiente, y es probable que el revisor la apruebe rápidamente.
Entonces quisiera sacar ese parche de toda la serie, hacerle cherry-pick a main y hacer rebase de la revisión sobre el nuevo HEAD. O también podría hacer rebase de la serie de parches más reciente sobre main, reordenar el parche acordado para ponerlo primero y luego hacer fast-forward de main hasta ese parche.
En esencia, se trata de reducir el alcance de la revisión a “lo que todavía está en discusión”, pero permitir que las correcciones de bugs se fusionen apenas estén listas.
La objeción sería “simplemente haz una revisión/PR aparte”, pero entonces aparece la complejidad de que el patchset A dependa del patchset B y, una vez que B se fusiona, pase a depender de main.
También ayudan ideas inteligentes de UX como el Attention Set. Básicamente indica “¿quién es la persona que debe realizar la siguiente acción?”, y funciona como un juego por turnos. Si acabo de revisar un parche, ya no estoy yo en el attention set de ese parche, sino el autor.
Por eso, en la UI de Gerrit ese elemento baja en mi cola. En la parte superior de la cola están los elementos en los que yo estoy en el attention set. Naturalmente, el trabajo se agrupa de esa manera.
No estoy abordando todos los demás pequeños problemas molestos de la UX de GitHub, pero incluso la lista de pull requests es peor que las alternativas. No puedes saber en qué estado está cada elemento y al final tienes que leerlo todo.
Si es x, el de más abajo, puedes enviarlo directamente y seguir avanzando con el resto.
Siempre es interesante ver nuevos enfoques para la revisión de código. GitHub también tiene sus ventajas, pero está lejos de ser perfecto.
En el escenario planteado, se podría pensar en dividir los tres parches en pull requests separados que dependan entre sí. GitHub no lo soporta de forma nativa, pero una herramienta adecuada de revisión de código debería poder mantener pequeños los pull requests y, a la vez, gestionar sus dependencias. Por ejemplo, se podría hacer que el parche 3 dependa del parche 2, y el parche 2 del parche 1.
Gracias al seguimiento de dependencias que ofrece la herramienta, se puede garantizar que, si hace falta, todos se desplieguen juntos.
Revisar cada parche por separado hace que el feedback sea más claro y más fácil de atender. Dentro del pull request, también se pueden hacer squash de commits para crear un historial de commits limpio que refleje con precisión los cambios individuales. Más aún, con una herramienta adecuada, se podrían resumir con IA los pull requests y las revisiones, simplificando también la redacción de mensajes de commit precisos sin trabajo manual.
Una buena herramienta de revisión de código no debería quedar a merced de operaciones de git como rebase, merge o force push. Sin importar qué operaciones complejas de git ocurran por detrás, el revisor debería ver solo los cambios desde su última revisión. Así puede concentrarse en lo nuevo sin volver a revisar un diff grande, y el historial de revisión se mantiene limpio y separado del historial de commits.
Me da curiosidad si esta forma de dividir los pull requests y rastrear sus dependencias mutuas cubriría las necesidades.
Es, literalmente, el flujo de trabajo para el que git fue diseñado, y es el núcleo de una crítica antigua que se viene planteando desde que GitHub incorporó los pull requests.
Me pregunto por qué esta idea, revisando el calendario, fue despreciada durante más de 15 años como la forma de hacer las cosas de los “dinosaurios de las listas de correo” y recién ahora está llegando a los círculos de cultura de desarrollo de moda.
Durante mucho tiempo pensé que, como muchos desarrolladores de software se negaban a aprender bien una de las herramientas que más usan, estaban eligiendo deliberadamente un flujo de trabajo malo. Por eso, cuando pasé la empresa a git, elegí y construí herramientas y flujos así. En fin, a nadie lo despiden por comprar IBM.
Cuando un colaborador externo usa un fork del repositorio, los tres PR terminan incluyendo progresivamente A, A+B y A+B+C. Entonces, en los últimos dos PR, hay que volver a ver en el diff código que ya se revisó en otro PR, lo que dificulta la revisión.
Cada commit se puede revisar de forma independiente. También se pueden rastrear dependencias entre commits. Que no tenga IA incorporada también es algo bueno. A diferencia de los PR, también se pueden ver interdiffs entre commits.
Los commits son el material básico de Git. Simplemente usen commits.
Me da curiosidad cómo GitContext rastrea commits que pasaron por operaciones como fixup, rebase o reordenamiento.
Soy quien escribió este artículo. Pregúntenme lo que quieran.
Además, no sé si esto va contra las reglas, pero hace poco me quedé necesitando un nuevo trabajo. Me gusta trabajar en herramientas para desarrolladores y problemas difíciles. Si les gustó este artículo, si quieren aumentar la productividad de su equipo de desarrollo, o si quieren experimentar y disfrutar de mi excelente y a veces ecléctico gusto, mi email está en el perfil.
Hablando en serio, tu currículum es impresionante. Espero que encuentres algo bueno, y rápido. Según mi experiencia muy reciente buscando trabajo, el mercado laboral actual está gravemente enfermo. Mientras más senior y experimentado eres, más te lastiman el alma las prácticas absurdas de entrevistas y RR. HH., y los rechazos inexplicables.
Un amigo me mandó estos enlaces:
https://danluu.com/hiring-lemons/
https://danluu.com/programmer-moneyball/
https://danluu.com/algorithms-interviews/
Mucha suerte.
Algo que todavía no se trató es que, por culpa de la diff soup, la gente puede terminar prefiriendo una estrategia de squash merge para eliminar el “ruido” de los commits fixup. Pero así también tiran a la basura los tres buenos commits atómicos iniciales.
En el estilo de revisión con interdiff, los primeros tres commits permanecen, y la decisión de incorporarlos por separado o hacer squash depende exclusivamente de esos commits en sí y de su atomicidad real.
También hay servicios externos que intentan reducir el dolor de GitHub y ofrecen soporte para stacked diffs, pero parecen bastante caros. Sobre todo si se comparan con Gerrit self-hosted. Me da curiosidad si también revisaste esas herramientas.
Recuerdo que antes se podía armar con bastante facilidad un patrón de serie de MR. Al mergear 3 MR, quedaban 3 merge commits, cada uno con un único commit squash por MR. Eso era independiente del historial de commits del MR.
El trade-off es que, si durante la revisión cambia una rama anterior de la serie, hay que volver a hacer merge en las ramas posteriores de la serie.
Aun así, durante la revisión, la gente puede manejar el historial de commits como quiera. Total, se va a hacer squash de todos modos.
Eso sí, hace mucho que no lo hago y, como últimamente vivo atado a GitHub, quizá lo esté recordando con lentes color de rosa.
Review Board [https://www.reviewboard.org] ya había creado interdiff en 2006. De hecho, puede que yo haya acuñado el término o llegado a él de forma independiente.
Incluso hoy es una de mis partes favoritas del producto y del proceso de revisión de código, y una de las funciones que más escucho que la gente extraña cuando se pasa a algo como GitHub.
Nunca sentí que los commits fix-it fueran una alternativa adecuada.
Primero, no te dicen cómo se reflejó el cambio superior en la serie de commits.
Segundo, aunque sea temporalmente, desordenan el grafo de commits y dificultan la revisión. Quien venía siguiendo la revisión quizá ya leyó el código que corrige el commit fix-it, pero alguien que llega de nuevo puede empezar con una mala primera impresión de qué intenta hacer ese código o de cuál es su estructura.
Tercero, no todos usan Git ni un sistema de control de versiones que pueda manejar múltiples commits. En desarrollo de videojuegos se suele usar Perforce, y en fabricantes de chips a menudo se usan sistemas de control de versiones especializados como Keysight SOS. En esos lugares, los commits fix-it ni siquiera son una opción.
Con un sistema de revisión de código con buen soporte de interdiff, un revisor puede seguir todas las actualizaciones desde la solicitud de revisión publicada inicialmente y ver solo lo que cambió, mientras que otro revisor puede entrar directamente al cambio completo más reciente sin preocuparse por una serie de fix-it. Y esto es posible independientemente del sistema de control de versiones.
Si se implementa bien, también puede coexistir con cambios compuestos por varios commits.
Por ejemplo, para ayudar a la revisión, podrías dividir un proyecto pequeño en varios commits para el handler de API, la UI de frontend y la documentación, y decidir que, como los commits están estrechamente relacionados, corresponde subirlos como una sola solicitud de revisión. Si estuvieran poco relacionados entre sí, lo ideal sería crear varias solicitudes de revisión como una cadena de dependencias.
Según el feedback de la revisión, puedes hacer una serie de cambios en uno o en todos esos commits. Cuando la gente revise la actualización, sería bueno que pudiera ver cómo evolucionó cada parte, sin tener que mapear mentalmente los commits fix-it y sus cambios contra los cambios originales correspondientes.
Por eso interdiff es realmente excelente. Ya sea que haya muchos commits pequeños o un commit grande, una solicitud de revisión de un solo commit o de múltiples commits, más gente debería usarlo.
Alrededor de 2013, Glasgow Haskell Compiler pasó de lo que en broma llamábamos “leer archivos .patch en el reportador de bugs” a usar Phabricator. Había varias razones, pero en ese momento no era por stacked diff. Era porque GitHub era tan malo para las revisiones que ni siquiera tenía side-by-side diff. Solo por eso quedaba completamente descartado, y también había otros motivos.
Pero esa no fue la primera vez que moví a un equipo a una herramienta de revisión de código. En mi primer trabajo, en 2009, éramos un equipo de ingeniería muy pequeño y unido, todos en una sala en Houston, y pensé que si otras personas revisaban mi código y yo leía lo que ellas escribían, podría entender mejor la base de código.
Así que durante mis primeros meses después de entrar insistí a mi manager hasta que instaló ReviewBoard, y a todos les encantó.
Así que esto es para decir gracias a RB. Todavía lo recuerdo con cariño de vez en cuando. Gracias a eso, la revisión de código fue una parte muy importante de mi carrera casi desde el primer día, y aún creo que podría hacer más.
En general, sentí que los sistemas como Gerrit, con la revisión de código como prioridad y centrados en rebase, hacen que el código sea mucho más fácil de revisar.
Una de sus mejores cosas es que soportan de forma nativa apilar varios parches, lo que hace que la gente cree parches más pequeños y más fáciles de revisar.
La revisión de código de GitHub se siente como una mala función agregada a posteriori: una UI que desperdicia espacio y parece un hilo de foro, que no puede seguir los cambios más allá de un rebase, etc.
Con demasiada frecuencia, estas discusiones técnicas pero de “panorama general” ocurren en el issue tracker. Pero tampoco sé bien dónde deberían ir. Esta pila es demasiado efímera y puede cambiar por completo en el siguiente push.
Escuché varias veces a gente defender esta estrategia, pero no me convence. En la mayoría de los proyectos en los que trabajo, la feature branch se integra haciendo squash en un solo commit y se elimina el historial de la rama
Si se diera el caso que describe el autor, simplemente haría el refactor, la nueva API y la actualización como 3 commits
Lo que para mí sí ha sido claramente una buena práctica es evitar las ramas de larga vida. Estos escenarios de commits en varias etapas suelen surgir de ahí. Es la situación en la que alguien trabaja en una funcionalidad durante días, o incluso semanas, y luego quiere tirarla toda de una vez
Prefiero mucho más mover cambios a main todos los días, o incluso varias veces al día. Una forma de lograrlo es usar feature flags para que los commits en curso también puedan incorporarse sin problemas. Si el sistema está bien configurado, eso además tiene la ventaja de poder activarlos y probarlos en entornos de desarrollo y staging. También queda a un paso de un despliegue blue/green
No quiero una forma de revisar commits grandes con más facilidad. Quiero obligar al equipo a commitear cambios pequeños, temprano y con frecuencia. Entiendo que no todos están de acuerdo
Una de las razones es que, a diferencia de los PR de GitHub, se puede incorporar solo una parte de la pila. En el ejemplo del artículo, si el diff de “pequeño refactor” está listo, se puede meter primero sin incorporar también los diffs de “nueva API” y “migración de usuarios de la API”
Si se trabaja de forma centrada en commits y no en ramas, el efecto es que los commits totales sean más pequeños que con ramas de larga vida
Eso vuelve
git blameygit bisectprácticamente inútilesSi hay una regresión,
git bisectpuede acotarla hasta un parche individual. Por eso es mejor tener en el historial de git 50 parches de 160 líneas que un único parche de 8000 líneas para una funcionalidad determinadaSi una línea de código parece sospechosa, quiero que
git blame, o una secuencia de comandosgit blame, me lleve a un commit de 160 líneas con un mensaje detallado, no a un commit de 8000 líneasTambién hay que preservar el orden de los commits originales. Años después, leer los mensajes de commits individuales en orden puede ayudar muchísimo a entender el diseño original. Por supuesto, el patchset original debe estar organizado en orden de dependencias, compilar en cada etapa, etc., lo que requiere una etapa de desarrollo separada además de implementar la funcionalidad. El código debe presentarse en pasos lógicos
Interesante. En el trabajo usamos los PR como el autor usa los commits, y al final efectivamente hacemos squash-and-merge
Pero con este enfoque, cada vez que se cambia un PR anterior, hay que hacer rebase de los PR posteriores. Es bastante engorroso, choca con la regla de “no hacer force-push”, a los ingenieros les toma tiempo aprenderlo y tiende a romper los comentarios existentes de revisión de código en la UI de GitHub. Aun así, con dos o tres PR funciona más o menos
En nuestro flujo, los commits son más bien puntos de guardado que unidades de trabajo
También usamos mucho stash y mucho undo-tree-mode de Emacs. Entonces terminamos teniendo cuatro formas de rastrear el historial del código fuente; suena redundante, pero en la práctica funciona bastante bien
La usabilidad de Git para manejar esto es bastante mala. Phabricator era mejor, pero aun así era innecesariamente difícil. Tal vez una nueva herramienta de control de versiones podría dar soporte de primera clase a conceptos de más alto nivel que commits y ramas, o tal vez eso la haría aún peor de usar
¿Sería bueno tener una herramienta mejor que Git? Claro, yo también quiero una herramienta con menos defectos y más amigable para el usuario. Pero como solución temporal, ¿qué tal tratar los commits como commits? No te compliques la vida innecesariamente
Me pregunto cuánta responsabilidad tiene GitHub por haber hecho que la gente mire todo con lentes de PR
jj,saplingymercurialMe gustó el post del blog, y me alegra ver gente que realmente piensa en cómo debería funcionar la revisión de código
He usado bastante cuatro sistemas de revisión de código, cada uno con distintas ventajas y desventajas: Critique (interno de Google), Gerrit (lo usé en Google, pero era igual al externo), GitHub y CodeApprove, que hice yo
Critique era por lejos el mejor, pero eso era posible porque estaba perfectamente adaptado al monorepo de Google, a su propio sistema de control de versiones y a sus herramientas personalizadas de lint/test. CodeApprove fue diseñado para llevar la mayor cantidad posible de esas ventajas a GitHub, pero en la práctica es difícil acercarse a eso
Gerrit era el segundo mejor en cuanto a experiencia para el revisor, pero como autor siempre me desagradó. Parecía haber más formas de hacerlo mal que de hacerlo bien, y la UI tampoco es precisamente bonita
GitHub es muy amigable para el autor y funciona de la forma en que solemos pensar: escribes código, recibes feedback y escribes más código. Si al final del PR haces squash and merge, no aparece el problema de historial que menciona el autor
Pero no es muy amigable para los revisores ni para el equipo. No se resaltan los diffs incrementales, el diff y la conversación están en pestañas separadas, y los force push y rebase destruyen el historial. Los comentarios desaparecen como “outdated”, no se pueden comentar archivos fuera de la ventana del diff, los archivos grandes se ocultan por defecto, y hay muchos otros problemas. Es evidente que a GitHub no le importa mucho esto, y quizá sepan algo que yo no
Al final, lo más frustrante es que muchos equipos simplemente aceptan la herramienta de revisión de código integrada en su plataforma de control de versiones. Es como usar el IDE que viene preinstalado en la laptop. Hoy hay muchas opciones mucho mejores. Además de CodeApprove, me gustan GitContext, Reviewable y Graphite, y podría nombrar al menos media docena más de buenas opciones. No hay que aceptar el valor por defecto
Los revisores y mantenedores son mucho más escasos que los contribuidores. Creo que el flujo de trabajo y la UI deberían optimizar el rendimiento de revisión
No he usado las otras tres herramientas mencionadas, así que mi argumento es general