Sommaire
Le message d'erreur
Impossible de 'squash' sans un commit précédent
signifie que vous avez probablement tenté de «vous écraser vers le bas». Git écrase toujours un commit plus récent dans un commit plus ancien ou «vers le haut» comme affiché sur la liste de tâches de rebase interactive, c'est-à-dire dans un commit sur une ligne précédente. Changer la commande sur la toute première ligne de votre liste de tâches squash
produira toujours cette erreur car il n'y a rien pour le premier commit à écraser.
The Fix
Revenez d'abord à votre point de départ
$ git rebase --abort
Dis que ton histoire est
$ git log --pretty=oneline
a931ac7c808e2471b22b5bd20f0cad046b1c5d0d c
b76d157d507e819d7511132bdb5a80dd421d854f b
df239176e1a2ffac927d8b496ea00d5488481db5 a
Autrement dit, a était le premier commit, puis b et enfin c. Après avoir commis c, nous décidons d'écraser b et c ensemble:
(Remarque: l'exécution par défaut git log
achemine sa sortie vers un pageur, less
par défaut sur la plupart des plates-formes. Pour quitter le pageur et revenir à votre invite de commande, appuyez sur la q
touche.)
La course à pied git rebase --interactive HEAD~2
vous donne un éditeur avec
pick b76d157 b
pick a931ac7 c
# Rebase df23917..a931ac7 onto df23917
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
(Notez que cette liste de tâches est dans l'ordre inverse par rapport à la sortie de git log
.)
Modification de B pick
à squash
entraînera l'erreur que vous avez vu, mais si au contraire vous de squash c en b (dans le récent engagement plus ou « vers le haut squashing ») en modifiant la liste des tâches à
pick b76d157 b
squash a931ac7 c
et en sauvegardant votre éditeur, vous obtiendrez un autre éditeur dont le contenu est
# This is a combination of 2 commits.
# The first commit's message is:
b
# This is the 2nd commit message:
c
Lorsque vous enregistrez et quittez, le contenu du fichier modifié devient le message de validation du nouveau commit combiné:
$ git log --pretty=oneline
18fd73d3ce748f2a58d1b566c03dd9dafe0b6b4f b and c
df239176e1a2ffac927d8b496ea00d5488481db5 a
Remarque sur l'historique de réécriture
Le rebase interactif réécrit l'histoire. Tenter de pousser vers une télécommande contenant l'ancien historique échouera car il ne s'agit pas d'une avance rapide.
Si la branche que vous avez rebasée est une branche de sujet ou de fonctionnalité dans laquelle vous travaillez par vous - même , ce n'est pas grave. Pousser vers un autre référentiel nécessitera la--force
option, ou bien vous pourrez, selon les autorisations du référentiel distant, supprimer d'abord l'ancienne branche, puis pousser la version rebasée. Des exemples de ces commandes susceptibles de détruire le travail sont hors de portée de cette réponse.
La réécriture de l'historique déjà publié sur une branche dans laquelle vous travaillez avec d'autres personnes sans très bonne raison, comme la fuite d'un mot de passe ou d'autres détails sensibles, force le travail sur vos collaborateurs et est antisocial et ennuiera les autres développeurs. La section «Récupération à partir d'une rebase en amont» dans la git rebase
documentation explique, avec un accent supplémentaire.
Rebaptiser (ou toute autre forme de réécriture) une branche sur laquelle d'autres ont basé leur travail est une mauvaise idée: toute personne en aval est obligée de corriger manuellement son historique. Cette section explique comment effectuer la correction du point de vue en aval. La vraie solution, cependant, serait d'éviter en premier lieu de rebaser l'amont. …