Git: Erreur "Impossible de" squash "sans validation préalable" lors du rebase

96

J'ai ce qui suit dans le texte de la tâche 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 de choisir le second en ajoutant "s" avant 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 le faire?

Je veux écraser le premier commit ( 56bcce7) et "sélectionner et reformuler" le deuxième e43cebacommit ( )

Dawny33
la source
1
Changez HEAD ~ 2 en HEAD ~ 3 si vous voulez vraiment écraser.
ElpieKay
1
Et éventuellement utiliser --root, si HEAD ~ 2 est votre premier commit: stackoverflow.com/a/598788/2444812
Sybille Peters

Réponses:

81

Le rebase interactif présente les commits dans l'ordre inverse de celui auquel vous êtes habitué lors de l'utilisation git log. git rebase -irelit les commits sélectionnés dans l'ordre exact (de haut en bas) dans lequel ils sont répertoriés dans le fichier d'instructions de rebase enregistré. 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 le squash 56bcce7dans 684f917)
  • Si vous avez l'intention de les combiner 56bcce7avec e43cebaet e43cebaque vous n'en dépendez pas 56bcce7, réorganisez-les simplement:

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

    MISE À JOUR : La réponse de Gus ci-dessous suggère une meilleure façon de faire de même, sans réorganiser les deux commits:

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

    Cela écrasera / fusionnera les deux commits en un seul. Lorsque le rebase interactif demande un message de validation reformulé pour 56bcce7, fournissez le message de validation qui décrit l'union de 56bcce7et e43ceba.

Léon
la source
1
Je veux le squash 56bcce7 dans e43ceba. Alors, comment faire l'étape 1 ici?
Dawny33 le
83

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

C'est le groupe de commit 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 voir, je ne voulais pas. 4, mais 1, 2 et 3 n'avaient pas de commit préalable à écraser . D'où le Cannot «squash» sans une erreur de validation précédente .

Ma solution était d'utiliser l' roption pour# r, reword = use commit, but edit the commit message

Donc ma liste de commits ressemblait à 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 l'enregistrement, le shell interactif m'a demandé de reformuler le commit choisi.

Après cela, mon journal de commit a abouti à un seul commit qui a abouti à un historique de commit plus propre.

Gus
la source
2
comme moi, si vous avez une erreur parce que vous n'avez choisi aucun commit pour reformuler ou choisir et obtenir l'erreur mentionnée (sur la question), vous devrez faire git rebase --edit-todoet corriger en référant cette réponse, puis fairegit rebase --continue
old-monk
Cette réponse était concise et
pertinente
16

J'ai eu ce problème et la raison pour laquelle cela s'est produit dans mon cas était que vous ne pouvez pas écraser des commits plus anciens sur un nouveau commit. Voici un exemple disant 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 tu dis git rebase -i HEAD~3et tu fais 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

Cela entraînera l'erreur:

erreur: impossible de «squash» sans une validation précédente Vous pouvez résoudre ce problème avec «git rebase --edit-todo» puis exécutez «git rebase --continue». Ou vous pouvez abandonner le rebase avec 'git rebase --abort'.

Solution :

Lorsque vous écrasez les commits, vous devez écraser les commits récents par les anciens et non l'inverse, donc dans l'exemple, ce sera 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 bien, au cas où vous voudriez tous vos messages de validation, je suggérerais une correction au lieu de squash .

DvixExtract
la source
5
Merci - Je n'écrase pas souvent les commits et le conseil de choisir le commit le plus ancien est ce qui m'a aidé à surmonter une erreur git inutile.
0x574F4F54
2

Squash avec la logique inverse . Vous pourrez sélectionner le message de validation souhaité à l'étape ultérieure.

  • pickle premier commit pour lequel vous ne voulez pas le message de commit.
  • squashou fixuple (s) commit (s) que vous souhaitez fusionner, jusqu'à celui qui contient le message de validation que vous vouliez réellement.
pick 56bcce7 Closes #2774
squash e43ceba Lint.py: Replace deprecated link
  • confirmer le changement ( :x)
  • supprimez le (s) message (s) de commit que vous ne voulez pas et ne laissez que le message du commit 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 ✌🏽

Kamafeather
la source
1

Il sera préférable de simplement dire dans l'éditeur interactif contenant les commits, git écrase toujours de bas en haut et il faut laisser une entrée "pick" en haut pour recevoir les squashes d'en bas.

ekyu88
la source
1

J'ai juste essayé cette approche.

git log -n3

Cela afficherait les 3 derniers commits, ce qui me donnerait une idée de ce qu'est le dernier commit et de celui qui a été effectué précédemment. Maintenant déclaré rebasage,

git rebase -i HEAD ~ 3

Choisissez le dernier commit en plus duquel nous devons écraser les deux autres. L'ID de commit qui est choisi comme commit de base serait comme,

choisissez commit_id

Pour les deux autres ID de validation, changez-les en,

squash commit_id

ou simplement,

s commit_id

Tom Taylor
la source
0

J'ai aussi déjà rencontré ce problème tout à l'heure, c'est juste insouciant.vous pouvez résoudre le problème comme suit: lorsque vous essayez d'écraser le premier (56bcce7) et de choisir le second, vous devez ajouter "s" avant la deuxième ligne mais pas le premier. vous pouvez également consulter le site Web suivant: http://backlogtool.com/git-guide/en/stepup/stepup7_5.html

utilisateur8073722
la source
1
Salut ! Ce serait mieux si vous vérifiez Comment créer un exemple minimal, complet et vérifiable pour une entreprise future au débordement de pile. -Merci
Momin