Estoy convirtiendo todo a Git para mi uso personal y encontré algunas versiones antiguas de un archivo que ya están en el repositorio. ¿Cómo lo confirmo en el historial en el orden correcto de acuerdo con la "fecha de modificación" del archivo para que tenga un historial preciso del archivo?
Me dijeron que algo como esto funcionaría:
git filter-branch --env-filter="GIT_AUTHOR_DATE=... --index-filter "git commit path/to/file --date " --tag-name-filter cat -- --all
git
version-control
repository
git-commit
desconocido
fuente
fuente

git commit --date="xxx day ago" -m "yyy"es suficiente para ese propósito si alguien se pregunta.Respuestas:
El consejo que le dieron es defectuoso. Establecer incondicionalmente GIT_AUTHOR_DATE en un
--env-filterreescribe la fecha de cada confirmación. Además, sería inusual usar git commit dentro--index-filter.Estás lidiando con múltiples problemas independientes aquí.
Especificar fechas distintas a "ahora"
Cada confirmación tiene dos fechas: la fecha del autor y la fecha del confirmador. Puede anular cada uno proporcionando valores a través de las variables de entorno GIT_AUTHOR_DATE y GIT_COMMITTER_DATE para cualquier comando que escriba una nueva confirmación. Consulte "Formatos de fecha" en git-commit (1) o a continuación:
El único comando que escribe un nuevo commit durante el uso normal es git commit . También tiene una
--dateopción que le permite especificar directamente la fecha del autor. Su uso anticipado incluyegit filter-branch --env-filtertambién las variables de entorno mencionadas anteriormente (estas son parte del "env" después del cual se nombra la opción; consulte "Opciones" en git-filter-branch (1) y el comando subyacente "plomería" git-commit -árbol (1) .Insertar un archivo en un solo historial de referencia
Si su repositorio es muy simple (es decir, solo tiene una sola rama, sin etiquetas), entonces probablemente pueda usar git rebase para hacer el trabajo.
En los siguientes comandos, use el nombre del objeto (hash SHA-1) de la confirmación en lugar de "A". No olvide utilizar uno de los métodos de "anulación de fecha" cuando ejecute git commit .
Si desea actualizar A para incluir el nuevo archivo (en lugar de crear una nueva confirmación donde se agregó), use en
git commit --amendlugar degit commit. El resultado se vería así:Lo anterior funciona siempre que pueda nombrar el commit que debería ser el padre de su nuevo commit. Si realmente desea que su nuevo archivo se agregue a través de una nueva confirmación raíz (sin padres), entonces necesita algo un poco diferente:
git checkout --orphanes relativamente nuevo (Git 1.7.2), pero hay otras formas de hacer lo mismo que funcionan en versiones anteriores de Git.Insertar un archivo en un historial de múltiples referencias
Si su repositorio es más complejo (es decir, tiene más de una referencia (ramas, etiquetas, etc.)), entonces probablemente necesitará usar git filter-branch . Antes de usar git filter-branch , debe hacer una copia de seguridad de todo su repositorio. Un archivo tar simple de todo su árbol de trabajo (incluido el directorio .git) es suficiente. git filter-branch hace referencias de copia de seguridad, pero a menudo es más fácil recuperarse de un filtro no del todo correcto simplemente borrando su
.gitdirectorio y restableciéndolo desde su copia de seguridad.Nota: Los siguientes ejemplos usan el comando de nivel inferior en
git update-index --addlugar degit add. Podría usar git add , pero primero necesitaría copiar el archivo desde alguna ubicación externa a la ruta esperada (--index-filterejecuta su comando en un GIT_WORK_TREE temporal que está vacío).Si desea que su nuevo archivo se agregue a cada confirmación existente, puede hacer esto:
Realmente no veo ninguna razón para cambiar las fechas de las confirmaciones existentes con
--env-filter 'GIT_AUTHOR_DATE=…'. Si lo usó, lo haría condicional para que reescribiera la fecha de cada confirmación.Si desea que su nuevo archivo aparezca solo en las confirmaciones después de alguna confirmación existente ("A"), puede hacer esto:
Si desea que el archivo se agregue a través de una nueva confirmación que se insertará en la mitad de su historial, deberá generar la nueva confirmación antes de usar git filter-branch y agregar
--parent-filtera git filter-branch :También puede hacer arreglos para que el archivo se agregue primero en una nueva confirmación de raíz: cree su nueva confirmación de raíz a través del método "huérfano" de la sección git rebase (capturarla
new_commit), use el incondicional--index-filtery cosas--parent-filtersimilares"sed -e \"s/^$/-p $new_commit/\"".fuente
--index-filteraplicado a los commits devueltos porgit rev-list? Por el momento estoy viendo el filtro de índice aplicado a un subconjunto de rev-list. Agradezco cualquier idea.-- --allpara procesar todos los commits accesibles desde cualquier referencia. El último ejemplo muestra cómo cambiar solo ciertas confirmaciones (solo pruebe GIT_COMMIT para lo que quiera). Para cambiar solo una lista específica de confirmaciones, puede guardar la lista antes de filtrar (pgit rev-list … >/tmp/commits_to_rewrite. Ej. ), Luego probar la pertenencia al filtro (pif grep -qF "$GIT_COMMIT" /tmp/commits_to_rewrite; then git update-index …. Ej .). ¿Qué estás tratando de lograr exactamente? Es posible que desee comenzar una nueva pregunta si es demasiado para explicar en los comentarios.import-directories.perldesde Gitcontrib/(oimport-tars.perl, oimport-zips.py...) para crear un nuevo repositorio de Git a partir de sus instantáneas (incluso con Marcas de tiempo "antiguas"). Las técnicasrebase/filter-branchen mi respuesta solo son necesarias si desea insertar un archivo que "quedó fuera" del historial de un repositorio existente.Puede crear el compromiso como de costumbre, pero cuando lo haga, configure las variables de entorno
GIT_AUTHOR_DATEyGIT_COMMITTER_DATElas fechas y horas apropiadas.Por supuesto, esto hará la confirmación en la punta de su rama (es decir, frente a la confirmación HEAD actual). Si quieres retrasarlo más en el repositorio, debes ponerte un poco elegante. Digamos que tienes esta historia:
Y desea que su nueva confirmación (marcada como "X") aparezca en segundo lugar :
La forma más fácil sería bifurcarse desde la primera confirmación, agregar su nueva confirmación y luego cambiar el resto de las confirmaciones por encima de la nueva. Al igual que:
fuente
GIT_AUTHOR_DATE='Fri Jul 26 19:32:10 2013 -0400' GIT_COMMITTER_DATE='Fri Jul 26 19:32:10 2013 -0400' git commit2013-07-26T19:32:10: kernel.org/pub/software/scm/git/docs/…THE_TIME='2019-03-30T8:20:00 -0500' GIT_AUTHOR_DATE=$THE_TIME GIT_COMMITTER_DATE=$THE_TIME git commit -m 'commit message here'Sé que esta pregunta es bastante antigua, pero eso es lo que realmente funcionó para mí:
fuente
--datetambién sea compatible con el formato de fecha relativa legible por humanos.git --datesolo modificará el $ GIT_AUTHOR_DATE ... por lo que, según las circunstancias, verá la fecha actual adjunta al compromiso ($ GIT_COMMITTER_DATE)git show <commit-hash> --format=fuller. Allí verá queAuthorDatees la fecha que especificó, peroCommitDatees la fecha real de la confirmación.En mi caso lo largo del tiempo que había ahorrado un montón de versiones de mi_archivo como myfile_bak, myfile_old, myfile_2010, copias de seguridad / mi_archivo etc. quería poner la historia de mi_archivo en git usando sus fechas de modificación. Así que cambie el nombre del más antiguo a mi archivo,
git add myfileluegogit commit --date=(modification date from ls -l) myfile, cambie el nombre del más antiguo a mi archivo, otro git commit con --date, repita ...Para automatizar esto, puede usar shell-foo para obtener el tiempo de modificación del archivo. Empecé con
ls -lycut, pero stat (1) es más directofuente
--date"Anular la fecha de autor utilizada en la confirmación".git log'Date parece ser AuthorDate,git log --pretty=fullermuestra AuthorDate y CommitDate.git commitopción--datesolo modificará elGIT_AUTHOR_DATE, noGIT_COMMITTER_DATE. Como explica el Libro Pro Git : "El autor es la persona que originalmente escribió el trabajo, mientras que el responsable es la última persona que aplicó el trabajo". En el contexto de las fechas,GIT_AUTHOR_DATEes la fecha en que se modificó el archivo, mientras queGIT_COMMITTER_DATEes la fecha en que se confirmó. Es importante tener en cuenta que, de forma predeterminada,git logmuestra las fechas de autor como "Fecha", pero luego utiliza fechas de confirmación para filtrar cuando se le ofrece una--sinceopción.stat -c %yen macOS (y otras variantes de BSD) esstat -f %m.Lo siguiente es lo que utilizo para confirmar los cambios en
fooalN=1día en el pasado:Si desea comprometerse a una fecha aún más antigua, por ejemplo 3 días atrás, apenas cambia el
dateargumento:date -v-3d.Eso es realmente útil cuando olvidas cometer algo ayer, por ejemplo.
ACTUALIZACIÓN :
--datetambién acepta expresiones como--date "3 days ago"o incluso--date "yesterday". Entonces podemos reducirlo a un comando de línea:fuente
git --datesólo se modificará el $ GIT_AUTHOR_DATE ... así que dependiendo de las circunstancias verá la fecha actual adjunto a la confirmación ($ GIT_COMMITTER_DATE)git commit --amend --date="$(stat -c %y fileToCopyMTimeFrom)"git commit --amend --date="$(date -R -d '2020-06-15 16:31')"En mi caso, al usar la opción --date, mi proceso git se bloqueó. Puede ser que hice algo terrible. Y como resultado apareció un archivo index.lock. Así que eliminé manualmente los archivos .lock de la carpeta .git y los ejecuté, para que todos los archivos modificados se confirmaran en fechas pasadas y esta vez funcionó. Gracias por todas las respuestas aquí.
fuente
git commit --date. Además, su mensaje de confirmación de ejemplo debe modificarse para desalentar los mensajes de una línea deficientes como estos @JstRoRRgit --datesolo modificará el $ GIT_AUTHOR_DATE ... por lo que, según las circunstancias, verá la fecha actual adjunta al compromiso ($ GIT_COMMITTER_DATE)Para realizar una confirmación que parece que se hizo en el pasado, debe establecer ambas
GIT_AUTHOR_DATEyGIT_COMMITTER_DATE:donde
date -d'...'puede ser la fecha exacta como2019-01-01 12:00:00o relativa como5 months ago 24 days ago.Para ver ambas fechas en git log use:
Esto también funciona para confirmaciones de fusión:
fuente
Siempre puede cambiar una fecha en su computadora, hacer una confirmación, luego cambiar la fecha y presionar.
fuente
O simplemente use un falso git-history para generarlo para un rango de datos específico.
fuente