Pregunta

¿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?

¿Fue útil?

Solución

Tal vez 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 que usted podría hacer primero git log > original.log comprometerse y luego editarlo para su inicial al mensaje de confirmación 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

Otros consejos

En versiones recientes de Git, puede utilizar git rebase --root -i.

Para cada confirmación, excepto el primero, el cambio pick a squash.

Actualizar

He hecho un git squash-all alias.
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 la confirmación por omisión mensaje "Un nuevo comienzo" se utilizaría

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'

Una Liner

git reset $(git commit-tree HEAD^{tree} -m "A new start")

Nota: . Aquí "A new start" es sólo un ejemplo, no dude en utilizar su propio idioma

TL; DR

No hay necesidad de aplastar, utilizar git commit-tree para crear un huérfano cometer e ir con ella.

Explicar

  1. crear un único cometer a través de git commit-tree

    Lo que hace es git commit-tree HEAD^{tree} -m "A new start":

      

    Crea un nuevo objeto cometer basado en el objeto de árbol proporcionado   y emite el nuevo identificador de objeto asignado en la salida estándar. El mensaje de registro es   leer de la entrada estándar, a menos que se les da -m o -F opciones.

    El HEAD^{tree} expresión significa que el objeto árbol correspondiente a HEAD, a saber, la punta de la rama actual. ver Árbol-Objetos y Commit-Objetos .

  2. restablecer la rama actual a la nueva cometer

    A continuación, git reset simplemente restablecer la rama actual a la recién creada cometer objeto.

De esta manera, no hay nada en el espacio de trabajo se toca, ni hay   la necesidad de rebase / squash, lo que hace que sea muy rápido. Y el tiempo que se necesita es irrelevante para el tamaño o la historia de profundidad repositorio.

Variación: Nueva Repo a partir de una plantilla de proyecto

Esto es útil para crear el "inicial Commit" 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 añadiendo el repositorio plantilla como un mando a distancia (origin o de otra manera) y se derrumba la historia de la cesión temporal plantilla en su inicial cometió.

Si lo único que quiere hacer es calabaza todas sus confirmaciones hasta la raíz comprometerse, a continuación, mientras que

git rebase --interactive --root

puede trabajar, no es práctico para un gran número de confirmaciones (por ejemplo, cientos de confirmaciones), debido a que la operación de rebase probablemente correr muy lentamente para generar el editor de rebase interactivo lista de cambios, así como ejecutar el rebase en sí.

Aquí hay dos soluciones más rápidas y más eficientes cuando se está aplastando un gran número de confirmaciones:

solución Alternativa # 1: ramas huérfanos

Usted puede simplemente crear una nueva rama huérfano en la punta (es decir, el más reciente commit) de la rama actual. Este huérfanos rama forma la raíz inicial confirmar sobre una completamente nueva e independiente cometer árbol de la historia, que es efectivamente equivalente a aplastar a todos sus compromete:

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 automático

Otra solución eficiente es usar simplemente un restablecimiento mixto o blanda a la raíz cometer <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 huérfano cometen con el árbol de la cabeza, y la salida de su nombre (SHA-1) en la salida estándar. A continuación, sólo restablecer la rama allí.

git reset SHA-1

Así es como terminé haciendo esto, en caso de que le funcione a alguien más:

Recuerde que siempre existe un riesgo al hacer cosas como esta y nunca es mala idea crear una rama guardada antes de comenzar.

Comience iniciando sesión

git log --oneline

Desplácese hasta la primera confirmación, copie SHA

git reset --soft <#sha#>

Reemplazar <#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

Modificar todos los cambios actuales al primer compromiso actual

Ahora fuerce el empuje de esta rama y sobrescribirá lo que hay allí.

La forma más sencilla es utilizar el 'cañerías' update-ref comando para eliminar la rama actual.

No se puede utilizar git branch -D ya que tiene una válvula de seguridad que le impida la supresión de la rama actual.

Esto lo pone de nuevo en el estado inicial 'comprometerse' donde se puede comenzar con cometer un fresco inicial.

git update-ref -d refs/heads/master
git commit -m "New initial commit"

He leído algo acerca del uso de injertos, pero nunca investigado mucho.

De todos modos, se puede aplastar los últimos 2 compromete de forma manual con algo como esto:

git reset HEAD~1
git add -A
git commit --amend

En primer lugar, de squash todas sus confirmaciones en un único cometen utilizando git rebase --interactive. Ahora uno se queda con dos confirmaciones para aplastar. Para ello, lea cualquiera de

en una línea de 6 palabras

git checkout --orphan new_root_branch  &&  git commit

Para aplastar el uso de injertos

Añadir un .git/info/grafts archivo, puesto allí el hash cometer desea convertirse en su raíz

git log ahora se iniciará a partir de que se comprometan

Para que sea más 'real' git filter-branch ejecutar

crear una copia de seguridad

git branch backup

Restablecer a confirmación especificada

git reset --soft <#root>

a continuación, añadir todos los archivos de puesta en escena

git add .

comprometerse sin actualizar el mensaje

git commit --amend --no-edit

empujar nueva rama con commits aplastados a repo

git push -f

Esta respuesta mejora en un par más arriba (por favor vote para arriba), en el supuesto de que, además de crear un commit (no-padres sin historia), que también quieren conservar la totalidad de la commit-datos de que cometer:

  • Autor (nombre y correo electrónico)
  • fecha Authored
  • Commiter (nombre y correo electrónico)
  • fecha confirmada
  • mensaje de registro Commmit

Por supuesto, el commit-SHA de la nueva / única confirmación va a cambiar, porque representa una nueva historia (no), convirtiéndose en un sin padres / root-commit.

Esto se puede hacer mediante la lectura de git log y el establecimiento de algunas variables para git commit-tree. Suponiendo que se desea crear una única confirmación de master en una nueva one-commit rama, la retención de los datos anteriores commit-:

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
')

Usualmente lo hago de esta manera:

  • Asegúrese de que todo está comprometida, y anotar el último commit id en caso de que algo va mal, o cree una rama separada como la copia de seguridad

  • Ejecutar git reset --soft `git rev-list --max-parents=0 --abbrev-commit HEAD` para restablecer su cabeza a la primera comprometerse, pero deje su índice sin cambios. Todos los cambios desde la primera comprometen aparecerá ahora listo para ser comprometido.

  • Ejecutar git commit --amend -m "initial commit" de enmendar su comprometerse con la primera comprometerse y cambiar el mensaje de confirmación, o si desea mantener el mensaje del informe existente, puede ejecutar git commit --amend --no-edit

  • Ejecutar git push -f para obligar a empujar los cambios

scroll top