tag - ¿Cómo hago un commit de Git en el pasado?
git tag (7)
El consejo que le dieron es defectuoso. La configuración incondicional de GIT_AUTHOR_DATE en un --env-filter
reescribirá la fecha de cada confirmación. Además, sería inusual usar git commit inside --index-filter
.
Aquí se enfrentan múltiples problemas independientes.
Especificación de fechas distintas de "ahora"
Cada commit tiene dos fechas: la fecha del autor y la fecha del committer. Puede sobrescribir 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:
Git internal format = <unix timestamp> <time zone offset>, e.g. 1112926393 +0200
RFC 2822 = e.g. Thu, 07 Apr 2005 22:13:13 +0200
ISO 8601 = e.g. 2005-04-07T22:13:13
El único comando que escribe una nueva confirmación durante el uso normal es git commit . También tiene una opción - fecha que le permite especificar directamente la fecha del autor. Su uso anticipado incluye git filter-branch --env-filter
también utiliza las variables de entorno mencionadas anteriormente (estas son parte del "env" después del cual se nombra la opción, vea "Opciones" en git-filter-branch (1) y el comando "plomería" subyacente git-commit-tree(1) .
Insertar un archivo en un solo historial de ref
Si tu repositorio es muy simple (es decir, solo tienes una sola rama, no hay etiquetas), entonces probablemente puedas usar git rebase para hacer el trabajo.
En los siguientes comandos, use el nombre del objeto (SHA-1 hash) 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 .
---A---B---C---o---o---o master
git checkout master
git checkout A~0
git add path/to/file
git commit --date=''whenever''
git tag ,new-commit -m''delete me later''
git checkout -
git rebase --onto ,new-commit A
git tag -d ,new-commit
---A---N (was ",new-commit", but we delete the tag)
/
B''---C''---o---o---o master
Si desea actualizar A para incluir el nuevo archivo (en lugar de crear un nuevo compromiso donde se haya agregado), utilice git commit --amend
lugar de git commit
. El resultado sería así:
---A''---B''---C''---o---o---o master
Lo anterior funciona siempre que puedas nombrar la confirmación que debería ser el padre de tu nueva confirmación. 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:
B---C---o---o---o master
git checkout master
git checkout --orphan new-root
git rm -rf .
git add path/to/file
GIT_AUTHOR_DATE=''whenever'' git commit
git checkout -
git rebase --root --onto new-root
git branch -d new-root
N (was new-root, but we deleted it)
/
B''---C''---o---o---o master
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 refracción múltiple
Si su repositorio es más complejo (es decir, tiene más de un ref (ramas, etiquetas, etc.)), entonces probablemente necesite 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 refs de respaldo, pero a menudo es más fácil recuperarse de un filtrado no del todo correcto simplemente borrando su directorio .git
y restaurándolo desde su respaldo.
Nota: Los ejemplos a continuación usan el comando de nivel más bajo git update-index --add
lugar de git add
. Podría usar git add , pero primero tendría que copiar el archivo desde una 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:
new_file=$(git hash-object -w path/to/file)
git filter-branch /
--index-filter /
''git update-index --add --cacheinfo 100644 ''"$new_file"'' path/to/file'' /
--tag-name-filter cat /
-- --all
git reset --hard
Realmente no veo ninguna razón para cambiar las fechas de las confirmaciones existentes con --env-filter ''GIT_AUTHOR_DATE=…''
. Si lo usaste, lo harías condicional para que reescriba la fecha de cada confirmación.
Si desea que su nuevo archivo aparezca solo en las confirmaciones después de una confirmación existente ("A"), puede hacer esto:
file_path=path/to/file
before_commit=$(git rev-parse --verify A)
file_blob=$(git hash-object -w "$file_path")
git filter-branch /
--index-filter ''
if x=$(git rev-list -1 "$GIT_COMMIT" --not ''"$before_commit"'') &&
test -n "$x"; then
git update-index --add --cacheinfo 100644 ''"$file_blob $file_path"''
fi
'' /
--tag-name-filter cat /
-- --all
git reset --hard
Si desea que el archivo se agregue a través de una nueva confirmación que se insertará en el medio de su historial, deberá generar la nueva confirmación antes de usar git filter-branch y agregar --parent-filter
a git filter -branco :
file_path=path/to/file
before_commit=$(git rev-parse --verify A)
git checkout master
git checkout "$before_commit"
git add "$file_path"
git commit --date=''whenever''
new_commit=$(git rev-parse --verify HEAD)
file_blob=$(git rev-parse --verify HEAD:"$file_path")
git checkout -
git filter-branch /
--parent-filter "sed -e s/$before_commit/$new_commit/g" /
--index-filter ''
if x=$(git rev-list -1 "$GIT_COMMIT" --not ''"$new_commit"'') &&
test -n "$x"; then
git update-index --add --cacheinfo 100644 ''"$file_blob $file_path"''
fi
'' /
--tag-name-filter cat /
-- --all
git reset --hard
También podría hacer arreglos para que el archivo se agregue primero en una nueva confirmación raíz: cree su nueva confirmación raíz mediante el método "huérfano" de la sección git rebase ( new_commit
en new_commit
), use el --index-filter
incondicional, y a --parent-filter
como "sed -e /"s/^$/-p $new_commit//""
.
Estoy convirtiendo todo en Git para mi uso personal y encontré algunas versiones antiguas de un archivo que ya están en el repositorio. ¿Cómo lo aplico al historial en el orden correcto según la "fecha de modificación" del archivo, así que tengo 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
En mi caso, al usar la opción --date, mi proceso de git se colgó. 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 las fechas aprobadas y funcionó esta vez. Gracias por todas las respuestas aquí.
git commit --date="`date --date=''2 day ago''`" -am "update"
En mi caso, con el tiempo había guardado un montón de versiones de myfile como myfile_bak, myfile_old, myfile_2010, backups / myfile, etc. Quería poner la historia de myfile en git usando sus fechas de modificación. Así que cambie el nombre de la más antigua a miarchivo, git add myfile
, luego git commit --date=(modification date from ls -l) myfile
, renombrar next oldest a myfile, otro git commit con --date, repeat ...
Para automatizar esto de alguna manera, puede usar shell-foo para obtener la hora de modificación del archivo. Empecé con ls -l
y cut
, pero stat (1) es más directo
git commit --date="`stat -c %y myfile`" myfile
Lo siguiente es lo que uso para confirmar cambios en foo
a N=1
días en el pasado:
git add foo
git commit -m "Update foo"
git commit --amend --date="$(date -v-1d)"
Si desea comprometerse con una fecha aún más antigua, digamos 3 días atrás, simplemente cambie el argumento de date -v-3d
: 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:
git add foo ; git commit --date "yesterday" -m "Update"
Puede crear la confirmación de la forma habitual, pero cuando la GIT_AUTHOR_DATE
, configure las variables de entorno GIT_AUTHOR_DATE
y GIT_COMMITTER_DATE
en los GIT_COMMITTER_DATE
apropiados.
Por supuesto, esto hará que la confirmación se realice en la punta de su rama (es decir, frente a la confirmación actual de HEAD). Si desea llevarlo más lejos en el repositorio, tiene que ser un poco sofisticado. Digamos que tienes esta historia:
o--o--o--o--o
Y desea que su nueva confirmación (marcada como "X") aparezca en segundo lugar :
o--X--o--o--o--o
La forma más fácil sería realizar una bifurcación desde la primera confirmación, agregar la nueva confirmación y luego volver a establecer la base de todas las demás confirmaciones sobre la nueva. Al igual que:
$ git checkout -b new_commit $desired_parent_of_new_commit
$ git add new_file
$ GIT_AUTHOR_DATE=''your date'' GIT_COMMITTER_DATE=''your date'' git commit -m ''new (old) files''
$ git checkout master
$ git rebase new_commit
$ git branch -d new_commit
Sé que esta pregunta es bastante antigua, pero eso fue lo que realmente funcionó para mí:
git commit --date="10 day ago" -m "Your commit message"
Siempre puede cambiar una fecha en su computadora, hacer una confirmación, luego cambiar la fecha y presionar.