Cómo hacer la vida más fácil al usar Git (así como una selección de materiales para inmersión profunda)


Tree of Dragons II por surrealistguitarist

Para aquellos que usan Git todos los días pero se sienten inseguros, el equipoMail.ru Cloud Solutions ha traducido un artículo del desarrollador front-end Shane Hudson . Aquí encontrará algunos trucos y consejos que pueden facilitarle un poco el trabajo con Git, así como una selección de artículos y manuales de un nivel más avanzado.

Git apareció hace casi 15 años. Durante este tiempo, pasó de ser un desvalido a un campeón invencible. Hoy, los nuevos proyectos a menudo comienzan con un equipo git init. Sin lugar a dudas, esta es una herramienta importante que muchos de nosotros usamos a diario, pero a menudo se parece a la magia: brillante, pero peligrosa.

Se han publicado muchos artículos sobre Habr, cómo comenzar a usar Git, cómo funciona Git bajo el capó y descripciones de las mejores estrategias de ramificación. Aquí, el autor se centró en cómo simplificar el trabajo con Git.

Ponemos las cosas en orden


El punto de Git es guardar su trabajo, cambiar de contexto y hacer otra cosa. Esto puede ser una copia de seguridad del código o la capacidad de desarrollar asincrónicamente varias funciones diferentes. Sería terrible tirar la segunda versión solo porque se encontró un error en la primera. No es menos vergonzoso guardar archivos con nombres como v1_final_bug_fixed. Como sabes, esto lleva a un completo desastre.

Todos sabemos que la vida se vuelve mucho más fácil cuando nuestras actualizaciones se distribuyen cuidadosamente en las sucursales de Git que puedes compartir con tus colegas. Pero a menudo surgen situaciones cuando cambia el contexto, luego regresa y no puede encontrar la rama correcta. ¿Hubo un compromiso en absoluto? ¿Quizás está escondido? Tal vez el compromiso no pasó, ahora todos se han ido a la rama equivocada, y todo está mal, ¡y estoy haciendo un trabajo terriblemente malo! Sí, todos estaban allí y sentían tales dudas. Hay formas de lidiar con esta situación.

Ordenar ramas por fecha


Ordenar por fecha muestra todas sus sucursales locales, comenzando por la última. Bastante común, pero me ayudó muchas veces:

# To sort branches by commit date
git branch --sort=-committerdate

Hilo anterior


¿Qué sucede si no se comprometió, cambió la rama y luego desea volver a la anterior? Probablemente pueda encontrarlo en la lista de ramas si tiene alguna idea de su nombre. Pero, ¿qué pasa si no es una rama, sino una detached HEADconfirmación específica?

Resulta que hay una salida simple:

# Checkout previous branch
git checkout -

El operador -es una forma abreviada de sintaxis @{-1}que le permite cambiar a cualquier cantidad de pagos. Entonces, si, por ejemplo, creó una rama feature/thing-a, entonces feature/thing-b, y luego bugfix/thing-c, el parámetro @{-2}lo devolverá a feature/thing-a:

# Checkout branch N number of checkouts ago
git checkout @{-N}

Mostrar información sobre todas las sucursales


La bandera vmuestra una lista de todas las ramas con el último identificador de confirmación y mensaje. El doble vvtambién mostrará las ramas ascendentes remotas, seguidas de las ramas locales:

# List branches along with commit ID, commit message and remote
git branch -vv

Encontrar archivo


Todos caímos en esta situación: de alguna manera resultó que un archivo quedó en la rama incorrecta. ¿Qué hacer? ¿Rehacer todo el trabajo o copiar el código de una rama a otra? No, afortunadamente, hay una manera de encontrar un archivo específico.

El método es un poco extraño, dado que git checkout -te lleva a la rama anterior. En general, si especifica --después del nombre de la sucursal al finalizar la compra, esto le permitirá especificar el archivo específico que está buscando. No adivinará dicha función sin una pista, pero es muy conveniente si sabe:

git checkout feature/my-other-branch -- thefile.txt

Estado claro


Tomasz Lacoma tuiteó sobre la reducción de la emisión git statuscon la ayuda de banderas -sby agregó: "Durante muchos años he estado usando Git, pero nadie me ha contado sobre esto". No se trata solo de encontrar archivos perdidos. Hay momentos en que simplificar el problema hace que sea más fácil ver los cambios.

