183 votes

Git : Erreur "Cannot 'squash' without a previous commit" lors d'un rebase

J'ai ce qui suit dans le texte à faire de git rebase -i HEAD~2 :

pick 56bcce7 Closes #2774
pick e43ceba Lint.py: Replace deprecated link

# Rebase 684f917..e43ceba onto 684f917 (2 command(s))
#
...

Maintenant, lorsque j'essaie d'écraser le premier ( 56bcce7 ) et choisir le second en ajoutant "s" devant le premier, j'obtiens l'erreur suivante :

Cannot 'squash' without a previous commit

Quelqu'un peut-il m'expliquer ce que cela signifie et comment procéder ?

Je veux écraser le premier commit( 56bcce7 ) et "sélectionner et reformuler" la seconde ( e43ceba ) s'engager

1 votes

Remplacez HEAD~2 par HEAD~3 si vous voulez vraiment faire du squash.

3 votes

Et éventuellement utiliser --Root, si HEAD~2 est votre premier commit : stackoverflow.com/a/598788/2444812

155voto

Gus Points 133

J'ai eu un problème similaire que j'ai résolu comme suit :

C'est le groupe d'engagement que je voulais écraser :

1 s 01cc5a08 Removes open div
2 s a2b6eecf Restores old fonts
3 s 603479ff Cleans left out div
4 pick 5afdbc33 Update: show logo on landing page
5 s 04c1cb13 change version of dev and prod from 1 to 2
6 s bbe6a8f8 Update: show logo on landing page if they have one
7 s c0d6008a Adds check for C users

Comme vous pouvez le constater, je voulais le no. 4, mais les numéros 1, 2 et 3 n'avaient pas d'engagement antérieur. courge en . Par conséquent, le Impossible d'effectuer un "squash" sans un commit précédent erreur.

Ma solution a consisté à utiliser la fonction r option pour les # r, reword = use commit, but edit the commit message

Ma liste d'engagements ressemblait donc à ceci :

1 r 01cc5a08 Removes open div
2 s a2b6eecf Restores old fonts
3 s 603479ff Cleans left out div
4 s 5afdbc33 Update: show logo on landing page
5 s 04c1cb13 change version of dev and prod from 1 to 2
6 s bbe6a8f8 Update: show logo on landing page if they have one
7 s c0d6008a Adds check for C users

Après avoir sauvegardé, le shell interactif m'a demandé de reformuler le commit choisi.

Après cela, mon journal des livraisons n'a donné lieu qu'à une seule livraison, ce qui a permis de nettoyer l'historique des livraisons.

7 votes

Comme moi, si vous obtenez une erreur parce que vous n'avez pas choisi d'engagement à reformuler ou à sélectionner et que vous obtenez l'erreur mentionnée (sur la question), vous devrez faire ce qui suit git rebase --edit-todo et fixer cette réponse, puis faire git rebase --continue

1 votes

Cette réponse était concise et pertinente, elle m'a beaucoup aidé, merci.

130voto

Leon Points 20011

Le rebasement interactif présente les modifications dans l'ordre inverse de celui auquel vous êtes habitué lorsque vous utilisez la commande git log . git rebase -i rejoue les modifications sélectionnées dans l'ordre exact (de haut en bas) où elles sont listées dans le fichier d'instructions rebase sauvegardé. Lors de l'écrasement, le commit sélectionné pour l'écrasement est combiné avec le commit qui le précède dans la liste (éditée), c'est-à-dire le commit de la ligne précédente. Dans votre cas - il n'y a pas de commit précédent pour 56bcce7 . Vous devez effectuer l'une des opérations suivantes

  • git rebase -i HEAD~3 (si vous voulez écraser 56bcce7 en 684f917 )
  • Si vous souhaitez combiner 56bcce7 avec e43ceba et e43ceba ne dépend pas de 56bcce7 Il suffit alors de les réorganiser :

    r e43ceba Lint.py: Replace deprecated link
    s 56bcce7 Closes #2774

    MISE À JOUR : Réponse de Gus ci-dessous propose une meilleure façon de faire la même chose, sans réordonner les deux commits :

    r 56bcce7 Closes #2774
    s e43ceba Lint.py: Replace deprecated link

    Cela va écraser/fusionner les deux commits en un seul. Lorsque le rebasement interactif demande un message de livraison reformulé pour 56bcce7 , fournir le message de validation qui décrit l'union de 56bcce7 y e43ceba .

1 votes

Je veux écraser 56bcce7 en e43ceba . Alors, comment dois-je procéder à l'étape 1 ?

44voto

DvixExtract Points 426

J'ai eu ce problème et la raison pour laquelle cela s'est produit dans mon cas est qu'il n'est pas possible d'insérer des commits plus anciens dans un nouveau commit. Voici un exemple, disons que vous avez 3 commits :

1 pick 01mn9h78 The lastest commit
2 pick a2b6pcfr A commit before the latest
3 pick 093479uf An old commit i made a while back

Maintenant, si vous dites git rebase -i HEAD~3 et vous faites quelque chose comme

1 pick 01mn9h78 The lastest commit
2 s a2b6pcfr A commit before the latest
3 s 093479uf An old commit i made a while back

Le message d'erreur suivant s'affiche :

erreur : impossible de "squash" sans un commit précédent Vous pouvez corriger cela avec 'git rebase --edit-todo' et ensuite lancer 'git rebase --continue'. Ou vous pouvez interrompre le rebasement avec 'git rebase --abort'.

Solution :

Lorsque vous écrasez des commits, vous devez écraser les commits récents sur les anciens et non l'inverse, ce qui donne dans l'exemple quelque chose comme ceci :

1 s 01mn9h78 The lastest commit
2 s a2b6pcfr A commit before the latest
3 pick 093479uf An old commit i made a while back

Cela fonctionnera très bien, mais si vous souhaitez obtenir tous les messages de validation, je vous suggère d'utiliser la méthode suivante réparation au lieu de courge .

6 votes

Merci, je ne modifie pas souvent les commits et le conseil de choisir le commit le plus ancien est ce qui m'a aidé à surmonter une erreur de git peu utile.

1 votes

Lastest" est un mot ambigu : (1) parce qu'il ne s'agit pas d'un mot de la langue anglaise et (2) parce qu'il se trouve à une lettre de "latest", qui est un mot anglais et signifie "le plus récent". Il serait préférable d'utiliser "Oldest" plutôt que "lastest". La confusion est d'autant plus grande que vous écrasez la ligne numéro 1, ce qui entraîne une erreur - celle que le PO a mentionnée. L'ordre réel qui apparaît dans l'éditeur est du plus ancien au plus récent, à l'opposé de ce que vous décrivez.

9voto

Kamafeather Points 179

La courge avec la logique inverse . Vous pourrez sélectionner le message de validation souhaité à l'étape suivante.

  • pick le premier engagement que vous ne voulez pas le message de validation.

  • squash o fixup le(s) commit(s) que vous voulez fusionner, jusqu'à celui qui a le message de commit que vous vouliez.

    pick 56bcce7 Closes #2774 squash e43ceba Lint.py: Replace deprecated link

  • confirmer la modification ( :x )

  • supprimer le(s) message(s) de validation que vous ne voulez pas et ne laisser que le message de validation que vous désirez (dans ce cas : Lint.py: Replace deprecated link ).

  • confirmer le choix ( :x )

J'espère que c'est plus clair pour quelqu'un

7voto

ekyu88 Points 21

Il est préférable de dire dans l'éditeur interactif contenant les commits, git squash toujours de bas en haut et il faut laisser une entrée "pick" en haut pour recevoir les squashs du bas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X