Question

Quelqu'un sait-il comment annuler facilement une rebase git?

Le seul moyen qui me vienne à l’esprit est d’y aller manuellement:

  • git checkout le parent engagé dans les deux branches
  • puis créez une branche temporaire à partir de là
  • sélectionnez tous les commits à la main
  • remplace la branche dans laquelle j'ai rebasé par la branche créée manuellement

Dans ma situation actuelle, ça va marcher car je peux facilement repérer les commits des deux branches (l’une était pour moi, l’autre était pour mon collègue).

Cependant, mon approche me semble suboptimale et sujette aux erreurs (disons que je venais de changer de base avec 2 de mes propres branches).

Des idées?

Clarification: je parle d’une refonte au cours de laquelle plusieurs commits ont été rejoués. Pas un seul.

Était-ce utile?

La solution

Le moyen le plus simple serait de trouver le commit en-tête de la branche tel qu'il était juste avant le démarrage de la base dans la reflog ... ...

git reflog

et de réinitialiser la branche actuelle sur celle-ci (avec les mises en garde habituelles concernant la certitude absolue avant de procéder à la réinitialisation avec l'option --hard).

Supposons que l'ancien commit était HEAD@{5} dans le journal de référence:

git reset --hard HEAD@{5}

Sous Windows, vous devrez peut-être citer la référence:

git reset --hard "HEAD@{5}"

Vous pouvez consulter l'historique de l'ancien candidat en effectuant simplement une git log HEAD@{5} ( Windows: git log "HEAD@{5}").

Si vous n’avez pas désactivé les modifications de branche par branche, vous devriez pouvoir effectuer git reflog branchname@{1} simplement une rebase qui détache la tête de la branche avant de la rattacher à la tête finale. Je revérifierais ceci, bien que je ne l’aie pas vérifié récemment.

Par défaut, tous les reflogs sont activés pour les référentiels non-nus:

[core]
    logAllRefUpdates = true

Autres conseils

En fait, rebase enregistre votre point de départ sur ORIG_HEAD, ce qui est généralement aussi simple que:

git reset --hard ORIG_HEAD

Cependant, reset, rebase et merge enregistrent tous votre HEAD pointeur d'origine dans <=>, donc, si vous avez exécuté l'une de ces commandes depuis le changement de base que vous essayez d'annuler, vous devrez utiliser le reflog.

La réponse de Charles fonctionne, mais vous voudrez peut-être faire ceci:

git rebase --abort

à nettoyer après le reset.

Sinon, vous pourriez recevoir le message & # 8220; Interactive rebase already started & # 8221;.

git reflog vous montrera toutes les modifications avant et après la modification de la base, et vous permettra de trouver la bonne à réinitialiser. Mais je suis surpris que personne ne mentionne encore cette manière super simple:

Rebase laisse l'ancien état comme ORIG_HEAD, vous pouvez donc rétablir le dernier rebase en exécutant:

git reset --hard ORIG_HEAD

Réinitialiser la branche sur l’objet de validation suspendu de son ancien conseil est bien sûr la meilleure solution, car elle restaure l’état précédent sans aucun effort. Mais si vous avez perdu ces commits (par exemple parce que vous avez collecté votre référentiel dans l'intervalle, ou s'il s'agit d'un nouveau clone), vous pouvez toujours rebaser la branche. La clé de ceci est le --onto commutateur.

Supposons que & # 8217; s dis que vous aviez une branche de sujet appelée de manière imaginative topic, que vous aviez ramifiée master lorsque la pointe de 0deadbeef était la validation git rebase master. À un moment donné sur la branche <=>, vous l’avez fait <=>. Maintenant, vous voulez annuler cela. Voici comment & # 8217;

git rebase --onto 0deadbeef master topic

Ceci prendra tous les commits sur <=> qui ne sont pas & # 8217; t sur <=> et les rejouer au-dessus de <=>.

Avec <=>, vous pouvez réorganiser votre historique pour créer à peu près n'importe quelle forme .

Amusez-vous. : -)