La mayoría de los comandos de Git tienen estos indicadores, por lo que debe aprender a usarlos para personalizar su flujo de trabajo:

# Usually we would use git status to check what files have changed
git status

# Outputs:
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified: README.md

Untracked files:
(use "git add <file>..." to include in what will be committed)

another-file
my-new-file

# Using the flags -sb we can shorten the output
git status -sb

# Outputs:
## master
M README.md
?? another-file
?? my-new-file

Toda la historia


Hay momentos en que algo salió completamente mal, por ejemplo, descartó accidentalmente los cambios por etapas (preparatorios) antes de cometerlos. Si git logno le permite volver al estado anterior y ninguno de los consejos anteriores ayuda, eso es git reflog.

Todas sus acciones en Git que cambian los contenidos por referencia HEAD@{}(por ejemplo push/pull/branch/checkout/commit) caen en el registro de referencia (registro de referencia). De hecho, esta es la historia de todas sus acciones, sin importar en qué rama se encuentre. Esta es la diferencia con git log, que muestra los cambios para una rama en particular.


Puede hacerlo git showcon la ID de confirmación y ver el cambio específico. Si esto es lo que estaba buscando, lo git checkouttransferirá a la rama deseada o incluso le permitirá seleccionar un archivo específico, como se muestra arriba:

# See the reference log of your activity
git reflog --all

# Look at the HEAD at given point from reflog
git show HEAD@{2}

# Checkout the HEAD, to get back to that point
git checkout HEAD@{2}

Archivos de preparación que omitieron la confirmación


En casos extremos, si git reflogno ayuda recuperar sus archivos (por ejemplo, ejecutó un restablecimiento completo con archivos intermedios), hay un truco más.

Cada cambio se almacena dentro de objetos .git/objectsque están llenos de archivos en el proyecto activo, por lo que es casi imposible resolverlo. Sin embargo, hay un comando Git llamado git fsck, que se utiliza para verificar la integridad (presencia de archivos dañados) en el repositorio. Podemos usarlo con una bandera --lost-foundpara buscar todos los archivos no relacionados con una confirmación. Dichos archivos se denominan "blob colgante".

Este comando también le permite encontrar "árboles colgantes" y "confirmaciones colgantes". Si lo desea, puede usar la bandera --dangling, pero la ventaja--lost-foundya que extrae todos los archivos relevantes en una carpeta .git/lost-found. Lo más probable es que en un proyecto activo tenga muchos de esos archivos "colgantes". Git tiene un comando de eliminación de basura que se ejecuta regularmente y los elimina.

Por lo tanto, --lost-foundmostrará todos los archivos y la hora / fecha de creación, lo que facilita enormemente la búsqueda. Tenga en cuenta que cada archivo por separado seguirá estando separado, es decir, no puede usar el pago. Además, todos los archivos tendrán nombres incomprensibles (hash), por lo que debe copiar los archivos necesarios en otra ubicación:

# This will find any change that was staged but is not attached to the git tree
git fsck --lost-found

# See the dates of the files
ls -lah .git/lost-found/other/

# Copy the relevant files to where you want them, for example:
cp .git/lost-found/other/73f60804ac20d5e417783a324517eba600976d30 index.html

Git en trabajo en equipo


Usar Git solo es una cosa, pero cuando trabajas en un equipo de personas, generalmente con experiencias, habilidades y herramientas completamente diferentes, Git puede ser una bendición o una maldición. Esta es una herramienta poderosa para compartir la misma base de código, realizar una revisión de código y monitorear el progreso de todo el equipo. Al mismo tiempo, todos los empleados deben tener una comprensión común de cómo usarlo en el trabajo en equipo. Independientemente de lo que se trate: la convención de nombrar las sucursales, formatear el mensaje adjunto en el compromiso o elegir qué archivos incluir en el compromiso, es importante garantizar una buena comunicación y acordar cómo usar esta herramienta.

Siempre es importante garantizar la simplicidad de la incorporación para principiantes y pensar en lo que sucederá si comienzan a comprometerse sin conocer los principios y convenciones adoptados por la empresa. Este no es el fin del mundo, pero puede causar cierta confusión y tomar tiempo para volver a un enfoque coordinado.

Esta sección contiene algunas recomendaciones sobre cómo integrar los acuerdos aceptados directamente en el repositorio, automatizar y emitir el número máximo de tareas en las declaraciones. En el caso ideal, cualquier empleado nuevo casi inmediatamente comienza a trabajar en el mismo estilo que el resto del equipo.

