¿Cómo aplastar todos los commits de git en uno?
¿Cómo se reduce todo el repositorio a la primera confirmación?
Puedo rebase a la primera confirmación, pero eso me dejaría con 2 confirmaciones. ¿Hay alguna manera de hacer referencia a la confirmación antes de la primera?
15 answers
Quizás la forma más fácil es simplemente 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 editar eso 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-01 14:23:33
En versiones recientes de git, puedes usar git rebase --root -i
.
Para cada confirmación excepto la primera, cambie pick
a squash
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-19 04:46:15
Actualizar
He creado 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 "A new start".
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 revestimiento
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.
Explicar
-
Crea un solo commit a través de
git commit-tree
Lo que
git commit-tree HEAD^{tree} -m "A new start"
hace es:Crea un nuevo objeto commit basado en el objeto árbol proporcionado y emite el nuevo id de objeto de confirmación en stdout. El mensaje de registro es lea desde la entrada estándar, a menos que se den las opciones-m o-F.
La expresión
HEAD^{tree}
significa el objeto de árbol correspondiente aHEAD
, es decir, la punta de su rama actual. ver Tree-Objectsy Commit-Objects. -
Restablecer la rama actual a la nueva confirmación
Luego {[12] } simplemente restablezca la rama actual a la rama recién creada confirmar objeto.
De esta manera, nada en el espacio de trabajo se toca, ni hay necesidad de rebase / squash, lo que lo hace muy rápido. Y el tiempo necesario es irrelevante para el tamaño del repositorio o la profundidad del historial.
Variación: Nuevo Repo de a Plantilla de proyecto
Esto es útil para crear el "commit inicial" en un nuevo proyecto usando otro repositorio como la plantilla/arquetipo/seed/skeleton. 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 plantilla como un control remoto (origin
o de otro modo) y contrae el historial del repositorio de plantilla en su confirmación inicial.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-17 13:35:33
Si todo lo que quieres hacer es aplastar todas tus confirmaciones a la confirmación raíz, entonces mientras
git rebase --interactive --root
Puede funcionar, no es práctico para un gran número de commits (por ejemplo, cientos de commits), porque la operación rebase probablemente se ejecutará muy lentamente para generar la lista de commits del editor de rebase interactivo, así como ejecutar la propia rebase.
Aquí hay dos soluciones más rápidas y eficientes cuando estás aplastando un gran número de commits:
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 raíz inicial de un árbol de historial de confirmaciones completamente nuevo y separado, que es efectivamente equivalente a aplastar todas tus 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: restablecimiento suave
Otra solución eficiente es para simplemente usar un reinicio mixto o suave a la confirmación root <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:
echo "message" | git commit-tree HEAD^{tree}
Esto creará un commit huérfano con el árbol de HEAD, y mostrará su nombre (SHA-1) en stdout. Entonces restablece tu sucursal allí.
git reset SHA-1
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-23 15:04:21
La forma más fácil es usar el comando 'plumbing' 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 te devuelve al estado de 'confirmación inicial' donde puedes comenzar con una confirmación inicial nueva.
git update-ref -d refs/heads/master
git commit -m "New initial commit"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-02 13:17:06
Así es como terminé haciendo esto, por si acaso funciona para alguien más:
Recuerde que siempre hay riesgo en hacer cosas como esta, y nunca es una mala idea crear una rama save antes de comenzar.
Comience por registrar
git log --oneline
Desplácese hasta la primera confirmación, copie SHA
git reset --soft <#sha#>
Reemplazar <#sha#>
con el SHA copiado del log
git status
Asegúrate de que todo esté verde, de lo contrario ejecuta git add -A
git commit --amend
Modificar todos los cambios actuales a actual primero commit
Ahora fuerza a empujar esta rama y sobrescribirá lo que hay allí.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-05 16:04:50
Leí algo sobre el uso de injertos, pero nunca lo investigué mucho.
De todos modos, puedes aplastar esas últimas 2 confirmaciones manualmente con algo como esto:
git reset HEAD~1
git add -A
git commit --amend
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-01 10:27:43
Primero, aplasta todos tus commits en un solo commit usando git rebase --interactive
. Ahora te quedan dos confirmaciones para aplastar. Para hacerlo, lea cualquiera de
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:27
Para aplastar usando injertos
Agregue un archivo .git/info/grafts
, ponga allí el hash de confirmación que desea que se convierta en su raíz
git log
ahora comenzará a partir de ese commit
Para hacerlo 'real' ejecutar git filter-branch
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-05 19:12:11
"Solución alternativa #1: ramas huérfanas" me ayuda.
"git rebase interactive interactive root root" atascado en el conflicto de archivos gitignored.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-26 13:17:19
Esta respuesta mejora a un par de anteriores (por favor vote hacia arriba), asumiendo que además de crear el commit único (no-parents no-history), usted también desea retener todos los datos del commit de ese commit:
- Autor (nombre y correo electrónico)
- Fecha de autor
- Commiter (nombre y correo electrónico)
- Fecha de compromiso
- Mensaje de registro de comunicación
Por supuesto, el commit-SHA del commit nuevo/único cambiará, porque representa un nuevo (non-)history, convirtiéndose en un parentless / root-commit.
Esto se puede hacer leyendo git log
y estableciendo algunas variables para git commit-tree
. Suponiendo que desea crear un solo commit desde master
en una nueva rama one-commit
, conservando los datos de commit 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
')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-28 17:27:50
Normalmente lo hago así:
-
Asegúrese de que todo está confirmado, y anote 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 head 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 a la primera confirmación y cambiar el mensaje de confirmación, o si desea mantenga el mensaje de confirmación existente, puede ejecutargit commit --amend --no-edit
-
Ejecute
git push -f
para forzar el empuje de sus cambios
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-18 13:13:28
Crear una copia de seguridad
git branch backup
Restablecer a la confirmación especificada
git reset --soft <root>
Agregue todos los archivos a staging
git add .
Confirmar sin actualizar el mensaje
git commit --amend --no-edit
Empuje una nueva rama con confirmaciones aplastadas a repo
git push -f
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-19 14:12:55
En una línea de 6 palabras
git checkout --orphan new_root_branch && git commit
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-15 21:57:00