¿Cómo aplastas tu repository completo hasta el primer compromiso?
Puedo volver a la base del primer commit, pero eso me dejaría con 2 commits. ¿Hay alguna manera de hacer reference a la confirmación antes de la primera?
Quizás la forma más fácil es simplemente crear un nuevo repository con el estado actual de la copy de trabajo. Si desea conservar todos los posts de confirmación, primero puede hacer git log > original.log
y luego editarlo para su post de confirmación inicial en el nuevo repository:
rm -rf .git git init git add . git commit
o
git log > original.log # edit original.log as desinetworking rm -rf .git git init git add . git commit -F original.log
En versiones recientes de git, puedes usar git rebase --root -i
.
Para cada compromiso, excepto el primero, cambie la pick
para squash
.
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 utilizará el post de confirmación pnetworkingeterminado "Un nuevo inicio".
O puede crear el alias con el siguiente command:
git config --global alias.squash-all '!f(){ git reset $(git commit-tree HEAD^{tree} -m "${1:-A new start}");};f'
git reset $(git commit-tree HEAD^{tree} -m "A new start")
Nota : aquí " A new start
" es solo un ejemplo, no dude en usar su propio idioma.
No necesita squash, use git commit-tree
para crear un commit huérfano e ir con él.
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 object de compromiso basado en el object de tree proporcionado y emite el nuevo ID de object de compromiso en stdout. El post de logging se lee de la input estándar, a less que se den opciones -m o -F.
La expresión HEAD^{tree}
significa el object de tree correspondiente a HEAD
, es decir, la punta de su twig actual. ver Árbol-Objetos y Commit-Objetos .
restablecer la twig actual a la nueva confirmación
Luego, git reset
simplemente restablece la twig actual al object commit recién creado.
De esta forma, no se toca nada en el espacio de trabajo, ni hay necesidad de rebase / squash, lo que lo hace realmente rápido. Y el time necesario es irrelevante para el tamaño del repository o la profundidad del historial.
Esto es útil para crear el "compromiso inicial" en un nuevo proyecto usando otro repository como la plantilla / archetype / 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 repository de plantilla como un control remoto ( origin
o no) y queuepsa el historial del repository de la plantilla en su confirmación inicial.
Si todo lo que quieres hacer es aplastar todas tus confirmaciones hasta la confirmación raíz, entonces mientras
git rebase --interactive --root
puede funcionar, no es práctico para un gran número de confirmaciones (por ejemplo, cientos de confirmaciones), porque la operación de rebase probablemente se ejecutará muy lentamente para generar la list de confirmación del editor de rebase interactivo, así como ejecutar la propia rebase.
Aquí hay dos soluciones más rápidas y eficientes cuando elimina un gran número de confirmaciones:
Simplemente puede crear una nueva sucursal huérfana en la punta (es decir, la confirmación más reciente) de su sucursal actual. Esta twig huérfana forma la confirmación raíz inicial de un tree de historial de compromisos completamente nuevo e independiente, que es en realidad 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:
Otra solución eficiente es simplemente usar un restablecimiento mixto o blando a la confirmación <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á una confirmación huérfana con el tree de HEAD y dará su nombre (SHA-1) en stdout. Entonces solo reinicia tu twig allí.
git reset SHA-1
La forma más fácil es usar la update-ref
order del 'plomería' para eliminar la twig actual.
No puedes usar git branch -D
ya que tiene una válvula de security para evitar que elimines la twig actual.
Esto te devuelve al estado de 'compromiso inicial' donde puedes comenzar con una nueva confirmación inicial.
git update-ref -d refs/heads/master git commit -m "New initial commit"
Así es como terminé haciendo esto, por si acaso funciona para otra persona:
Recuerde que siempre hay riesgo al hacer cosas como esta, y nunca es una mala idea crear una twig de save antes de comenzar.
Comience registrando
git log --oneline
Desplácese hasta la primera confirmación, copie SHA
git reset --soft <#sha#>
Reemplace <#sha#>
con el SHA copydo del logging
git status
Asegúrate de que todo esté verde; de lo contrario, ejecuta git add -A
git commit --amend
Enmendar todos los cambios actuales al primer compromiso actual
Ahora fuerza empuje esta twig y sobrescribirá lo que está allí.
Primero, aplaste todas sus confirmaciones en una única confirmación mediante git rebase --interactive
. Ahora te quedan dos compromisos para aplastar. Para hacerlo, lea cualquiera de
Leí algo sobre el uso de injertos, pero nunca lo investigué demasiado.
De todos modos, puedes aplastar esos dos últimos commits manualmente con algo como esto:
git reset HEAD~1 git add -A git commit --amend
Agregue un file .git/info/grafts
, coloque allí el hash de confirmación que desea que se convierta en su raíz
git log
ahora comenzará a partir de ese compromiso
Para que sea 'real' ejecuta git filter-branch
Esta respuesta mejora en un par más arriba (por favor vótelos), suponiendo que además de crear un compromiso (no-padres sin historial), también desea conservar todos los datos de compromiso de ese compromiso:
Por supuesto, el commit-SHA del commit nuevo / único cambiará, ya que representa un nuevo (no) historial, convirtiéndose en un parentless / root-commit.
Esto puede hacerse 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 bifurcación de one-commit
sucursal, conservando los datos de confirmación arriba:
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 ')