Las mismas terminaciones de línea


De manera predeterminada, Windows usa terminaciones de línea de DOS \r\n(CRLF), mientras que Mac y Linux usan terminaciones de línea UNIX \n(LF), mientras que las versiones anteriores de Mac usan \r(CR). Por lo tanto, a medida que el equipo crece, el problema de las terminaciones de línea incompatibles se vuelve más probable. Esto es inconveniente, ellos (generalmente) no rompen el código, pero debido a ellos, las solicitudes de confirmación y agrupación muestran varios cambios irrelevantes. A menudo, las personas simplemente los ignoran, porque es bastante problemático caminar y cambiar todas las terminaciones de línea incorrectas.

Existe una solución: puede solicitar a todos los miembros del equipo que configuren sus configuraciones locales para completar la línea automáticamente:

# This will let you configure line-endings on an individual basis
git config core.eol lf
git config core.autocrlf input

Por supuesto, debe inscribirse en esta convención y un principiante, lo cual es fácil de olvidar. ¿Cómo hacer esto para todo el equipo? De acuerdo con el algoritmo de trabajo, Git verifica la presencia de un archivo de configuración en el repositorio .git / config, luego verifica la configuración del usuario en todo el sistema ~/.gitconfigy luego verifica la configuración global /etc/gitconfig.

Todo esto es bueno, pero resulta que ninguno de estos archivos de configuración se puede instalar a través del repositorio. Puede agregar configuraciones específicas del repositorio, pero no se extenderán a otros miembros del equipo.

Sin embargo, hay un archivo que está realmente comprometido con el repositorio. Se llama .gitattributes . De forma predeterminada, no lo tiene, así que cree un nuevo archivo y guárdelo como*.gitattributes*. Establece atributos para cada archivo. Por ejemplo, puede forzar a git diff a usar encabezados exif de archivos de imagen en lugar de tratar de calcular la diferencia en archivos binarios. En este caso, podemos usar un comodín para que la configuración funcione para todos los archivos, actuando, de hecho, como un archivo de configuración común para todo el comando:

# Adding this to your .gitattributes file will make it so all files
# are checked in using UNIX line endings while letting anyone on the team
# edit files using their local operating system’s default line endings.
* text=auto

Auto-escondite


Es habitual agregar archivos compilados (como node_modules/) a .gitignore para que se almacenen localmente y no se carguen en el repositorio. Sin embargo, a veces todavía desea cargar el archivo, pero no desea verlo más tarde cada vez en la solicitud del grupo.

En esta situación (al menos en GitHub), puede agregar rutas marcadas a .gitattributes linguist-generatedy asegurarse de que .gitattributes esté en la carpeta raíz del repositorio. Esto ocultará los archivos en la solicitud del grupo. Se "minimizarán": aún puede ver el hecho del cambio, pero sin el código completo.

Todo lo que reduce el estrés y la carga cognitiva en el proceso de revisión del código mejora su calidad y reduce el tiempo.

Por ejemplo, desea agregar archivos de recursos (activo) al repositorio, pero no los va a modificar y rastrear más adelante, por lo que puede agregar la siguiente línea al archivo con atributos:

*.asset linguist-generated

Usa la culpa git más a menudo


El artículo de Harry Roberts "Pequeñas cosas que me gusta hacer con Git" recomienda git blame(asignar git praisetraducción ) asignar un alias (traducción de la traducción "inglés") para sentir a este equipo como una acción positiva. Por supuesto, el cambio de nombre no cambia el comportamiento del equipo. Pero cada vez que surge la discusión sobre el uso de una función git blame, todos se ponen tensos y, por supuesto, yo también. Es natural percibir la palabra culpa (culpa) como algo negativo ... ¡pero esto está completamente mal!

Una función potente git blame (o git praise, si lo desea) muestra quién fue el último en trabajar con este código. No vamos a culparlo o alabarlo, solo queremos aclarar la situación. Se hace más claro qué preguntas hacer y a quién, lo que ahorra tiempo.

Debe presentarse git blameno solo como algo bueno, sino también como un medio de comunicación que ayuda a todo el equipo a reducir el caos y no perder el tiempo averiguando quién sabe qué. Algunos IDE, como Visual Studio, activan esta función como anotaciones. Para cada función, verá instantáneamente quién la cambió por última vez (y, por lo tanto, con quién hablar sobre ella).