En fait, j'ai placé une balise de sauvegarde sur la branche avant d'effectuer toute opération non triviale (la plupart des rebases sont triviales, mais je le ferais si elles avaient l'air complexes).

Ensuite, la restauration est aussi simple que git reset --hard BACKUP.

Dans le cas où vous aviez transféré votre branche vers un référentiel distant (généralement son origine), vous avez ensuite procédé à une nouvelle base réussie (sans fusion) (git rebase --abort donne & "Aucune base". en cours ") vous pouvez facilement réinitialiser la branche à l'aide de commande:

  

git reset --hard origin / {branchName}

Exemple:

$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is ahead of 'origin/{branchName}' by 135 commits.
  (use "git push" to publish your local commits)

nothing to commit, working directory clean

$ ~/work/projects/{ProjectName} $ git reset --hard origin/{branchName}
HEAD is now at 6df5719 "Commit message".

$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is up-to-date with 'origin/{branchName}.

nothing to commit, working directory clean

Dans le cas où vous n'avez pas terminé la réabonnement et au milieu de celui-ci, les travaux suivants:

git rebase --abort

L'utilisation de reflog n'a pas fonctionné pour moi.

Ce qui a fonctionné pour moi était semblable à celui décrit ici . Ouvrez le fichier dans .git / logs / refs nommés d'après la branche qui a été rebasée et recherchez la ligne contenant & "; Rebase finsihed &"; Quelque chose comme:

5fce6b51 88552c8f Kris Leech <me@example.com> 1329744625 +0000  rebase finished: refs/heads/integrate onto 9e460878

Checkout le deuxième commit répertorié sur la ligne.

git checkout 88552c8f

Une fois confirmé le contenu de mes modifications perdues, j'ai ramifié et poussé un soupir de soulagement.

git log
git checkout -b lost_changes

Pour les validations multiples, rappelez-vous que toute validation renvoie à tout l'historique ayant conduit à cette validation. Donc, dans la réponse de Charles, lisez & "L'ancien commit &"; comme " le plus récent de l’ancien commet " ;. Si vous réinitialisez ce commit, toute l'historique ayant conduit à ce commit réapparaîtra. Cela devrait faire ce que vous voulez.

Suite à la solution de @Allan et @Zearin, j'aimerais pouvoir simplement 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 faire git rebase --abort ( sans le -i ). .

L’utilisation simultanée de -i et --abort oblige Git à afficher une liste de ses utilisations / options.

Mon statut de succursale précédent et actuel avec cette solution est donc:

matbhz@myPc /my/project/environment (branch-123|REBASE-i)
$ git rebase --abort

matbhz@myPc /my/project/environment (branch-123)
$

Si vous réussissez à rebaser votre base contre une branche distante et que vous ne pouvez pas git rebase --abort, vous pouvez toujours effectuer quelques astuces pour enregistrer votre travail et ne pas forcer. Supposons que votre branche actuelle rebasée par erreur s'appelle your-branch et suit origin/your-branch

.
  • git branch -m your-branch-rebased # renommer la branche actuelle
  • git checkout origin/your-branch # extraire au dernier état connu de l'origine
  • git checkout -b your-branch
  • vérifiez git log your-branch-rebased, comparez avec git log your-branch et définissez les validations manquantes dans git cherry-pick COMMIT_HASH
  • your-branch-rebased pour chaque commit dans remote/your-branch
  • poussez vos modifications. Veuillez noter que deux branches locales sont associées à <=> et que vous ne devez pousser que <=>

Disons que je rebase maître sur ma branche de fonctionnalité et que je reçois 30 nouveaux commits qui cassent quelque chose. J'ai trouvé qu'il est souvent plus facile de supprimer les mauvais commits.

git rebase -i HEAD~31

Réplication 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 " choisissez " ;. Maintenant, les commits sont supprimés, ce qui annule la nouvelle base (si vous ne supprimez que les commits que vous venez de recevoir lors de la nouvelle base).

Si vous êtes sur une branche, vous pouvez utiliser:

git reset --hard @{1}

Il n’existe pas seulement un journal de référence pour HEAD (obtenu par git reflog), il existe également des réflexions pour chaque branche (obtenu par git reflog <branch>). Donc, si vous êtes sur master, alors git reflog master listera toutes les modifications apportées à cette branche. Vous pouvez faire référence à ces modifications par master@{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 actuelle , donc il est égal à git reset --hard ORIG_HEAD si vous êtes sur git reset.

rebase ne fonctionnera pas si vous avez utilisé <=> lors d'une session interactive <=>.

Pour les débutants / ceux qui ont trop peur d'effectuer une réinitialisation matérielle, vous pouvez extraire le commit du compte de reflog, puis l'enregistrer en tant que nouvelle branche.

git reflog

Recherchez le commit juste avant de commencer à rebaser. Vous devrez peut-être faire défiler l'écran plus bas pour le trouver (appuyez sur Entrée ou sur Page suivante). Prenez note du numéro HEAD et remplacez 57:

git checkout HEAD@{57}

Vérifiez la branche / les validations. Si cela semble bon, créez une nouvelle branche à l'aide de ce HEAD:

git checkout -b new_branch_name

git reset --hard origin / {branchName}

est la bonne solution pour réinitialiser tous vos changements locaux effectués par rebase.

Ce que je fais habituellement, c'est git reset #commit_hash

jusqu'au dernier commit où je pense que rebase n'a eu aucun effet.

alors git pull

Votre branche doit maintenant correspondre exactement à celle des commits principaux. Les commits rebasés ne doivent pas y figurer.

Vous pouvez maintenant sélectionner les commits sur cette branche.

Si vous gâchez quelque chose dans un rebase git, par exemple. git rebase --abort, tant que vous avez des fichiers non validés, ils seront perdus et git reflog ne vous aideront pas. Cela m'est arrivé et vous devrez sortir des sentiers battus ici. Si vous êtes chanceux comme moi et utilisez IntelliJ Webstorm, vous pouvez right-click->local history et revenir à un état antérieur de votre fichier / dossier, quelles que soient les erreurs que vous avez commises avec le logiciel de gestion de versions. Il est toujours bon d’avoir une autre sécurité en fonctionnement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top