Warning

Si tiene alguna duda sobre la exactitud del contenido de esta traducción, la única referencia válida es la documentación oficial en inglés. Además, por defecto, los enlaces a documentos redirigen a la documentación en inglés, incluso si existe una versión traducida. Consulte el índice para más información.

Original:

Documentation/process/7.AdvancedTopics.rst

Translator:

Carlos Bilbao <carlos.bilbao.osdev@gmail.com> and Avadhut Naik <avadhut.naik@amd.com>

7. Temas avanzados

Llegados a este punto, con suerte, tiene una idea de cómo funciona el proceso de desarrollo. Sin embargo, ¡todavía hay más que aprender! Esta sección cubrirá varios temas que pueden ser útiles para los desarrolladores que desean convertirse en una parte regular del proceso de desarrollo del kernel Linux.

7.1. Gestionar parches con git

El uso del control de versiones distribuido para el kernel comenzó a principios de 2002 cuando Linus comenzó a jugar con la aplicación propietaria BitKeeper. Aunque BitKeeper fue controvertido, el enfoque de la gestión de versiones de software que incorporó ciertamente no lo fue. El control de versiones distribuido permitió una aceleración inmediata del proyecto de desarrollo del kernel. En los tiempos actuales, existen varias alternativas gratuitas a BitKeeper. Para bien o para mal, el proyecto del kernel ha optado por git como su herramienta preferida.

Administrar parches con git puede hacer la vida mucho más fácil para el desarrollador, especialmente a medida que crece el volumen de esos parches. Git también tiene sus asperezas y representa ciertos peligros; es una herramienta joven y poderosa que aún está siendo civilizada por sus desarrolladores. Este documento no intentará enseñar al lector cómo usar git; eso sería material suficiente para un documento extenso por derecho propio. En su lugar, el enfoque aquí será cómo git encaja en el proceso de desarrollo del kernel en particular. Los desarrolladores que deseen ponerse al día con git encontrarán más información en:

y en varios tutoriales que se encuentran en la web.

El primer orden del negocio es leer los sitios mencionados anteriormente y comprender cómo funciona git antes de intentar usarlo para poner parches a disposición de otros. Un desarrollador que usa git debe ser capaz de obtener una copia del repositorio mainline, explorar el historial de revisiones, hacer commits en el árbol, usar ramas, etcétera. También es útil entender las herramientas de git para rescribir la historia (como rebase). Git viene con su propia terminología y conceptos; un nuevo usuario de git debe conocer las referencias, las ramas remotas, el índice, las fusiones fast-forward, los pushes y pulls, las cabezas separadas, etcétera. Todo puede ser un poco intimidante al principio, pero los conceptos no son tan difíciles de entender con un poco de estudio.

Usar git para generar parches para enviarlos por correo electrónico puede ser un buen ejercicio mientras te pones al día.

Cuando esté listo para comenzar a publicar árboles de git para que otros los vean, necesitará por supuesto, un servidor del que se pueda extraer. Configurar un servidor de este tipo con git-daemon es relativamente sencillo si tiene un sistema accesible a Internet. De lo contrario, los sitios de alojamiento público y gratuitos (GitHub, por ejemplo) están comenzando a aparecer en la red. Los desarrolladores establecidos pueden obtener una cuenta en kernel.org, pero no son fáciles de conseguir; ver https://kernel.org/faq/ para más información.

El flujo de trabajo normal de git implica el uso de muchas ramas. Cada línea de desarrollo puede separarse en una “rama temática” separada y mantenerse de forma independiente. Las ramas en git son baratas, no hay razón para no hacer uso gratuito de ellas. Y, en cualquier caso, no debe desarrollarse en ninguna rama de la que tenga la intención de pedir a otros que hagan un pull. Las ramas disponibles públicamente deben crearse con cuidado; fusione los parches de las ramas de desarrollo cuando estén en forma completa y listos para usar – no antes.

Git proporciona herramientas poderosas que permiten reescribir su historia de desarrollo. Un parche inconveniente (uno que rompe la bisección, por ejemplo, o que tiene algún otro tipo de error obvio) se puede corregir en su lugar o hacer que desaparezca de la historia por completo. Una serie de parches se puede reescribir como si se hubiera escrito sobre el mainline de hoy, aunque haya estado trabajando en ella durante meses. Los cambios se pueden transferir de manera transparente de una rama a otra. Y así sucesivamente. El uso juicioso de la capacidad de git para revisar el historial puede ayudar en la creación de conjuntos de parches limpios con menos problemas.

El uso excesivo de esta capacidad puede llevar a otros problemas más allá de una simple obsesión por crear la historia perfecta del proyecto. Reescribir la historia rescribirá los cambios contenidos en esa historia, convirtiendo un árbol del kernel probado (con suerte) en uno no probado. Pero más allá de eso, los desarrolladores no pueden colaborar fácilmente si no tienen una vista compartida del historial del proyecto; si reescribe la historia que otros desarrolladores han introducido en sus repositorios, les hará la vida mucho más difícil a esos desarrolladores. Por lo tanto, aquí se aplica una regla simple general: la historia que se ha exportado a otros generalmente debe considerarse inmutable a partir de entonces.

Por lo tanto, una vez que envié un conjunto de cambios a su servidor disponible públicamente, esos cambios no deben reescribirse. Git intentará hacer cumplir esta regla si intenta enviar cambios que no resulten en un “fast-forward merge” (es decir, cambios que no comparten el mismo historial). Es posible anular esta comprobación, y puede haber ocasiones en las que sea necesario reescribir un árbol exportado. Mover conjuntos de cambios entre árboles para evitar conflictos en linux-next es un ejemplo. Pero tales acciones deberían ser raras. Esta es una de las razones por las que el desarrollo debe hacerse en ramas privadas (que se pueden reescribir si es necesario) y solo trasladarse a ramas públicas cuando esté en un estado razonablemente avanzado.

