586 votos

La calabaza los dos primeros se compromete en Git?

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

Todo eso es genial, a menos que usted quiere que la calabaza se compromete en la inicial cometer. Que parece imposible de hacer.

Hay alguna forma de conseguirlo?


Moderadamente relacionados:

En relación con esta pregunta, me las arreglé para llegar con un enfoque diferente a la necesidad de aplastar contra el primer commit, que es, bueno, para hacer el segundo.

Si usted está interesado: git: cómo insertar un commit como la primera, el cambio de todas las demás?

804voto

VonC Puntos 414372

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

Ahora, usted puede reajustar todos los envíos hasta la raíz, y seleccione el segundo cometer Y a ser aplastado con la primera X.

git rebase -i --root master

pick sha1 X
squash sha1Y Y
pick sha1 Z

git rebase [-i] --root $tip

ahora se puede usar para reescribir toda la historia que lleva a "$tip", abajo a la raíz.

Ver cometer df5df20c1308f936ea542c86df1e9c6974168472 de Chris Webb (arachsys).


Respuesta Original (febrero de 2009)

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

Charles Bailey siempre que haya la más detallada respuesta, recordándonos que la confirmación es un completo árbol (no sólo de las diferencias a partir de un estado anterior).
Y aquí, el viejo commit (el "inicial commit") y el nuevo commit (resultado del aplastamiento) no tendrá ningún ancestro común.
Eso significa que usted no puede "commit --amend" la inicial de comprometerse en una nueva, y luego de reajuste a la nueva inicial de cometer la historia de la inicial previa confirmación (un montón de conflictos)

(La última frase no es cierto con git rebase -i --root <aBranch>)

Lugar (con A la original "inicial cometer", y B de la posterior cometer necesarios para ser aplastado dentro de la inicial):

  1. Volver al último commit que queremos formar el inicial commit (separar la HEAD):

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

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

    git commit --amend
    
  4. Temporalmente etiqueta de esta nueva inicial cometer (o podría recordar el nuevo commit sha1 manualmente):

    git tag tmp
    
  5. Volver a la original de la subdivisión de asumir maestro para este ejemplo):

    git checkout master
    
  6. Reproducción de todos los commits después de B en la nueva inicial comprometen a:

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

    git tag -d tmp
    

De esa manera, el "rebase --onto" no presentar conflictos durante la mezcla, ya que se reajusta de la historia hecha después de que el último commit (B) para ser aplastado en la inicial (la que estaba A) tmp (que representa a la aplastado nueva inicial commit): trivial de avance rápido combina sólo.

Que trabaja para "A-B", pero también "A-...-...-...-B" (cualquier número de confirmaciones pueden ser aplastado en la primera de esta manera)

30voto

fonsinchen Puntos 201

He reelaborado VonC la secuencia de comandos para hacerlo todo de forma automática y no me piden nada. Se dan dos cometer SHA1s y calabaza todo lo que entre en un commit denominado "aplastada la historia":

#!/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

22voto

Ryan Thompson Puntos 7501

Para lo que vale, debo evitar este problema mediante la creación de un "no-op" primer commit, en el que la única cosa en el repositorio es un vacío .gitignore:

https://github.com/DarwinAwardWinner/git-custom-commands/blob/master/bin/git-myinit

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

5voto

Antony Hatchkins Puntos 5831

Esta calabaza segundo cometer 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

Mensaje de la confirmación para AB será tomada de B (aunque yo preferiría a partir de Una).

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

3voto

hillu Puntos 4033

Aplastamiento de la primera y la segunda cometer sería el resultado en el primer commit siendo reescrito. Si usted tiene más de una sucursal que está basada en el primer commit, tendría que cortar esa rama.

Considere el siguiente ejemplo:

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

Aplastar a y b en un nuevo commit "ab", el resultado sería en dos distintos árboles que en la mayoría de los casos no es deseable desde git-mezcla y git rebase dejará de funcionar a través de las dos ramas.

ab---HEAD

a---d

Si usted realmente quiere este, se puede hacer. Eche un vistazo a git-filtro-de la rama de un poderoso (y peligroso) de la herramienta para la reescritura de la historia.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X