remove - ¿Cómo aplastar todos los git commit en uno?
git tag commit id (15)
¿Cómo aplastas todo tu repositorio hasta la primera confirmación?
Puedo volver a la primera confirmación, pero eso me dejaría con 2 confirmaciones. ¿Hay alguna forma de hacer referencia al commit antes del primero?
Aplastar utilizando injertos.
Agregue un archivo .git/info/grafts
, ponga allí el hash de confirmación que desea que sea su raíz
git log
ahora comenzará a partir de ese compromiso
Para que sea ''real'' ejecute git filter-branch
Actualizar
He hecho un alias git squash-all
.
Ejemplo de uso : git squash-all "a brand new start"
.
[alias]
squash-all = "!f(){ git reset $(git commit-tree HEAD^{tree} -m /"${1:-A new start}/");};f"
Advertencia : recuerde proporcionar un comentario, de lo contrario se usaría el mensaje de confirmación predeterminado "Un nuevo comienzo".
O puede crear el alias con el siguiente comando:
git config --global alias.squash-all ''!f(){ git reset $(git commit-tree HEAD^{tree} -m "${1:-A new start}");};f''
Un trazador de líneas
git reset $(git commit-tree HEAD^{tree} -m "A new start")
Nota : aquí " A new start
" es solo un ejemplo, siéntase libre de usar su propio idioma.
TL; DR
No hay necesidad de aplastar, use git commit-tree
para crear un commit huérfano e ir con él.
Explique
crear un solo compromiso a través de
git commit-tree
Lo que hace
git commit-tree HEAD^{tree} -m "A new start"
es:Crea un nuevo objeto de confirmación basado en el objeto de árbol proporcionado y emite el nuevo ID de objeto de confirmación en la salida estándar. El mensaje de registro se lee desde la entrada estándar, a menos que se den las opciones -m o -F.
La expresión
HEAD^{tree}
significa el objeto del árbol correspondiente aHEAD
, es decir, la punta de su rama actual. ver Tree-Objects Commit-Objects .restablecer la rama actual a la nueva confirmación
Luego,
git reset
simplemente restablece la rama actual al objeto commit recién creado.
De esta manera, no se toca nada en el área de trabajo, ni hay necesidad de rebase / squash, lo que lo hace realmente rápido. Y el tiempo necesario es irrelevante para el tamaño del repositorio o la profundidad del historial.
Variación: Nuevo repositorio de una plantilla de proyecto
Esto es útil para crear el "compromiso inicial" en un nuevo proyecto utilizando otro repositorio como la plantilla / arquetipo / semilla / esqueleto. Por ejemplo:
cd my-new-project
git init
git fetch --depth=1 -n https://github.com/toolbear/panda.git
git reset --hard $(git commit-tree FETCH_HEAD^{tree} -m "initial commit")
Esto evita agregar el repositorio de la plantilla como un control remoto ( origin
u otro) y colapsa el historial del repositorio de la plantilla en su confirmación inicial.
En una linea de 6 palabras
git checkout --orphan new_root_branch && git commit
"Solución alternativa # 1: ramas huérfanas" me ayuda.
"git rebase --interactive --root" se atascó en el conflicto de archivos gitignored.
Así es como terminé haciendo esto, en caso de que funcione para otra persona:
Recuerde que siempre existe el riesgo de hacer cosas como esta, y nunca es una mala idea crear una rama guardada antes de comenzar.
Comience por el registro
git log --oneline
Desplácese hasta la primera confirmación, copie SHA
git reset --soft <#sha#>
Reemplace <#sha#>
con el SHA copiado del registro
git status
Asegúrate de que todo esté verde, de lo contrario ejecuta git add -A
git commit --amend
Modifique todos los cambios actuales al primer compromiso actual
Ahora fuerce empuje esta rama y sobrescribirá lo que está allí.
En versiones recientes de git, puedes usar git rebase --root -i
.
Para cada commit excepto el primero, cambia pick
a squash
.
Esta respuesta mejora en un par de los de arriba (por favor vota), asumiendo que además de crear el único compromiso (sin padres sin historial), también quieres conservar todos los datos de compromiso de ese compromiso:
- Autor (nombre y correo electrónico)
- Fecha de autor
- Comisión (nombre y correo electrónico)
- Fecha comprometida
- Mensaje de registro de comision
Por supuesto, el commit-SHA del nuevo / single commit cambiará, ya que representa un nuevo historial (no), convirtiéndose en un parentless / root-commit.
Esto se puede hacer leyendo el git log
y configurando algunas variables para git commit-tree
. Suponiendo que desea crear una única confirmación desde el master
en una nueva sucursal de one-commit
, manteniendo los datos de confirmación anteriores:
git checkout -b one-commit master ## create new branch to reset
git reset --hard /
$(eval "$(git log master -n1 --format=''/
COMMIT_MESSAGE="%B" /
GIT_AUTHOR_NAME="%an" /
GIT_AUTHOR_EMAIL="%ae" /
GIT_AUTHOR_DATE="%ad" /
GIT_COMMITTER_NAME="%cn" /
GIT_COMMITTER_EMAIL="%ce" /
GIT_COMMITTER_DATE="%cd"'')" ''git commit-tree master^{tree} <<COMMITMESSAGE
$COMMIT_MESSAGE
COMMITMESSAGE
'')
La forma más fácil es usar el comando ''fontanería'' update-ref
para eliminar la rama actual.
No puede usar git branch -D
ya que tiene una válvula de seguridad para evitar que elimine la rama actual.
Esto le devuelve al estado de "confirmación inicial" donde puede comenzar con una confirmación inicial nueva.
git update-ref -d refs/heads/master
git commit -m "New initial commit"
Leí algo sobre el uso de injertos pero nunca lo investigué mucho.
De todos modos, puedes aplastar los 2 últimos compromisos manualmente con algo como esto:
git reset HEAD~1
git add -A
git commit --amend
Normalmente lo hago así:
Asegúrese de que todo esté confirmado, y escriba el último ID de confirmación en caso de que algo salga mal, o cree una rama separada como copia de seguridad
Ejecute
git reset --soft `git rev-list --max-parents=0 --abbrev-commit HEAD`
para restablecer su cabeza a la primera confirmación, pero deje su índice sin cambios. Todos los cambios desde la primera confirmación aparecerán listos para ser confirmados.Ejecute
git commit --amend -m "initial commit"
para modificar su confirmación de la primera confirmación y cambiar el mensaje de confirmación, o si desea mantener el mensaje de confirmación existente, puede ejecutargit commit --amend --no-edit
Ejecuta
git push -f
para forzar empujar tus cambios
Primero, aplasta todos tus compromisos en un solo compromiso usando git rebase --interactive
. Ahora te quedan dos compromisos para aplastar. Para hacerlo, lee cualquiera de
Quizás la forma más sencilla es crear un nuevo repositorio con el estado actual de la copia de trabajo. Si desea mantener todos los mensajes de confirmación, primero puede hacer git log > original.log
y luego editarlo para su mensaje de confirmación inicial en el nuevo repositorio:
rm -rf .git
git init
git add .
git commit
o
git log > original.log
# edit original.log as desired
rm -rf .git
git init
git add .
git commit -F original.log
Si todo lo que quieres hacer es aplastar todos tus compromisos hasta la confirmación de la raíz, entonces mientras
git rebase --interactive --root
puede funcionar, no es práctico para una gran cantidad de confirmaciones (por ejemplo, cientos de confirmaciones), ya que la operación de rebase probablemente se ejecutará muy lentamente para generar la lista de confirmaciones del editor de rebase interactivo, así como para ejecutar la rebase.
Aquí hay dos soluciones más rápidas y más eficientes cuando está aplastando una gran cantidad de confirmaciones:
Solución alternativa # 1: ramas huérfanas.
Simplemente puede crear una nueva rama huérfana en la punta (es decir, la confirmación más reciente) de su rama actual. Esta rama huérfana forma la confirmación de raíz inicial de un árbol de historial de confirmación completamente nuevo y separado, que es equivalente a aplastar todas sus confirmaciones:
git checkout --orphan new-master master
git commit -m "Enter commit message for your new initial commit"
# Overwrite the old master branch reference with the new one
git branch -M new-master master
Documentación:
Solución alternativa # 2: reinicio suave
Otra solución eficiente es simplemente usar un reinicio mixto o suave en el root commit <root>
:
git branch beforeReset
git reset --soft <root>
git commit --amend
# Verify that the new amended root is no different
# from the previous branch state
git diff beforeReset
Documentación:
crear una copia de seguridad
git branch backup
restablecer a la confirmación especificada
git reset --soft <root>
agregar todos los archivos a la puesta en escena
git add .
cometer sin actualizar el mensaje
git commit --amend --no-edit
empujar nueva rama con compromisos aplastados para repo
git push -f
echo "message" | git commit-tree HEAD^{tree}
Esto creará una confirmación huérfana con el árbol de HEAD y generará su nombre (SHA-1) en la salida estándar. Entonces simplemente reinicia tu rama allí.
git reset SHA-1