A medida que el mainline (u otro árbol en el que se basa un conjunto de cambios) avanza, es tentador fusionarse con ese árbol para permanecer a la vanguardia. Para una rama privada, la rebase puede ser una manera fácil de mantenerse al día con otro árbol, pero la rebase no es una opción una vez que el árbol se exporta al mundo. Una vez que eso sucede, se debe realizar una fusión completa. Fusionar ocasionalmente tiene sentido, pero las fusiones demasiado frecuentes pueden desordenar el historial innecesariamente. La técnica sugerida en este caso es fusionar con poca frecuencia y, por lo general, solo en puntos de lanzamiento específicos (como una versión -rc del mainline). Si está nervioso por cambios específicos, siempre puede realizar fusiones de prueba en una rama privada. La herramienta git “rerere” puede ser útil en tales situaciones; recuerda cómo se resolvieron los conflictos de fusión para que no tenga que hacer el mismo trabajo dos veces.

Una de las mayores quejas recurrentes sobre herramientas como git es la siguiente: el movimiento masivo de parches de un repositorio a otro hace que sea fácil deslizar cambios más aconsejados que pasan al mainline debajo del radar de revisión. Los desarrolladores del kernel tienden a descontentarse cuando ven que suceden ese tipo de cosas; poner un árbol de git con parches no revisados o fuera de tema puede afectar su capacidad para hacer que los árboles sean integrados en el futuro. Citando a Linus:

Puede enviarme parches, pero para que yo acepte un parche de git de
su parte, necesito saber que usted sabe lo que está haciendo, y
necesito poder confiar en las cosas *sin* tener que revisar
manualmente cada cambio individual.

(https://lwn.net/Articles/224135/).

Para evitar este tipo de situación, asegúrese de que todos los parches dentro de una rama determinada se adhieran estrictamente al tema asociado; una rama de “correcciones de drivers” no debería hacer cambios en el código central de gestión de memoria. Y, lo más importante, no utilice un árbol git para eludir el proceso de revisión. Publique un resumen ocasional del árbol en la lista relevante y, cuando sea el momento adecuado, solicite que el árbol se incluya en linux-next.

Si y cuando otros comiencen a enviar parches para su inclusión en su árbol, no olvide revisarlos. Además, asegúrese de mantener la información de autoría correcta; la herramienta git “am” hace lo mejor que puede es este sentido, pero es posible que tenga que agregar una línea “From:” al parche si ha sido reenviado a través de un tercero.

Al solicitar un pull, proporcione toda la información relevante: dónde está su árbol, qué rama se debe pull, y que cambios resultarán del pull. El comando git request-pull puede ser útil en este sentido; formateará la solicitud como otros desarrolladores esperan, y también comprobará para asegurarse de que ha recordado enviar esos cambios al servidor público.

7.2. Revisión de parches

Algunos lectores seguramente se opondrán a incluir esta sección con “temas avanzados” porque incluso los desarrolladores principiantes del kernel deberían revisar los parches. Es cierto que no hay mejor manera de aprender a programar en el entorno del kernel que mirando el código publicado por otros. Además, los revisores siempre escasean; al revisar código, puede contribuir significativamente al proceso en su conjunto.

Revisar el código puede ser una perspectiva intimidante, especialmente para un nuevo desarrollador de kernel que puede sentirse nervioso al cuestionar el código – en público – publicado por aquellos con más experiencia. Sin embargo, incluso el código escrito por los desarrolladores más experimentados se puede mejorar. Quizás el mejor consejo para los revisores (todos los revisores) es este: expresar los comentarios de revisión como preguntas en lugar de críticas. Preguntar “¿cómo se libera el bloqueo en este camino?” siempre funcionará mejor que decir “el bloqueo aquí es incorrecto”.

Otra técnica que es útil en caso de desacuerdo es pedir a otros que intervengan. Si una discusión llega a un punto muerto después de algunos intercambios, solicite las opiniones de otros revisores o maintainers. A menudo, aquellos que están de acuerdo con un revisor permanecen en silencio a menos que se les invite a participar. La opinión de varias personas tiene exponencialmente más peso.

Diferentes desarrolladores revisarán el código desde diferentes puntos de vista. Algunos se preocupan principalmente por el estilo de codificación y si las líneas de código tienen espacios en blanco al final. Otros se enfocarán principalmente en si el cambio implementado por el parche en su totalidad es beneficioso para el kernel o no. Sin embargo, otros comprobarán si hay bloqueos problemáticos, uso excesivo de la pila, posibles problemas de seguridad, duplicación de código encontrado en otras partes, documentación adecuada, efectos adversos en el rendimiento, cambios en la ABI del espacio de usuario, etcétera. Todos los tipos de revisión, si conducen a un mejor código en el kernel, son bienvenidos y valen la pena.

No hay ningún requisito estricto para usar etiquetas específicas como Reviewed-by. De hecho, las revisiones en Inglés sencillo son más informativas y alentadas incluso cuando se proporciona una etiqueta, por ejemplo, “Revisé los aspectos A, B y C de esta propuesta y me parece bien”. ¡Alguna forma de mensaje de revisión o respuesta es obviamente necesaria, de lo contrario, los maintainers no sabrán que el revisor ha revisado el parche en absoluto!

Por último, pero no menos importante, la revisión de parches puede convertirse en un proceso negativo, centrado en señalar problemas. ¡Por favor, dé un cumplido de vez en cuando, especialmente a los principiantes!