Comment puis-je facilement annuler une modification de git?
Mes idées actuelles ne sont que des approches manuelles:
git checkout
sur le parent de validation sur les deux branches- Créez une branche temporaire à partir de là
git cherry-pick
tout s'engage à la main- remplacer la branche dans laquelle j'ai rebasé par la branche créée manuellement
Dans ma situation actuelle, cela fonctionnerait parce que je peux facilement repérer les commits des deux branches (l'une était mon affaire, l'autre était celle de mon collègue).
Cependant, mon approche me semble sous-optimale et sujette aux erreurs (disons que je venais de rebaser avec 2 de mes propres branches).
Clarification : je parle d'un rebase pendant lequel un tas de commits ont été rejoués. Non seulement un.
git
rebase
git-rebase
undo
webmat
la source
la source
Réponses:
Le moyen le plus simple serait de trouver le commit principal de la branche tel qu'il était juste avant le rebase dans le reflog ...
et de réinitialiser la branche actuelle (avec les mises en garde habituelles d'être absolument sûr avant de réinitialiser avec l'
--hard
option).Supposons que l'ancien commit était
HEAD@{5}
dans le journal de référence:Sous Windows, vous devrez peut-être citer la référence:
Vous pouvez vérifier l'historique de l'ancienne tête du candidat en faisant simplement un
git log HEAD@{5}
( Windows:)git log "HEAD@{5}"
.Si vous n'avez pas désactivé les reflogs par branche, vous devriez pouvoir le faire simplement
git reflog branchname@{1}
car un rebase détache la tête de branche avant de se reconnecter à la tête finale. Je revérifierais ceci, bien que je ne l'ai pas vérifié récemment.Par défaut, tous les reflogs sont activés pour les référentiels non nus:
la source
git log -g
(astuce de progit.org/book de Scott Chacon ).git rebase --abort
(-i
n'a aucun sens avec--abort
) sert à abandonner un rebase qui n'a pas été terminé - soit parce qu'il y avait des conflits, soit parce qu'il était interactif ou les deux; il ne s'agit pas d'annuler un rebasage réussi, c'est de cela qu'il s'agit. Vous utiliseriezrebase --abort
oureset --hard
selon la situation dans laquelle vous vous trouviez. Vous ne devriez pas avoir besoin de faire les deux.git tag BACKUP
. Vous pouvez y revenir en cas de problème:git reset --hard BACKUP
commit:
derebase:
. Cela semble évident, mais cela m'a un peu dérouté.git reset --hard ORIG_HEAD
l'affaire aussi bien immédiatement après le rebase accidentel?En fait, rebase enregistre votre point de départ
ORIG_HEAD
, c'est donc généralement aussi simple que:Cependant, le
reset
,rebase
etmerge
tous enregistrent votreHEAD
pointeur d' origine dansORIG_HEAD
ainsi, si vous avez exécuté l'une de ces commandes depuis le rebase que vous essayez d'annuler, vous devrez utiliser le reflog.la source
ORIG_HEAD
n'est plus utile, vous pouvez également utiliser labranchName@{n}
syntaxe, oùn
est la nième position antérieure du pointeur de branche. Ainsi, par exemple, si vous rebasez unefeatureA
branche sur votremaster
branche, mais que vous n'aimez pas le résultat de la rebase, vous pouvez simplement fairegit reset --hard featureA@{1}
pour réinitialiser la branche exactement à l'endroit où elle se trouvait avant de rebaser. Vous pouvez en savoir plus sur la syntaxe branch @ {n} dans les documents officiels de Git pour les révisions .git rebase --abort
bien.git 2.17.0
.git reset --hard ORIG_HEAD
peut utiliser à plusieurs reprises pour revenir en arrière encore et encore. Dites, si A --- rebase à --- B --- rebase à --- C, maintenant je suis à C, je peux revenir à A en utilisant deux foisgit reset --hard ORIG_HEAD
git rebase --abort
?La réponse de Charles fonctionne, mais vous voudrez peut-être faire ceci:
nettoyer après le
reset
.Sinon, vous pouvez obtenir le message «
Interactive rebase already started
».la source
La réinitialisation de la branche à l'objet de validation pendant de son ancienne astuce est bien sûr la meilleure solution, car elle restaure l'état précédent sans aucun effort. Mais si vous avez perdu ces validations (par exemple, parce que vous avez récupéré votre référentiel entre-temps, ou s'il s'agit d'un nouveau clone), vous pouvez toujours rebaser la branche à nouveau. La clé est le
--onto
commutateur.Supposons que vous ayez une branche de sujet appelée avec imagination
topic
, que vous avez bifurquéemaster
lorsque la pointe de la commande amaster
été0deadbeef
validée. À un moment donné pendant quetopic
vous étiez sur la branche, vous l'avez faitgit rebase master
. Vous voulez maintenant annuler cela. Voici comment:Cela prendra toutes les validations
topic
qui ne sont pasmaster
activées et les rejouera par dessus0deadbeef
.Avec
--onto
, vous pouvez réorganiser votre histoire dans à peu près n'importe quelle forme .S'amuser. :-)
la source
--onto
et-i
vous pouvez réorganiser votre histoire dans à peu près n'importe quelle forme. Utilisez gitk (ou gitx sur mac) pour voir les formes que vous créez :-).En fait, j'ai mis une balise de sauvegarde sur la branche avant de faire une opération non triviale (la plupart des rebases sont triviales, mais je le ferais si cela semble complexe).
Ensuite, la restauration est aussi simple que
git reset --hard BACKUP
.la source
branchName@{n}
syntaxe, voicin
la nième position antérieure du pointeur de branche. Ainsi, par exemple, si vous rebasez unefeatureA
branche sur votremaster
branche, mais que vous n'aimez pas le résultat de la rebase, vous pouvez simplement fairegit reset --hard featureA@{1}
pour réinitialiser la branche exactement à l'endroit où elle se trouvait avant de rebaser. Vous pouvez en savoir plus sur labranch@{n}
syntaxe dans les documents officiels de Git pour les révisions .HEAD
de la branche est temporairement stocké dansORIG_HEAD
. Mais la technique d'utilisation d'une étiquette de branche de sauvegarde fonctionne également, c'est juste plus d'étapes.Dans le cas où vous aviez poussé votre branche vers un référentiel distant (généralement son origine) et que vous avez ensuite effectué un rebase réussi (sans fusion) (
git rebase --abort
donne "Pas de rebase en cours"), vous pouvez facilement réinitialiser la branche en utilisant la commande:Exemple:
la source
L'utilisation
reflog
n'a pas fonctionné pour moi.Ce qui a fonctionné pour moi était similaire à celui décrit ici . Ouvrez le fichier dans .git / logs / refs nommé d'après la branche qui a été rebasée et recherchez la ligne qui contient "rebase finsihed", quelque chose comme:
Extraire le deuxième commit répertorié sur la ligne.
Une fois confirmé, cela contenait mes changements perdus, je me suis ramifié et j'ai poussé un soupir de soulagement.
la source
Pour plusieurs validations, n'oubliez pas que toute validation fait référence à tout l'historique menant à cette validation. Ainsi, dans la réponse de Charles, lisez «l'ancien commit» comme «le plus récent des anciens commits». Si vous réinitialisez ce commit, tout l'historique menant à ce commit réapparaîtra. Cela devrait faire ce que vous voulez.
la source
Suite à la solution de @Allan et @Zearin, je souhaite simplement pouvoir faire un commentaire mais je n'ai pas assez de réputation, j'ai donc utilisé la commande suivante:
Au lieu de faire
git rebase -i --abort
(notez le -i ), je devais simplement le fairegit rebase --abort
( sans le -i ).En utilisant les deux
-i
et--abort
en même temps, Git me montre une liste d'utilisation / d'options.Mon statut de branche précédent et actuel avec cette solution est donc:
la source
Si vous avez réussi à rebaser contre une branche distante et que
git rebase --abort
vous ne pouvez pas, vous pouvez toujours faire quelques astuces pour enregistrer votre travail et ne pas avoir de push forcé. Supposons que votre branche actuelle qui a été rebasée par erreur soit appeléeyour-branch
et effectue le suiviorigin/your-branch
git branch -m your-branch-rebased
# renommer la branche actuellegit checkout origin/your-branch
# paiement vers le dernier état connu d'originegit checkout -b your-branch
git log your-branch-rebased
, comparergit log your-branch
et définir les commits manquants dansyour-branch
git cherry-pick COMMIT_HASH
pour chaque commityour-branch-rebased
remote/your-branch
et que vous ne devez pousseryour-branch
la source
Disons que je rebase master dans ma branche de fonctionnalité et que je reçois 30 nouveaux commits qui cassent quelque chose. J'ai constaté que, souvent, il est plus facile de simplement supprimer les mauvais commits.
Rebase interactive pour les 31 derniers commits (cela ne fait pas de mal si vous en choisissez beaucoup trop).
Prenez simplement les commits dont vous voulez vous débarrasser et marquez-les avec "d" au lieu de "choisir". Désormais, les validations sont supprimées, ce qui annule la réinitialisation (si vous supprimez uniquement les validations que vous venez d'obtenir lors de la réinitialisation).
la source
Pour les débutants / ceux qui ont trop peur de faire une réinitialisation matérielle, vous pouvez extraire le commit du reflog, puis l'enregistrer en tant que nouvelle branche.
Trouvez le commit juste avant de commencer le rebasage. Vous devrez peut-être faire défiler plus bas pour le trouver (appuyez sur Entrée ou PageDown). Prenez note du numéro HEAD et remplacez 57:
Passez en revue la branche / commits, si cela semble bon, créez une nouvelle branche en utilisant cette HEAD:
la source
Si vous êtes sur une succursale, vous pouvez utiliser:
Il n'y a pas seulement un journal de référence pour HEAD (obtenu par
git reflog
), il existe également des reflogs pour chaque branche (obtenu pargit reflog <branch>
). Donc, si vous êtesmaster
activégit reflog master
, la liste de toutes les modifications apportées à cette branche sera répertoriée. Vous pouvez consulter que les changements parmaster@{1}
,master@{2}
, etc.git rebase
changera généralement HEAD plusieurs fois mais la branche actuelle ne sera mise à jour qu'une seule fois.@{1}
est simplement un raccourci pour la branche en cours , il est donc égal àmaster@{1}
si vous êtes activémaster
.git reset --hard ORIG_HEAD
ne fonctionnera pas si vous l'avez utiliségit reset
lors d'une interactionrebase
.la source
Ce que je fais d'habitude c'est
git reset #commit_hash
au dernier commit où je pense que le rebase n'a eu aucun effet.
puis
git pull
Maintenant, votre branche doit correspondre exactement comme maître et les validations rebasées ne doivent pas y être.
Maintenant, on peut juste choisir les commits sur cette branche.
la source
J'ai essayé toutes les suggestions avec reset et reflog sans succès. La restauration de l'historique local d'IntelliJ a résolu le problème des fichiers perdus
la source
git reset --hard origin / {branchName}
est la bonne solution pour réinitialiser toutes vos modifications locales effectuées par rebase.
la source
origin/branch
vous risquez de perdre les modifications entre HEAD et ce point. Vous ne voulez pas cela d'une manière générale.Si vous gâchez quelque chose dans un rebase git, par exemple
git rebase --abort
, pendant que vous avez des fichiers non validés , ils seront perdus etgit reflog
ne vous aideront pas. Cela m'est arrivé et vous devrez sortir des sentiers battus ici. Si vous avez de la chance comme moi et que vous utilisez IntelliJ Webstorm, vous pouvezright-click->local history
et pouvez revenir à un état précédent de vos fichiers / dossiers, quelles que soient les erreurs que vous avez faites avec le logiciel de version. Il est toujours bon d'avoir une autre sécurité intégrée en cours d'exécution.la source
git rebase --abort
Abandonne un rebasage actif, il n'undo un rebasage. De plus, utiliser deux VCS en même temps est une mauvaise idée. C'est une fonctionnalité intéressante du logiciel Jetbrains, mais vous ne devez pas utiliser les deux. Il est préférable d'apprendre simplement Git, en particulier lorsque vous répondez à des questions sur Stack Overflow concernant Git.