Pregunta

    

Esta pregunta ya tiene una respuesta aquí:

         

Con git rebase --interactive <commit> se puede aplastar cualquier número de confirmaciones juntos en una sola.

Eso es todo lo grande a menos que desee calabaza compromete a cometer el inicial. Eso parece imposible de hacer.

¿Existe alguna forma de lograrlo?


Moderadamente relacionados:

En una pregunta relacionada, me las arreglé para llegar a un enfoque diferente a la necesidad de aplastar contra el primer compromiso, que es, también, para que sea la segunda.

Si está interesado: git:? cómo insertar un cometen como la primera, cambiando todos los demás

¿Fue útil?

Solución

Actualización de julio de 2012 ( Git 1.7.12 + )

Ahora puede rebasar todas las confirmaciones hasta la raíz, y seleccione el segundo Y comprometerse a ser aplastado con la primera X.

git rebase -i --root master

pick sha1 X
squash sha1 Y
pick sha1 Z
git rebase [-i] --root $tip
     

Este comando se puede utilizar ahora para reescribir toda la historia que va desde "$tip" hasta la raíz de comprometerse.

cometer df5df20c1308f936ea542c86df1e9c6974168472 en GitHub de Chris Webb (arachsys) .


Respuesta original (febrero de 2009)

Creo que va a encontrar diferentes recetas para que en la pregunta SO " ¿Cómo combino las dos primeras confirmaciones de un repositorio git? "

Charles Bailey siempre que exista el más detallada respuesta , que nos recuerda que un commit es un árbol por completo (no sólo diffs desde unos estados anteriores).
Y aquí el viejo se comprometen (el "Commit Inicial") y el nuevo commit (resultado del aplastamiento) no tendrá ningún antepasado común.
Eso significa que no puede "commit --amend" la inicial comprometerse en uno nuevo, y luego se rebase en el nuevo inicial comprometen la historia de la primera confirmación anterior (un montón de conflictos)

(Esa última frase ya no es así con git rebase -i --root <aBranch> es)

En lugar (con A el original "inicial cometer", y B un posterior cometer necesaria para ser aplastado en el inicial):

  1. volver a la última confirmación de que queremos formar el primer commit (separar HEAD):

    git checkout <sha1_for_B>
    
  2. Restablecer el puntero rama de cometer el inicial, pero dejando el índice y el árbol de trabajo intactos:

    git reset --soft <sha1_for_A>
    
  3. Modificar el árbol inicial utilizando el árbol de 'B':

    git commit --amend
    
  4. Temporalmente etiquetar esta nueva inicial comprometerse (o usted podría recordar la nueva sha1 confirmación manualmente):

    git tag tmp
    
  5. Volver a la rama original (asumir maestro para este ejemplo):

    git checkout master
    
  6. Replay todas las confirmaciones después de que B en la nueva inicial se comprometen:

    git rebase --onto tmp <sha1_for_B>
    
  7. Eliminar la etiqueta temporal:

    git tag -d tmp
    

De esta manera, el "rebase --onto" no introduce conflictos durante la fusión, ya que rebasa la historia hechas después de la última confirmación (B) para ser aplastado en la inicial (que era A) a tmp (que representa cometer el aplastado nueva inicial): trivial avance rápido se funde solamente.

Esto funciona para "A-B", sino también "A-...-...-...-B" (cualquier número de confirmaciones puede ser aplastado en la inicial de esta manera)

Otros consejos

He vuelto a trabajar el guión de VonC que hacer todo de forma automática y no me pide nada. Se le da dos cometer SHA1s y va a aplastar todo lo que entre en una sola commit denomina "historia aplastado":

#!/bin/sh
# Go back to the last commit that we want
# to form the initial commit (detach HEAD)
git checkout $2

# reset the branch pointer to the initial commit (= $1),
# but leaving the index and working tree intact.
git reset --soft $1

# amend the initial tree using the tree from $2
git commit --amend -m "squashed history"

# remember the new commit sha1
TARGET=`git rev-list HEAD --max-count=1`

# go back to the original branch (assume master for this example)
git checkout master

# Replay all the commits after $2 onto the new initial commit
git rebase --onto $TARGET $2

Por lo que vale, evito este problema creando siempre un "no-op" primera comprometerse, en el que la única cosa en el repositorio es un .gitignore vacío:

https://github.com/DarwinAwardWinner/ git-custom-comandos / burbuja / maestro / bin / git-MyInit

De esa manera, nunca hay ninguna razón para meterse con el primer comprometerse.

Si usted simplemente quiere aplastar todas las confirmaciones en un único, inicial cometió, simplemente restablecer el repositorio y enmendar la primera comprometerse:

git reset hash-of-first-commit
git add -A
git commit --amend

Restablecer Git saldrá del árbol de trabajo intacto, por lo que todo está todavía allí. Así que sólo tiene que añadir los archivos mediante comandos git add, y enmendar el primer comprometen con estos cambios. En comparación con rebase -i si no se pierden la capacidad de fusionar los comentarios git sin embargo.

Esto aplastar segundo comprometerse en la primera:

A-B-C-... -> AB-C-...

git filter-branch --commit-filter '
    if [ "$GIT_COMMIT" = <sha1ofA> ];
    then
        skip_commit "$@";
    else
        git commit-tree "$@";
    fi
' HEAD

Commit mensaje para AB se tomará de B (aunque yo prefiero de A).

Tiene el mismo efecto que la respuesta de Uwe Kleine-König, pero funciona para no inicial A, así.

Aplastamiento la primera y segunda cometer resultaría en la primera commit ser reescrito. Si usted tiene más de una rama que se basa fuera de la primera cometer, que había cortado esa rama.

Considere el siguiente ejemplo:

a---b---HEAD
 \
  \
   '---d

Aplastamiento a y b en una nueva cometer "ab" resultaría en dos árboles distintos que en la mayoría de los casos no es deseable desde git-merge y git-rebase ya no trabajar a través de las dos ramas.

ab---HEAD

a---d

Si realmente quieres esto, se puede hacer. Echar un vistazo a git-filter-branch para una herramienta de gran alcance (y peligroso) para reescribir la historia.

Puede utilizar git filter-branch para eso. por ejemplo.

git filter-branch --parent-filter \
'if test $GIT_COMMIT != <sha1ofB>; then cat; fi'

Esto resulta en AB-C tirar el registro de cometer de A.

Se puede usar rebase interactivo para modificar las dos últimas confirmaciones antes de que hayan sido empujados a una distancia

git rebase HEAD^^ -i

Hay una manera más fácil de hacer esto. Vamos a suponer que usted está en la rama master

Crea una nueva rama huérfanos que eliminará todo el historial de cometer:

$ git checkout --orphan new_branch

Añadir su inicial cometer mensaje:

$ git commit -a

Se puede olvidarse de la vieja rama principal sin combinar:

$ git branch -D master

Cambiar el nombre de su new_branch rama actual a master:

$ git branch -m master
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top