¿Cómo agrupar todos los compromisos de git en uno?
¿Cómo comprimes todo tu repositorio hasta la primera confirmación?
Puedo cambiar la base a la primera confirmación, pero eso me dejaría con 2 confirmaciones. ¿Hay alguna manera de hacer referencia al compromiso antes del primero?
A partir de git 1.6.2 , puedes usargit rebase --root -i
Para cada confirmación excepto la primera, cambie pick
a squash
en el editor que aparece.
Una sola línea (para Bash/Zsh)
Puedes crear un compromiso de squash-all directamente desde HEAD
, sin ningún tipo de rebase , simplemente ejecuta:
git reset $(git commit-tree HEAD^{tree} -m "A new start")
Nota : esto requiere un shell compatible con POSIX como bash/zsh o Git Bash en Windows .
Crear un alias en~/.gitconfig
[alias]
squash-all = "!f(){ git reset $(git commit-tree HEAD^{tree} \"$@\");};f"
Entonces simplemente ejecuta:git squash-all -m "a brand new start"
Nota : proporcione el mensaje de confirmación desde la entrada estándar o mediante las opciones -m
/ -F
, como el comando git commit . Consulte el manual de git-commit-tree .
Alternativamente, puede crear el alias con el siguiente comando:
git config --global alias.squash-all '!f(){ git reset $(git commit-tree HEAD^{tree} "$@");};f'
Explicar
crear una única confirmación a través de
git commit-tree
Lo que
git commit-tree HEAD^{tree} -m "A new start"
hace es:Crea un nuevo objeto de confirmación basado en el objeto de árbol proporcionado y emite la nueva identificación del objeto de confirmación en la salida estándar. El mensaje de registro se lee desde la entrada estándar, a menos que se proporcionen las opciones -m o -F.
La expresión
HEAD^{tree}
representa el objeto de árbol correspondiente aHEAD
, es decir, la punta de su rama actual. consulte Objetos de árbol y Objetos de confirmación .restablecer la rama actual a la nueva confirmación
Luego
git reset
simplemente restablezca la rama actual al objeto de confirmación recién creado.De esta manera, no se toca nada en el espacio de trabajo, ni hay necesidad de rebase/aplastar, 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 a partir de una plantilla de proyecto
Esto es útil para crear el "compromiso inicial" en un nuevo proyecto usando otro repositorio como 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 plantilla como remoto ( origin
o de otro modo) y colapsa el historial del repositorio de plantilla en su confirmación inicial.
Si todo lo que quiere hacer es aplastar todas sus confirmaciones hasta la confirmación 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), porque la operación de rebase probablemente se ejecutará muy lentamente para generar la lista de confirmaciones del editor de rebase interactivo, así como también ejecutará la rebase en sí.
Aquí hay dos soluciones más rápidas y eficientes cuando estás eliminando una gran cantidad de confirmaciones:
Solución alternativa n.° 1: ramas huérfanas
Simplemente puede crear una nueva rama huérfana al final (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, lo que efectivamente equivale 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:
- git-checkout(1) Página del manual .
Solución alternativa n.° 2: reinicio parcial
Otra solución eficaz es simplemente utilizar un reinicio mixto o parcial de la confirmación raíz <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:
- git-reset(1) Página del manual .