Culpa de git analógico por archivos faltantes


Recientemente, vi a un desarrollador de nuestro equipo tratando de averiguar quién eliminó un archivo, cuándo y por qué. Parece que puede ayudar aquí git blame, pero funciona con las líneas en el archivo y es inútil si falta el archivo.

Sin embargo, hay otra solución. Viejos fieles git log. Si mira el registro sin argumentos, verá una larga lista de todos los cambios en la rama actual. Puede agregar un identificador de confirmación para ver el registro de esta confirmación en particular, pero si especifica --(que usamos anteriormente para apuntar a un archivo específico), puede obtener un registro para un archivo, incluso uno que ya no existe:

# By using -- for a specific file,
# git log can find logs for files that were deleted in past commits
git log -- missing_file.txt

Plantilla de mensaje de confirmación


Los mensajes de compromiso a menudo necesitan mejorarse. Tarde o temprano, los desarrolladores del equipo llegan a esta conclusión. Hay muchas formas de mejorar. Por ejemplo, puede hacer referencia a identificadores de errores desde una herramienta interna de gestión de proyectos, o tal vez alentar a escribir al menos algo de texto en lugar de un mensaje en blanco.

Este comando debe ejecutarse manualmente cada vez que alguien clona el repositorio, ya que los archivos de configuración no están comprometidos con el repositorio. Sin embargo, es conveniente porque puede crear un archivo común con cualquier nombre que actúe como una plantilla de mensaje de confirmación:

# This sets the commit template to the file given,
# this needs to be run for each contributor to the repository.
git config commit.template ./template-file

Git para automatización


Git es una poderosa herramienta de automatización. Esto no es inmediatamente obvio, pero piense por sí mismo: ve toda su actividad en el repositorio, más la actividad de otros participantes, y tiene mucha información que puede ser muy útil.

Ganchos Git


Muy a menudo, ves que los miembros del equipo realizan tareas repetitivas mientras trabajan. Esto puede ser una prueba de pasar pruebas y linter antes de enviar una rama al servidor (enganchar antes de enviar) o una estrategia forzada para nombrar ramas (enganchar antes de comprometerse). Sobre este tema, Konstantinos Lamonis escribió un artículo en la revista Smashing titulado "Cómo simplificar el flujo de trabajo usando ganchos Git" .

Automatización manual


Una de las características clave de automatización en Git es git bisect. Muchos han oído hablar de él, pero pocos lo usan. La conclusión es procesar el árbol Git (historial de confirmación) y encontrar dónde se ingresa el error.

La forma más fácil de hacer esto es a mano. Usted comienza git bisect start, establece los identificadores de las confirmaciones buenas y malas (donde no hay error y donde hay un error), luego ejecuta git bisect goodo git bisect badpara cada confirmación.

Esta es una característica más poderosa de lo que parece a primera vista, porque no ejecuta el registro Git linealmente, lo que podría hacerse manualmente como un proceso iterativo. En cambio, utiliza una búsqueda binaria que efectivamente pasa a través de confirmaciones con el menor número de pasos:

# Begin the bisect
git bisect start

# Tell git which commit does not have the bug
git bisect good c5ba734

# Tell git which commit does have the bug
git bisect bad 6c093f4

# Here, do your test for the bug.
# This could be running a script, doing a journey on a website, unit test etc.

# If the current commit has bug:
git bisect bad

# If the current commit does not have the bug
git bisect good

# This will repeat until it finds the first commit with the bug
# To exit the bisect, either:

# Go back to original branch:
git bisect reset

# Or stick with current HEAD
git bisect reset HEAD

# Or you can exit the bisect at a specific commit
git bisect reset <commit ID>

Avanzando: Automatización científica


En su informe de depuración científica, Stuart Halloway explicó cómo usar el comando git bisectpara automatizar la depuración.
Se enfoca en Clojure, pero no necesitamos saber este idioma para beneficiarnos de su charla.

Git bisect es en parte una automatización científica. Escribes un pequeño programa que probará algo, y Git salta de un lado a otro, cortando el mundo a la mitad con cada salto, hasta que encuentre el borde en el que tu prueba cambia de estado.
Stuart Halloway

