Cuando estaba mirando la documentación de los comandos de git, noté que muchos de ellos tenían una opción para <pathspec>
. Inicialmente pensé que esta era solo una forma técnica de decir “ruta” y supuse que solo podía aceptar directorios y nombres de archivos. Después de sumergirme en la madriguera del conejo de la documentación, descubrí que la opción pathspec de los comandos git es capaz de mucho más.
Pathspec es el mecanismo que usa git para limitar el alcance de un comando de git a un subconjunto del repositorio. Si ha usado mucho git, es probable que haya usado una especificación de ruta, lo sepa o no. Por ejemplo, en el comando git add README.md
, la especificación de ruta es README.md
. Sin embargo, es capaz de muchos más matices y flexibilidad.
Entonces, ¿por qué debería aprender sobre pathspecs? Dado que es parte de muchos comandos, estos comandos se vuelven mucho más poderosos con una comprensión de las especificaciones de ruta. Con git add
, puede agregar solo los archivos dentro de un solo directorio. Con git diff
, puede examinar solo los cambios realizados en los nombres de archivo con una extensión de .scss
. Usted puede git grep
todos los archivos excepto los del /dist
directorio.
Además, pathspecs puede ayudar con la escritura de alias de git más genéricos. Por ejemplo, tengo un alias llamado git todo
, que buscará la cadena en todos mis archivos de repositorio 'todo'
. Sin embargo, me gustaría que esto mostrara todas las instancias de la cadena, incluso si no están dentro de mi directorio de trabajo actual. Con pathspecs, veremos cómo esto es posible.
archivo o directorio
La forma más sencilla de usar una especificación de ruta es con solo un directorio y/o un nombre de archivo. Por ejemplo, con git add
puedes hacer lo siguiente. .
, src/
, y README
son las especificaciones de ruta respectivas para cada comando.
git add . # add CWD (current working directory)
git add src/ # add src/ directory
git add README # add only README directory
También puede agregar varias especificaciones de ruta a un comando:
git add src/ server/ # adds both src/ and server/ directories
A veces, es posible que vea un --
que precede a la especificación de ruta de un comando. Esto se usa para eliminar cualquier ambigüedad de cuál es la especificación de ruta y qué es parte del comando.
comodines
Además de archivos y directorios, puede hacer coincidir patrones usando *
, ?
, y []
. El *
El símbolo se utiliza como comodín y coincidirá con el /
en rutas; en otras palabras, buscará a través de subdirectorios.
git log '*.js' # logs all .js files in CWD and subdirectories
git log '.*' # logs all 'hidden' files and directories in CWD
git log '*/.*' # logs all 'hidden' files and directories in subdirectories
Las comillas son importantes, especialmente cuando se usan *
! Evitan que su shell (como bash o ZSH) intente expandir los comodines por su cuenta. Por ejemplo, echemos un vistazo a cómo git ls-files
enumerará los archivos con y sin las comillas.
# example directory structure
#
# .
# ├── package-lock.json
# ├── package.json
# └── data
# ├── bar.json
# ├── baz.json
# └── foo.json
git ls-files *.json
# package-lock.json
# package.json
git ls-files '*.json'
# data/bar.json
# data/baz.json
# data/foo.json
# package-lock.json
# package.json
Dado que el caparazón está expandiendo el *
en el primer comando, git ls-files
recibe el comando como git ls-files package-lock.json package.json
. Las comillas aseguran que git es el que resuelve el comodín.
También puede utilizar el ?
carácter como comodín para un solo carácter. Por ejemplo, para hacer coincidir cualquiera mp3
o mp4
archivos, puede hacer lo siguiente.
git ls-files '*.mp?'
Expresiones de paréntesis
También puede usar “expresiones entre paréntesis” para hacer coincidir un solo carácter de un conjunto. Por ejemplo, si desea hacer coincidencias entre archivos TypeScript o JavaScript, puede usar [tj]
. Esto coincidirá con un t
o un j
.
git ls-files '*.[tj]s'
Esto coincidirá con cualquiera .ts
archivos o .js
archivos Además de solo usar caracteres, hay ciertas colecciones de caracteres a las que se puede hacer referencia dentro de las expresiones entre paréntesis. Por ejemplo, puedes usar [:digit:]
dentro de una expresión de paréntesis para que coincida con cualquier dígito decimal, o puede usar [:space:]
para que coincida con cualquier carácter de espacio.
git ls-files '*.mp[[:digit:]]' # mp0, mp1, mp2, mp3, ..., mp9
git ls-files '*[[:space:]]*' # matches any path containing a space
Para leer más sobre la expresión entre paréntesis y cómo usarla, consulte el manual de GNU.
firmas mágicas
Pathspecs también tiene la herramienta especial en su arsenal llamada “firmas mágicas” que desbloquea algunas funciones adicionales para sus pathspecs. Estas “firmas mágicas” se llaman usando :(signature)
al comienzo de su pathspec. Si esto no tiene sentido, no se preocupe: esperamos que algunos ejemplos ayuden a aclararlo.
cima
El top
La firma le dice a git que coincida con el patrón de la raíz del repositorio de git en lugar del directorio de trabajo actual. También puedes usar la abreviatura :/
en vez de :(top)
.
git ls-files ':(top)*.js'
git ls-files ':/*.js' # shorthand
Esto mostrará una lista de todos los archivos en su repositorio que tienen una extensión de .js
. Con el top
firma esto se puede llamar dentro de cualquier subdirectorio en su repositorio. ¡Encuentro que esto es especialmente útil al escribir alias genéricos de git!
git config --global alias.js 'ls-files -- ':(top)*.js''
Puedes usar git js
en cualquier lugar dentro de su repositorio para obtener una lista de todos los archivos JavaScript en su proyecto usando esto.
caso
El icase
La firma le dice a git que no se preocupe por las mayúsculas y minúsculas al hacer coincidir. Esto podría ser útil si no le importa en qué caso está el nombre del archivo; por ejemplo, esto podría ser útil para hacer coincidir jpg
archivos, que a veces usan la extensión en mayúsculas JPG
.
git ls-files ':(icase)*.jpg'
literal
El literal
La firma le dice a git que trate a todos tus personajes literalmente. Esto se usaría si desea tratar caracteres como *
y ?
como ellos mismos, en lugar de como comodines. A menos que su repositorio tenga nombres de archivo con *
o ?
, no espero que esta firma se use con demasiada frecuencia.
git log ':(literal)*.js' # returns log for the file '*.js'
globo
Cuando comencé a aprender pathspecs, noté que los comodines funcionaban de manera diferente a como estaba acostumbrado. Normalmente veo un solo asterisco *
como un comodín que no coincide con nada a través de directorios y asteriscos consecutivos (**
) como un comodín “profundo” que coincide con nombres a través de directorios. Si prefiere este estilo de comodines, puede utilizar el glob
firma mágica!
Esto puede ser útil si desea un control más detallado sobre cómo buscar en la estructura de directorios de su proyecto. Como ejemplo, observe cómo estos dos git ls-files
puede buscar a través de un proyecto React.
git ls-files ':(glob)src/components/*/*.jsx' # 'top level' jsx components
git ls-files ':(glob)src/components/**/*.jsx' # 'all' jsx components
atributo
Git tiene la capacidad de establecer “atributos” a archivos específicos. Puede establecer estos atributos mediante un .gitattributes
Archivo.
# .gitattributes
src/components/vendor/* vendored # sets 'vendored' attribute
src/styles/vendor/* vendored
Utilizando el attr
La firma mágica puede establecer requisitos de atributos para su especificación de ruta. Por ejemplo, es posible que deseemos ignorar los archivos anteriores de un proveedor.
git ls-files ':(attr:!vendored)*.js' # searches for non-vendored js files
git ls-files ':(attr:vendored)*.js' # searches for vendored js files
excluir
Por último, está la firma mágica “excluir” (abreviatura de :!
o :^
). Esta firma funciona de forma diferente al resto de firmas mágicas. Una vez resueltas todas las demás especificaciones de ruta, todas las especificaciones de ruta con un exclude
firma se resuelven y luego se eliminan de las rutas devueltas. Por ejemplo, puede buscar en todos sus .js
archivos mientras se excluyen los .spec.js
archivos de prueba.
git grep 'foo' -- '*.js' ':(exclude)*.spec.js' # search .js files excluding .spec.js
git grep 'foo' -- '*.js' ':!*.spec.js' . # shorthand for the same
Combinando firmas
¡No hay nada que te limite a usar múltiples firmas mágicas en una sola especificación de ruta! Puede usar múltiples firmas separando sus palabras mágicas con comas dentro de su paréntesis. Por ejemplo, puede hacer lo siguiente si desea hacer coincidir desde la base de su repositorio (usando top
), mayúsculas y minúsculas (usando icase
), usando solo código creado (ignorando los archivos de proveedores con attr
), y usando comodines de estilo global (usando glob
).
git ls-files -- ':(top,icase,glob,attr:!vendored)src/components/*/*.jsx'
Las únicas dos firmas mágicas que no puedes combinar son glob
y literal
, ya que ambos afectan cómo git
trata con comodines. Esto se menciona en el glosario de git con quizás mi oración favorita que he leído en cualquier documentación.
La magia glob es incompatible con la magia literal.
Pathspecs son una parte integral de muchos comandos de git, pero su flexibilidad no es accesible de inmediato. Al aprender a usar comodines y firmas mágicas, puede multiplicar su dominio de la línea de comandos de git.