¿Cómo cambiar el nombre del autor filtrado por el post de confirmación?

La configuration es así. Tuvimos varios cambios al repository con un post de confirmación que se veía así:

[System] Updated the logs [System] CSV file updated etc. 

Ahora me gustaría que esos commits estén vinculados a una count de git específica para poder distinguir los cambios de mis commits. El "Sistema" ha estado cometiendo con el nombre del autor y los correos electrónicos como el mío.

Ahora me gustaría search los posts de confirmación y para cada confirmación que tenga [Sistema] en el post, me gustaría actualizar el nombre al Sistema. ¿Como puedo hacer eso?

y me gustaría que fuera en forma de command de console (donde puedo ejecutar un command, sin usar la opción -interactive para cambiarlo manualmente) (usando git of bash o python, cualquiera que sea la solución)

Hay algunos commands que podrían ayudar como:

git show :/[System] – que muestra el último post de git que coincide con la cadena

git-filter-branch

y alguna otra, pero no estoy seguro de cómo podría hacer eso en forma de guión (o cualquier otra).

La respuesta es la misma, con las mismas advertencias , como en el duplicado que sajib khan notó . Usted solo cambia la testing . Mire la respuesta aceptada allí, que contiene estas partes:

 git filter-branch --env-filter ' OLD_EMAIL="your-old-email@example.com" CORRECT_NAME="Your Correct Name" CORRECT_EMAIL="your-correct-email@example.com" if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ] 

Tenga en count que este primer paso testing la cadena de "committer email" del commit original. Desea probar el post de confirmación del commit original, posiblemente junto con el autor y / o committer del commit original.

 if <some-test> 

La parte difícil es la testing en sí, ya que el post de la confirmación original no es parte del entorno.

Si su testing se atesting, quiere cambiar tanto el autor como el autor del compromiso, por lo que no es del todo correcto:

 then export GIT_COMMITTER_NAME="$CORRECT_NAME" export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL" fi if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ] then export GIT_AUTHOR_NAME="$CORRECT_NAME" export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL" fi 

pero puede simplemente eliminar la segunda testing y anular tanto el autor como el committer:

 then export GIT_COMMITTER_NAME="$CORRECT_NAME" export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL" export GIT_AUTHOR_NAME="$CORRECT_NAME" export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL" fi 

Finalmente, el último bit del command seguirá siendo el mismo, por ejemplo:

 ' --tag-name-filter cat -- --branches --tags 

Por lo tanto, el problema se networkinguce a la <test> . Aquí debes tomar algunas decisiones:

  • ¿Desea cambiar (la copy de) cualquier confirmación que tenga la cadena literal [System] en algún lugar dentro de ella? O bien, ¿desea cambiar solo confirmaciones que comiencen con [System] ?

  • ¿Desea cambiar estas copys solo cuando el autor del compromiso original y / o el nombre del comitente y / o el correo electrónico coincidan con los suyos? ¿O desea cambiarlos independientemente del autor y / o autorizador original? ¿Qué ocurre si el autor coincide con su nombre pero el autor no lo hace, o si el autor del contrato se corresponde con su nombre, pero el autor no?

  • ¿Desea calcular la coincidencia "sobre la marcha" en el filter, o prefiere precomputar todas las ID de hash de confirmación, y luego aplicar el cambio a esas confirmaciones particulares?

Cuando piense en sus respuestas, recuerde que la forma git filter-branch opera git filter-branch es que copy cada confirmación a la que lo dirige ( --branches significa "cada compromiso accesible desde un nombre de twig"). A medida que copy cada confirmación, aplica cada uno de tus filters. Hay muchos; ver la documentation de git filter-branch para la list .

En efecto, el código de la twig de filter extrae la confirmación original, realiza los cambios solicitados aplicando cada filter en el order apropiado, y luego realiza una nueva confirmación del resultado. Si la nueva confirmación, incluida la identificación hash principal del nuevo compromiso, es bit por bit idéntica a la confirmación original, la nueva confirmación es la confirmación original. Sin embargo, tan pronto como uno se compromete en alguna parte de una cadena se modifica de alguna manera, la nueva confirmación obtiene una nueva ID de hash diferente. Esto obliga a todas las confirmaciones posteriores a tener al less una cosa diferente, es decir, el hash de confirmación padre, por lo que una vez que hay al less un cambio, el cambio "se extiende" por las confirmaciones restantes.

El resultado es un nuevo repository que ya no es compatible con el repository original. Todos los clones del original deben ser descartados y reemplazados con nuevos clones del nuevo repository, con sus nuevas identificaciones hash.

Si eliges responder a la tercera pregunta, "¿quieres precomputar las ID hash para cambiar?", Con "sí": esto te permite estar mucho más seguro de lo que hará tu filter, y que no tocará ninguna indeseada confirma, entonces tendrá que volver a calcular las ID de hash pre calculadas si necesita cambiar las cosas nuevamente después de un cambio anterior, ya que las ID de hash cambiarán cada vez que realice algún cambio. Si eliges "no, probaré dinámicamente", esto se convierte en un problema menor, pero tu código de testing debe ser correcto o modificarás las copys de las confirmaciones que no pretendas modificar. Por supuesto, puede inspeccionar cuidadosamente el nuevo repository modificado para asegurarse de que sea correcto. De lo contrario, en lugar de dejar de lado los originales en favor de la copy, descarte la copy y comience a filtrar nuevamente con una testing mejorada.

