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-filter
reescribe 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
--date
opción que le permite especificar directamente la fecha del autor. Su uso anticipado incluyegit filter-branch --env-filter
tambié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 --amend
lugar 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 --orphan
es 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
.git
directorio y restableciéndolo desde su copia de seguridad.Nota: Los siguientes ejemplos usan el comando de nivel inferior en
git update-index --add
lugar degit add
. Podría usar git add , pero primero necesitaría copiar el archivo desde alguna ubicación externa a la ruta esperada (--index-filter
ejecuta 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-filter
a 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-filter
y cosas--parent-filter
similares"sed -e \"s/^$/-p $new_commit/\""
.fuente
--index-filter
aplicado 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.-- --all
para 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.perl
desde 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-branch
en 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_DATE
yGIT_COMMITTER_DATE
las 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 commit
2013-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
--date
también sea compatible con el formato de fecha relativa legible por humanos.git --date
solo 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á queAuthorDate
es la fecha que especificó, peroCommitDate
es 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 myfile
luegogit 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 -l
ycut
, 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=fuller
muestra AuthorDate y CommitDate.git commit
opción--date
solo 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_DATE
es la fecha en que se modificó el archivo, mientras queGIT_COMMITTER_DATE
es la fecha en que se confirmó. Es importante tener en cuenta que, de forma predeterminada,git log
muestra las fechas de autor como "Fecha", pero luego utiliza fechas de confirmación para filtrar cuando se le ofrece una--since
opción.stat -c %y
en macOS (y otras variantes de BSD) esstat -f %m
.Lo siguiente es lo que utilizo para confirmar los cambios en
foo
alN=1
dí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
date
argumento:date -v-3d
.Eso es realmente útil cuando olvidas cometer algo ayer, por ejemplo.
ACTUALIZACIÓN :
--date
también acepta expresiones como--date "3 days ago"
o incluso--date "yesterday"
. Entonces podemos reducirlo a un comando de línea:fuente
git --date
só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 --date
solo 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_DATE
yGIT_COMMITTER_DATE
:donde
date -d'...'
puede ser la fecha exacta como2019-01-01 12:00:00
o 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