Al principio git bisectpuede parecer una característica interesante y bastante interesante, pero al final no es muy útil. El rendimiento de Stewart en gran medida muestra que en realidad es contraproducente depurar como estamos acostumbrados. Si en cambio te enfocas en hechos empíricos, ya sea que la prueba pase o no, entonces puedes ejecutarla en todos los commits, comenzando con la versión de trabajo, y reducir la sensación de "deambular en la oscuridad" a la que estamos acostumbrados.

Entonces, ¿cómo automatizamosgit bisect? Puede pasarle un script para cada confirmación correspondiente. Anteriormente, dije que puede ejecutar manualmente el script en cada paso de bisect, pero si pasa un comando para ejecutar, ejecutará automáticamente el script en cada paso. Puede ser un script específicamente para depurar este problema específico o una prueba (modular, funcional, integración, cualquier tipo de prueba). Por lo tanto, puede escribir una prueba para verificar que la regresión no se repita y ejecutar esta prueba en confirmaciones anteriores:

# Begin the bisect
git bisect start

# Tell git which commit does not have the bug
git bisect good c5ba734

# Tell git which commit does have the bug
git bisect bad 6c093f4

# Tell git to run a specific script on each commit
# For example you could run a specific script:
git bisect run ./test-bug

# Or use a test runner
git bisect run jest

En cada pasado cometer


Una de las fortalezas git bisectes el uso efectivo de la búsqueda binaria para evitar todos los eventos en la historia de una manera no lineal. Pero a veces se necesita un bypass lineal. Puede escribir un script que lea el registro de Git y recorra el código en cada confirmación. Pero hay un amigo, que lo haga por usted: git rebase.

Kamran Ahmed en un tweet escrito como rebaseestá, qué commit no pasa la prueba:

Encuentre una confirmación que no pase la prueba:

$ git rebase -i --exec "yarn test" d294ae9

El comando ejecuta la prueba de hilo en todas las confirmaciones entre d294ae9 y HEAD y se detiene en la confirmación donde se bloquea la prueba.

Ya hemos considerado git bisectesta tarea, que puede ser más eficiente, pero en este caso no estamos limitados a un caso de uso.

Hay un lugar para la creatividad. Quizás desee generar un informe sobre cómo ha cambiado el código con el tiempo (o mostrar el historial de pruebas), y simplemente analizar el registro de Git no es suficiente. Quizás este no sea el truco más útil en este artículo, pero es interesante y muestra una tarea, cuya realidad no podíamos creer antes:

# This will run for every commit between current and the given commit ID
git rebase -i --exec ./my-script

Una selección de artículos y manuales para ayudarlo a profundizar en Git


En dicho artículo, es imposible profundizar en el tema, de lo contrario, todo el libro resultará. Elegí algunos pequeños trucos que incluso los usuarios experimentados podrían no conocer. Pero Git tiene muchas más características: desde funciones básicas hasta scripts complejos, configuraciones precisas e integración de consola. Por lo tanto, aquí hay algunos recursos que pueden ser de su interés:

  1. Explorer git . Un sitio interactivo que lo ayuda a comprender fácilmente cómo lograr lo que desea.
  2. Dang it git! . Cada uno de nosotros en algún momento puede perderse en Git y no sabe cómo resolver ningún problema. Este sitio proporciona soluciones a muchos de los problemas más comunes.
  3. Pro git . Este libro gratuito es un recurso invaluable para comprender Git.
  4. Git Docs. — . , Git Docs, Git (, man git-commit) Git .
  5. Thoughtbot. Git Thoughtbot .
  6. Git. Git.
  7. Git. , … . Git, .
  8. Git: desde principiante hasta nivel avanzado . Mike Ritmüller escribió este útil artículo, que es ideal para usuarios novatos de Git.
  9. Pequeñas cosas que amo hacer con Git . Fue este artículo de Harry Roberts el que me hizo darme cuenta de cuántas posibilidades aún acechan en Git, además de mover el código a través de las ramas.
  10. Atlassian Advanced Git Guides . Estos tutoriales detallan muchos de los temas mencionados en este artículo.
  11. Git hoja de trucos en Github . Siempre es conveniente tener una buena hoja de trucos para herramientas como Git.
  12. Reducción de git . Este artículo detalla varios indicadores de comando Git y recomienda muchos alias.

Pero, ¿qué más puedes leer ?

  1. Git. №1: , .git
  2. Git. №2: rebase.
  3. .

All Articles