Consideremos ahora la <test> . Si ha preparado una list completa de todas las identificaciones de compromiso que desea cambiar, la testing será: "¿es el hash de la confirmación de copydo uno de los valores hash de la list?" El hash de commit a ser copydo está disponible, en todos los filters de twig de filter , como $GIT_COMMIT :

Filtros

Los filters se aplican en el order que se detalla a continuación. El argumento <command> siempre se evalúa en el context del shell utilizando el command eval (con la notable exception del filter de confirmación, por razones técnicas). Antes de eso, la variable de entorno $GIT_COMMIT se configurará para contener la identificación de la confirmación que se está reescribiendo. Además, GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_AUTHOR_DATE, GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL y GIT_COMMITTER_DATE se toman del compromiso actual y se exportan al entorno, con el fin de afectar las identidades del autor y del committer del compromiso de reemploop creado por git-commit-tree (1) después los filters se han ejecutado.

Por lo tanto, si sus identificadores de compromiso se ven afectados en un file, uno por línea, puede usar grep para ver si $GIT_COMMIT coincide con una de esas líneas:

 if grep $GIT_COMMIT /tmp/list-of-commits 

(como efecto secundario, si grep coincide con uno de esos commits, el hash del commit se imprimirá en la salida estándar, que verá durante el filtrado).

Si desea elegir commits dinámicamente, es un poco más difícil. Debe extraer el post de logging de compromiso dado el hash de confirmación. Puedes hacer esto con el git log :

 git log --no-walk --pretty=format:%B $GIT_COMMIT 

para get el post completo, o:

 git log --no-walk --pretty=format:%s $GIT_COMMIT 

para get solo la línea de asunto. A continuación, puede alimentarlo a través de un progtwig coincidente, como grep nuevamente, para decidir si el post contiene o comienza con una cadena.

Dado que grep hace expresiones regulares y los corchetes son caracteres de expresión regular, puede usar fgrep (grep de cadena fija) en su lugar. fgrep embargo, usar fgrep significa que es imposible verificar que el corchete abierto ocurra al principio de la línea de asunto, si deseas hacerlo.

Por lo tanto, algunas forms de detectar [System] dentro o al comienzo del post de logging son:

 if git log --no-walk --pretty=format:%B $GIT_COMMIT | fgrep "[System]" 

o:

 if git log --no-walk --pretty=format:%s $GIT_COMMIT | grep "^\[System]" 

Recuerde, en sh y bash, if ... simplemente ejecuta el command después de la palabra if , luego mira su estado de salida. Un estado de salida de cero significa "sí": la testing tiene éxito. Un estado de salida distinto de cero significa "no": la testing falla. La testing:

 if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ] 

simplemente está ejecutando el [ progtwig, con arguments:

 $GIT_COMMITTER_EMAIL (spaces retained as a single argument) = $OLD_EMAIL (spaces likewise protected by double quote) ] 

El progtwig /bin/[ , también conocido como /bin/test , busca el cierre ] como último argumento, y lo elimina. (Si se invoca como test , no busca el cierre ] .) Luego realiza la testing prescrita por los arguments restantes. En este caso, los arguments son dos cadenas con an = entre ellas, por lo que test si las dos cadenas son iguales.

Simplemente reemplazamos la testing con grep (para ver si $GIT_COMMIT está en un file de ID de confirmación) o con el git log ... | grep git log ... | grep (para ver si la salida de git log contiene una cadena). El estado de salida de grep nos dice si la cadena que estamos buscando se encontró, o no.

Si usa un file preparado de hashes de confirmación, puede probar muchos methods diferentes para recostackr los identificadores de hash de las confirmaciones que desea cambiar, sin mucho dolor, ya que trabajará en una progtwigción mucho más familiar (y probablemente más rica). ambiente que el disponible dentro de los filters eval -ed de git filter-branch .

Una advertencia más

Esto probablemente debería anotarse en la respuesta de la otra pregunta, pero cada vez que ejecute git filter-branch , es una buena idea ejecutarlo en un clon nuevo y fresco del repository. De esta forma, puede inspeccionar los nuevos commits cuidadosamente y ver si sus filters hicieron lo que esperaban que hicieran. De lo contrario, puede descartar el clon filtrado y volver a intentarlo, ya que lo único que ha gastado en él es el time y el espacio de disco necesarios para clonar y filtrar.

Puedes usar git commit –amend para cambiar el autor a un commit

mientras se rebase el uso

 edit 

luego usa el command:

 git commit --amend --author="Author Name <email@address.com>" 

luego usa:

 git rebase --continue 

Puede especificar el número de confirmación en rebase para modificar un compromiso particular