¿Cómo puedo usar git-rm y globbing de files para eliminar files de ciertos directorys, pero no de subdirectorys de esos directorys?

El escenario

Estoy tratando de eliminar algunos files de todo el historial de un repository de git. Todos comparten un par de criterios comunes:

  • Tienen "configuraciones" en el nombre del file. Sin embargo, también pueden tener varios prefijos y sufijos.
  • Se encontrarán en dos niveles en un determinado directory en el tree de files. Los nombres de los directorys de segundo nivel varían. Hay files de configuration más profundos en el tree de files que no deberían eliminarse.

Aquí, entonces, hay un ejemplo del tree de files:

root-directory/ |-> apples/ | |-> bad-settings-alpha.txt | |-> bad-settings-beta.txt | |-> oranges/ | |-> bad-settings-gamma.txt | |-> bad-settings-delta.txt | |-> navels/ | |-> good-settings.txt | |-> good-settings.txt 

Necesito filtrar todos los files de bad-settings mientras mantengo los files de good-settings correcta.

Mi acercamiento

Entonces, usando un tutorial proporcionado por GitHub , junto con la página de manual para git-rm , diseñé este command (dividido en dos líneas):

 git filter-branch -f --index-filter 'git rm --dry-run --cached \ --ignore-unmatch root-directory/*/*settings*.txt' --prune-empty -- --all 

De particular interés aquí es el file glob que utilicé: root-directory/*/*settings*.txt . Si utilizo ese file glob con ls , entonces obtengo exactamente la list de files que quiero eliminar. Por lo tanto, debería funcionar, ¿verdad?

Aparentemente no. Si ejecuto mi command con ese comodín, también se eliminan todos los files de configuration en niveles más profundos que dos. En el ejemplo anterior del tree de files, eso significa que root-directory/oranges/navels/good-settings.php se desmantelaría.


Intenté resolver esto solo, probando variaciones en el file glob y usando la maravillosa opción " --dry-run para git-rm . Nada parecía funcionar; todo lo que pude averiguar fue cómo cambiar la profundidad del tree de files en el que comencé a eliminar los files de configuration.

Encontré una cosa que parecía extremadamente relevante para mi problema. En la página de manual para git-rm , hay este ejemplo:

 git rm Documentation/\*.txt Removes all *.txt files from the index that are under the Documentation directory and any of its subdirectories. Note that the asterisk * is quoted from the shell in this example; this lets git, and not the shell, expand the pathnames of files and subdirectories under the Documentation/ directory. 

"Quita todos … los files del índice que están bajo el … directory y cualquiera de sus subdirectorys" es consistente con lo que está sucediendo realmente. Lo que es realmente interesante es la mención del asterisco citado. Entiendo que esto permite a git-rm manejar la expansión glob del file en lugar de bash . Bueno. Pero eso deja estas preguntas:

  • ¿Por qué querría hacer eso?
  • No estoy citando mis asteriscos, así que bash debería estar haciendo la expansión. Si eso es cierto, y mi file global funciona con ls , ¿por qué no funciona con git-rm ?

También he visto el ejemplo directamente debajo del anterior, y parece hacer lo que bash hacer. Y sin embargo, eso no me sucede a mí, de lo contrario no estaría aquí. Sin embargo, parece confirmar que quiero hacer la expansión de files con bash .

¿Por qué no utilizar find para mostrar dos niveles de files profundos?

 find . -maxdepth 2 -mindepth 2 -type f -name "bad-settings*" 

Esto le dará la list de malos ajustes de solo dos directores de nivel profundo. Puedes git rm en git rm través de xargs :

 find . -maxdepth 2 -mindepth 2 -type f -name "bad-settings*" | xargs git rm