git culpe con ignorerevsfile opcional

5 minutos de lectura

avatar de usuario de anol
anol

Tengo alrededor de 40 repositorios git, la mayoría de los cuales tienen un .git-blame-ignore-revs archivo para usar con git blame. Entonces, en lugar de configurar localmente cada uno de ellos con blame.ignorerevsfile=.git-blame-ignore-revslo apliqué a mi global configuración de git.

Sin embargo, los pocos repositorios que no no tienen un archivo de este tipo se ven afectados por él: ejecutando git blame sobre ellos da como resultado fatal: could not open object name list: .git-blame-ignore-revs.

¿Hay alguna manera de decirle a git que lea dicho archivo? si existiera, ignorándolo de otra manera? Eso sería ideal: simple de configurar, pero discreto si no existe dicho archivo.

Nota: otra razón por la que tener un opcional .git-blame-ignore-revs file es útil, es que prácticamente todos los repositorios de git se crean sin dicho archivo, y solo más tarde se agrega. Sin embargo, al dividir en dos las confirmaciones antiguas, podemos terminar volviendo a un punto antes el archivo existe, y luego tenemos que touch termine de dividirlo en dos, luego elimínelo nuevamente para poder volver a la confirmación HEAD. Incluso si uso un local config para el archivo, esta situación extremadamente molesta seguirá ocurriendo. Por esa razón, creo que el comportamiento predeterminado debería ser ignorar el archivo si no existe.

avatar de usuario de phd
Doctor

¿Hay alguna manera de decirle a git que lea dicho archivo si existe, ignorándolo de lo contrario?

No hay. Cualquiera de los usos

git config --local blame.ignoreRevsFile .git-blame-ignore-revs

en lugar de --global. O usar

git config --local blame.ignoreRevsFile ""

en aquellos repositorios donde el archivo no existe. Nombre de archivo vacío significa “no usar ningún archivo”.

O crear vacío .git-blame-ignore-revs archivos

Actualizar. Prueba con un nuevo repositorio temporal:

git init test-git
cd test-git

git config --global blame.ignoreRevsFile test
git config --show-origin blame.ignoreRevsFile
file:/home/phd/.gitconfig       test

git config --local blame.ignoreRevsFile ""
git config --show-origin blame.ignoreRevsFile
file:.git/config

Upd2

git blame testfile
fatal: could not open object name list: test

¡Ay!

  • Sería genial que la configuración local tomara el relevo de la global, permitiendo ignorar la primera. Sin embargo, a pesar de que su enlace dice que Los nombres de archivo vacíos restablecerán la lista de revisiones ignoradasy esta página diciendo que “Los archivos se leen en el orden dado arriba [global before local]con el último valor encontrado prevaleciendo sobre los valores leídos anteriormente”, todavía no funciona, probablemente debido a este comportamiento: “Cuando se toman varios valores, se utilizarán todos los valores de una clave de todos los archivos”.

    – anol

    21 de diciembre de 2021 a las 14:42

  • @anol Muestra el resultado de git config --show-origin blame.ignoreRevsFile en un repositorio sin el archivo.

    – Doctor

    21 dic 2021 a las 14:50


  • Muestra file:$HOME/.gitconfig .git-blame-ignore-revscomo era de esperar, ya que lo configuré a través de --global previamente. Me parece que hay una ligera desviación de comportamiento de la documentación. Incluso al agregar la opción --ignore-revs-file ""cual es documentado como Un nombre de archivo vacío, “”, borrará la lista de revoluciones de los archivos procesados ​​previamenteno parece ser el caso para mí: git todavía busca el .git-blame-ignore-revs archivo y el comando falla.

    – anol

    21 dic 2021 a las 15:00

  • @anol Ups, tienes razón! Ver Upd2. Yo diría que esto es un error en git blame.

    – Doctor

    21 de diciembre de 2021 a las 15:44

  • Aparentemente un parche relacionado se ha propuesto para git en agosto, pero desde entonces creo que no ha avanzado mucho. Pero algo similar podría aterrizar en una futura versión de Git.

    – anol

    21 de diciembre de 2021 a las 16:16

Avatar de usuario de Ryan Ulch
ryan ulch

Bueno, esta no es una solución perfecta ya que no se aplicará a una culpa de git sin procesar, pero usé un alias de comando de shell. Obviamente, cambie el comando según sea necesario, pero FWIW obtuve resultados mucho mejores para mis casos de uso con ‘-w’ (ignore los espacios en blanco) proporcionados:

git config --global alias.bl "!myGitBlame.sh"

Y el script de shell correspondiente (que se supone que está en la RUTA para el comando de configuración de git anterior):

#!/usr/bin/env bash
if [[ -z $GIT_PREFIX ]]; then
    GIT_PREFIX=./
fi

# Assume (and impose limitation) that the last argument to this script is the
# file being blamed. Pull it out of the args list and make it relative to the
# root of the git repo to match the execution context of git shell aliases
LAST_ARG="${@: -1}"
set -- "${@:1:$(($#-1))}"
FILE_PATH=$GIT_PREFIX$LAST_ARG

# optional ignore revs file, specified relative to the root of the git repo
OPTIONAL_GIT_BLAME_REVS_FILE=.git-blame-ignore-revs

# if the revs file does not exist, ignore-revs-file accepts empty values
# without issue
if [[ ! -f $OPTIONAL_GIT_BLAME_REVS_FILE ]]; then
    OPTIONAL_GIT_BLAME_REVS_FILE=""
fi

git blame -w --ignore-revs-file=$OPTIONAL_GIT_BLAME_REVS_FILE "$@" $FILE_PATH

Y como una sola línea si desea transmitirlo fácilmente a sus compañeros de trabajo:

git config --global alias.bl '!if [[ -z $GIT_PREFIX ]]; then GIT_PREFIX=./; fi; f() { LAST_ARG="${@: -1}"; set -- "${@:1:$(($#-1))}"; FILE_PATH=$GIT_PREFIX$LAST_ARG; GIT_BLAME_REVS_FILE=.git-blame-ignore-revs; if [[ ! -f $GIT_BLAME_REVS_FILE ]]; then GIT_BLAME_REVS_FILE=""; fi; git blame -w --ignore-revs-file=$GIT_BLAME_REVS_FILE "$@" $FILE_PATH; }; f'

NOTA: Esto supone que el último argumento para culpar a git es el archivo; eso significa que esto no es 1: 1 con lo que acepta una línea de comando de culpa normal de git porque técnicamente puede git blame <commit_hash> <file> o git blame <file> <commit_hash> en casos simples.

Definitivamente uso esto en la forma de script de shell, pero soy consciente de las ventajas de la configuración de 1 línea para propagar esto a los compañeros de trabajo y evitar la RUTA en general.

También asumo un entorno bash disponible aquí.

Inicialmente, intenté simplemente hacer una configuración local que apunte directamente al archivo, pero eso se encuentra con todo tipo de problemas que usted describió, y también interactúa muy mal con las configuraciones del árbol de trabajo. Esto debería funcionar de manera más general, aunque no completamente a la perfección.

¿Ha sido útil esta solución?