Estaba escribiendo un guión simple en la computadora de la escuela y cometiendo los cambios en Git (en un repositorio que estaba en mi pendrive, clonado desde mi computadora en casa). Después de varias confirmaciones, me di cuenta de que estaba comprometiendo cosas como usuario root.
¿Hay alguna forma de cambiar el autor de estas confirmaciones a mi nombre?
git
version-control
git-filter-branch
git-rewrite-history
Flávio Amieiro
fuente
fuente
Respuestas:
Cambiar el autor (o el confirmador) requeriría reescribir toda la historia. Si estás de acuerdo con eso y crees que vale la pena, entonces deberías revisar git filter-branch . La página del manual incluye varios ejemplos para comenzar. También tenga en cuenta que puede usar variables de entorno para cambiar el nombre del autor, el confirmador, las fechas, etc. - vea la sección "Variables de entorno" de la página de manual de git .
Específicamente, puede corregir todos los nombres de autor y correos electrónicos incorrectos para todas las ramas y etiquetas con este comando (fuente: ayuda de GitHub ):
fuente
git push --force --tags origin HEAD:master
NOTA: Esta respuesta cambia los SHA1, así que tenga cuidado al usarla en una rama que ya ha sido enviada. Si solo desea corregir la ortografía de un nombre o actualizar un correo electrónico antiguo, git le permite hacerlo sin tener que volver a escribir el historial
.mailmap
. Ver mi otra respuesta .Usando Rebase Interactiva
Podrías hacerlo
Luego marque todas sus confirmaciones erróneas como "editar" en el archivo de rebase. Si también desea cambiar su primera confirmación, debe agregarla manualmente como primera línea en el archivo de rebase (siga el formato de las otras líneas). Luego, cuando git le pide que modifique cada confirmación, haga
editar o simplemente cerrar el editor que se abre, y luego hacer
para continuar el rebase.
Puede omitir abrir el editor por completo aquí agregando
--no-edit
para que el comando sea:Compromiso único
Como han señalado algunos de los comentaristas, si solo desea cambiar la confirmación más reciente, el comando rebase no es necesario. Solo haz
Esto cambiará el autor al nombre especificado, pero el confirmador se establecerá en su usuario configurado en
git config user.name
ygit config user.email
. Si desea establecer el confirmador en algo que especifique, esto establecerá tanto el autor como el confirmador:Nota sobre los compromisos de fusión
Hubo un pequeño defecto en mi respuesta original. Si hay ningún commit combinación entre la corriente
HEAD
y su<some HEAD before all your bad commits>
, a continuación,git rebase
se aplanan ellos (y por cierto, si se utiliza una solicitud de extracción de GitHub, no va a haber un montón de confirmaciones de combinación en el historial). Esto a menudo puede conducir a un historial muy diferente (ya que los cambios duplicados pueden "eliminarse"), y en el peor de los casos, puede llevar agit rebase
pedirle que resuelva conflictos de fusión difíciles (que probablemente ya se resolvieron en los compromisos de fusión). La solución es usar la-p
bandera paragit rebase
, que preservará la estructura de fusión de su historial. La página de manual paragit rebase
advierte que el uso-p
y-i
puede conducir a problemas, pero en elBUGS
la sección dice "Editar confirmaciones y volver a redactar sus mensajes de confirmación debería funcionar bien".He agregado
-p
al comando anterior. Para el caso en el que solo está cambiando la confirmación más reciente, esto no es un problema.fuente
git commit --amend --reset-author
También funciona una vezuser.name
yuser.email
están configurados correctamente.<commit>
usaruser.name
yuser.email
desde~/.gitconfig
: ejecutargit rebase -i <commit> --exec 'git commit --amend --reset-author --no-edit'
, guardar, salir. No hay necesidad de editar!También puedes hacer:
Tenga en cuenta que si está usando este comando en el símbolo del sistema de Windows, debe usarlo en
"
lugar de'
:fuente
"A previous backup already exists in refs/original/ Force overwriting the backup with -f"
lo siento, pero dónde-f
va a estar la bandera cuando se ejecute este script dos veces. En realidad, eso está en la respuesta de Brian, disculpen las molestias justo después de que la rama de filtro sea la solución.Una línea, pero tenga cuidado si tiene un repositorio multiusuario: esto cambiará todas las confirmaciones para tener el mismo (nuevo) autor y confirmador.
Con saltos de línea en la cadena (que es posible en bash):
fuente
HEAD
al final del comando?git push --force --tags origin 'refs/heads/*'
después del comando recomendado$git push --force --tags origin 'refs/heads/master'
Ocurre cuando no tiene un $ HOME / .gitconfig inicializado. Puedes arreglar esto como:
probado con git versión 1.7.5.4
fuente
--local
obras tambiéngit commit --amend --reset-author --no-edit
comando es especialmente útil si creó confirmaciones con la información de autor incorrecta, luego configure el autor correcto después del hecho a través degit config
. Ahorré un $$ ahora mismo cuando tuve que actualizar mi correo electrónico.Para una sola confirmación:
(extraído de la respuesta del autor)
fuente
git help commit
,git commit --amend
cambia la confirmación en la "punta de la rama actual" (que es HEAD). Esta es normalmente la confirmación más reciente, pero puede hacer la confirmación que desee al verificar primero esa confirmación congit checkout <branch-name>
ogit checkout <commit-SHA>
.author
y no elcommitter
En el caso de que solo los pocos commits superiores tengan malos autores, puede hacer todo esto dentro
git rebase -i
usando elexec
comando y el--amend
commit, de la siguiente manera:que le presenta la lista editable de confirmaciones:
Luego agregue
exec ... --author="..."
líneas después de todas las líneas con malos autores:guardar y salir del editor (para ejecutar).
Esta solución puede ser más larga de escribir que algunas otras, pero es altamente controlable: sé exactamente a qué compromete.
Gracias a @asmeurer por la inspiración.
fuente
exec git commit --amend --reset-author -C HEAD
?Someone else's commit
lugar demy bad commit 1
? IntentéHEAD^^
enmendar los últimos 2 commits, y funcionó perfectamente bien.git rebase -i HEAD^^^^^^
usted también puede escribirgit rebase -i HEAD~6
Github tiene una buena solución , que es el siguiente script de shell:
fuente
git reset --hard HEAD^
un par de veces en los otros repositorios locales para obtener una versión anterior,git pull
-ed la versión enmendada, y aquí estoy sin ninguna línea que contengaunknown <[email protected]>
(me encantó el incumplimiento de git).git push -f
. Además, los repositorios locales deben volverse a clasificar después de esto.Como mencionó docgnome, reescribir el historial es peligroso y romperá los repositorios de otras personas.
Pero si realmente quieres hacer eso y estás en un entorno bash (no hay problema en Linux, en Windows, puedes usar git bash, que se proporciona con la instalación de git), usa git filter-branch :
Para acelerar las cosas, puede especificar un rango de revisiones que desea reescribir:
fuente
--tag-name-filter cat
es la opción "hacer que funcione".--tag-name-filter cat
. Esto realmente debería haber sido el comportamiento predeterminado.Al hacerse cargo de un commit no fusionado de otro autor, hay una manera fácil de manejar esto.
git commit --amend --reset-author
fuente
--no-edit
a hacer esto aún más fácil, ya que por lo general la mayoría de la gente quiere actualizar sólo la dirección de correo electrónico y no el mensaje de confirmaciónPuede usar esto como un alias para que pueda hacer:
o para los últimos 10 commits:
Añadir a ~ / .gitconfig:
Fuente: https://github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig
Espero que sea útil.
fuente
[[ ]]
compatible con sh[ ]
(paréntesis individuales). Además de eso funciona muy bien, gracias!Esta es una versión más elaborada de la versión de @ Brian:
Para cambiar el autor y el confirmador, puede hacer esto (con saltos de línea en la cadena que es posible en bash):
Puede obtener uno de estos errores:
(esto significa que otra rama de filtro se ha ejecutado previamente en el repositorio y la referencia de la rama original se respalda en refs / original )
Si desea forzar la ejecución a pesar de estos errores, agregue la
--force
bandera:Es
-- --all
posible que se necesite una pequeña explicación de la opción: hace que la rama de filtro funcione en todas las revisiones en todas las referencias (que incluye todas las ramas). Esto significa, por ejemplo, que las etiquetas también se reescriben y es visible en las ramas reescritas.Un "error" común es usar
HEAD
en su lugar, lo que significa filtrar todas las revisiones solo en la rama actual . Y luego no existirían etiquetas (u otras referencias) en la rama reescrita.fuente
Un solo comando para cambiar el autor de las últimas N confirmaciones:
NOTAS
--no-edit
bandera se asegura degit commit --amend
que no pida una confirmación adicionalgit rebase -i
, puede seleccionar manualmente los commits donde cambiar el autor,el archivo que edite se verá así:
Aún puede modificar algunas líneas para ver dónde desea cambiar el autor. Esto le da un buen punto medio entre la automatización y el control: ve los pasos que se ejecutarán, y una vez que guarde, todo se aplicará a la vez.
fuente
git rebase -i master -x ...
git rebase -i <sha1 or ref of starting point>
edit
(oe
)repita los dos comandos siguientes hasta que haya procesado todas las confirmaciones:
git commit --amend --reuse-message=HEAD --author="New Author <[email protected]>"
;git rebase --continue
Esto mantendrá toda la otra información de confirmación (incluidas las fechas). La
--reuse-message=HEAD
opción evita que se inicie el editor de mensajes.fuente
Utilizo lo siguiente para reescribir al autor para un repositorio completo, incluidas las etiquetas y todas las ramas:
Luego, como se describe en la página MAN de filter-branch , elimine todas las referencias originales respaldadas por
filter-branch
(esto es destructivo, primero haga una copia de respaldo):fuente
--tag-name-filter cat
. De lo contrario, sus etiquetas permanecerán en la cadena original de confirmaciones. Las otras respuestas no mencionan esto.Adapte esta solución que funciona ingiriendo un simple
author-conv-file
(el formato es el mismo que para git-cvsimport ). Funciona cambiando todos los usuarios como se define en elauthor-conv-file
todas las ramas.Usamos esto junto con
cvs2git
para migrar nuestro repositorio de cvs a git.es decir, muestra
author-conv-file
La secuencia de comandos:
fuente
Debo señalar que si el único problema es que el autor / correo electrónico es diferente al habitual, esto no es un problema. La solución correcta es crear un archivo llamado
.mailmap
en la base del directorio con líneas comoY a partir de entonces, los comandos like
git shortlog
considerarán esos dos nombres como iguales (a menos que usted les indique específicamente que no lo hagan). Ver http://schacon.github.com/git/git-shortlog.html para obtener más información.Esto tiene la ventaja de todas las otras soluciones aquí, ya que no tiene que volver a escribir el historial, lo que puede causar problemas si tiene un flujo ascendente, y siempre es una buena manera de perder datos accidentalmente.
Por supuesto, si cometió algo como usted mismo y realmente debería ser otra persona, y no le importa reescribir la historia en este momento, cambiar el autor de confirmación es probablemente una buena idea para fines de atribución (en cuyo caso lo dirijo a mi Otra respuesta aquí).
fuente
Encontré que las versiones presentadas son demasiado agresivas, especialmente si confirma parches de otros desarrolladores, esto esencialmente robará su código.
La siguiente versión funciona en todas las ramas y cambia el autor y el comitter por separado para evitarlo.
Felicitaciones a leif81 para la opción de todos.
fuente
Cambie commit
author name & email
porAmend
y luego reemplaceold-commit with new-one
:Otra forma
Rebasing
:fuente
La forma más rápida y fácil de hacer esto es usar el argumento --exec de git rebase:
Esto creará una lista de tareas que se verá así:
y esto funcionará todo automáticamente, lo que funciona cuando tienes cientos de confirmaciones.
fuente
Si usted es el único usuario de este repositorio, puede reescribir la historia utilizando
git filter-branch
(como svick escribió ), ogit fast-export
/git fast-import
más el guión de filtro (como se describe en el artículo referido en docgnome respuesta ) o interactiva de rebase . Pero cualquiera de ellos cambiaría las revisiones desde el primer compromiso modificado en adelante; Esto significa problemas para cualquiera que haya basado sus cambios en la reescritura de su rama.RECUPERACIÓN
Si otros desarrolladores no basaron su trabajo en la versión previa a la reescritura, la solución más simple sería volver a clonar (clonar nuevamente).
Alternativamente, pueden intentarlo
git rebase --pull
, lo que avanzaría rápidamente si no hubiera cambios en su repositorio, o cambiaría su rama por encima de las confirmaciones reescritas (queremos evitar la fusión, ya que mantendría los comités de reescritura para siempre). Todo esto asumiendo que no tienen trabajo comprometido; usegit stash
para guardar los cambios de otra manera.Si otros desarrolladores usan ramas de características, y / o
git pull --rebase
no funciona, por ejemplo, porque el flujo ascendente no está configurado, tienen que volver a basar su trabajo sobre los compromisos posteriores a la reescritura. Por ejemplo, justo después de buscar nuevos cambios (git fetch
), para unamaster
rama basada en / bifurcadaorigin/master
, es necesario ejecutarAquí
origin/master@{1}
está el estado previo a la reescritura (antes de buscar), vea gitrevisions .La solución alternativa sería usar refs / replace / mecanismo, disponible en Git desde la versión 1.6.5. En esta solución, proporciona reemplazos para confirmaciones que tienen correo electrónico incorrecto; entonces, cualquiera que
fetch = +refs/replace/*:refs/replace/*
busque referencias de 'reemplazo' (algo así como refspec en el lugar apropiado en su lugar.git/config
) obtendría reemplazos de forma transparente, y aquellos que no busquen esas referencias verían compromisos antiguos.El procedimiento es algo como esto:
Encuentre todas las confirmaciones con correo electrónico incorrecto, por ejemplo, utilizando
Para cada confirmación incorrecta, cree una confirmación de reemplazo y agréguela a la base de datos de objetos
Ahora que ha corregido el compromiso en la base de datos de objetos, debe decirle a git que reemplace de forma automática y transparente el compromiso incorrecto por uno corregido mediante el
git replace
comando:Finalmente, enumere todos los reemplazos para verificar si este procedimiento tuvo éxito
y verifique si se realizan reemplazos
Por supuesto, puede automatizar este procedimiento ... bueno, todo excepto usar el
git replace
que no tiene (todavía) modo por lotes, por lo que tendría que usar el bucle de shell para eso o reemplazarlo "a mano".¡NO PROBADO! YMMV.
Tenga en cuenta que puede encontrar algunas esquinas ásperas al usar el
refs/replace/
mecanismo: es nuevo y aún no está muy bien probado .fuente
Si las confirmaciones que desea corregir son las últimas, y solo un par de ellas, puede usar una combinación de
git reset
ygit stash
volver a confirmarlas después de configurar el nombre y el correo electrónico correctos.La secuencia será algo así (para 2 confirmaciones incorrectas, sin cambios pendientes):
fuente
Si está utilizando Eclipse con EGit, entonces hay una solución bastante fácil.
Suposición: tiene confirmaciones en una rama local 'local_master_user_x' que no se puede enviar a una rama remota 'maestra' debido al usuario no válido.
fuente
Con el rebase interactivo, puede colocar un comando de modificación después de cada confirmación que desee modificar. Por ejemplo:
fuente
;-)
.Tenga en cuenta que git almacena dos direcciones de correo electrónico diferentes, una para el emisor (la persona que cometió el cambio) y otra para el autor (la persona que escribió el cambio).
La información de confirmación no se muestra en la mayoría de los lugares, pero puede verla con
git log -1 --format=%cn,%ce
(o usarla enshow
lugar delog
especificar una confirmación particular).Si bien cambiar el autor de tu último commit es tan simple como
git commit --amend --author "Author Name <[email protected]>"
, no hay una sola línea o argumento para hacer lo mismo con la información del committer.La solución es (temporalmente o no) cambiar su información de usuario, luego enmendar el commit, lo que actualizará el committer a su información actual:
fuente
path\to\repo\.git
. Todavía no estoy seguro de qué necesitarías hacer para eliminarlo por completo. Desafortunadamente, las enmiendas (?) No parecen borrarse.Hoy hemos tenido un problema en el que un carácter UTF8 en el nombre de un autor causaba problemas en el servidor de compilación, por lo que tuvimos que reescribir el historial para corregirlo. Los pasos dados fueron:
Paso 1: cambie su nombre de usuario en git para todas las confirmaciones futuras, según las instrucciones aquí: https://help.github.com/articles/setting-your-username-in-git/
Paso 2: Ejecute el siguiente script bash:
Descripción general rápida: Revise su repositorio en un archivo temporal, revise todas las ramas remotas, ejecute el script que reescribirá el historial, hará un impulso forzado del nuevo estado y les dirá a todos sus colegas que hagan un cambio de base para obtener los cambios.
Tuvimos problemas para ejecutar esto en OS X porque de alguna manera estropeó las terminaciones de línea en los mensajes de confirmación, por lo que tuvimos que volver a ejecutarlo en una máquina Linux después.
fuente
Tu problema es muy común. Consulte " Uso de Mailmap para corregir la lista de autores en Git "
En aras de la simplicidad, he creado un script para facilitar el proceso: git-changemail
Después de poner ese script en su camino, puede emitir comandos como:
Cambiar coincidencias de autor en la rama actual
Cambie las coincidencias de autor y confirmador en <branch> y <branch2>. Pase
-f
a rama de filtro para permitir reescribir copias de seguridadMostrar usuarios existentes en repositorio
Por cierto, después de realizar los cambios, limpie la copia de seguridad de la rama de filtro con: git-backup-clean
fuente
Probar esto. Hará lo mismo que se mencionó anteriormente, pero de forma interactiva.
Referencia: https://github.com/majdarbash/git-author-change-script
fuente
Quiero agregar mi ejemplo también. Quiero crear una bash_function con el parámetro dado.
esto funciona en mint-linux-17.3
fuente
Si usted es el único usuario de este repositorio o no le importa posiblemente romper el repositorio para otros usuarios, entonces sí. Si ha empujado estas confirmaciones y existen en otro lugar donde puede acceder a ellas, entonces no, a menos que no le importe romper los repositorios de otras personas. El problema es que al cambiar estas confirmaciones, generará nuevos SHA que harán que se traten como confirmaciones diferentes. Cuando alguien más intenta obtener estas confirmaciones modificadas, la historia es diferente y kaboom.
Esta página http://inputvalidation.blogspot.com/2008/08/how-to-change-git-commit-author.html describe cómo hacerlo. (No he probado esto, así que YMMV)
fuente
refs/replace/
mecanismo.