.. include:: ../disclaimer-sp.rst

:Original: Documentation/process/7.AdvancedTopics.rst
:Translator: Carlos Bilbao <carlos.bilbao.osdev@gmail.com> and Avadhut Naik <avadhut.naik@amd.com>

.. _sp_development_advancedtopics:

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.

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:

	https://git-scm.com/

	https://www.kernel.org/pub/software/scm/git/docs/user-manual.html

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.

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!