web-dev-qa-db-fra.com

Mercurial: comment annuler le dernier commit non poussé?

J'ai accidentellement fait un commit dans mon référentiel local. Pour être plus précis, j'ai validé tous les changements de nombreux fichiers en même temps, alors que je voulais les valider un à un. 

Comment annuler ce commit et récupérer ma copie de travail dans l'état où il se trouvait avant le commit afin de pouvoir faire ce que j'aurais dû faire en premier lieu?

Je n'ai ni poussé ni tiré ni rien d'autre depuis le commit. 


Vous soupçonnez peut-être qu'il s'agit d'un doublon. Je vais donc expliquer pourquoi les questions suivantes sont différentes ou ne pas répondre à ma question:

Mercurial annule le dernier commit

Une réponse à celle-ci indique que vous pouvez faire cela avec hg commit --amend, mais n'explique pas comment et ne donne pas d'exemple de cette opération. L'aide mercurail ne me l'explique pas non plus.

Comment faites-vous "rollback" pour la dernière fois sur Mercurial?

Les États à utiliser hg rollback. Cette commande est apparemment obsolète, j'ai quand même essayé de l'utiliser, mais le message messge: no rollback information available. Dommage que cela ne fonctionne pas car ce serait un moyen très intuitif de réaliser ce que je veux.

30
crobar

Sur la base des informations de cette question :

hg strip --keep --rev .
--keep: do not modify working directory during strip
--rev . (le point indique le dernier commit. Lire la réponse de sid0 concernant les descendants)


Pour les personnes plus familières avec la langue git, vous recherchez git reset --mixed HEAD^ 

hard qui ignorerait vos modifications et ferait "disparaître" votre travail (je suppose que ce n'est pas une option) 

soft annulerait la validation mais conserverait les fichiers précédemment validés indexés (c'est-à-dire suivis) 

mixed conserve vos fichiers modifiés en place, mais indique à l'index d'annuler le commit. dans git-speak: git st dirais Changes not staged for commit 


Voir aussi git-reset docs , Différence git reset soft/mixed , git/hg Tableau d'équivalence de commandes

35
maosmurf

Ok, je pense avoir trouvé la réponse, activer l'activation de l'extension strip et utiliser la commande suivante:

hg strip -r -1 --keep

Cela supprime la dernière révision du repostiory (le bit -r -1) et l'option --keep signifie qu'aucune modification n'est apportée à la copie de travail. Vous vous retrouvez donc avec une copie de travail exactement telle qu'elle était juste avant la validation, sans aucune dernière validation dans le référentiel.

Je ne suis pas un expert Mercurial, utilisez-le à vos risques et périls.

24
crobar

Ce que je ferais dans cette situation serait de créer une nouvelle branche qui aurait les changements que je souhaitais avant même de penser à éliminer le mauvais ensemble de changements. Donc, dans ce cas, je devrai revenir à la révision avant de faire la validation incorrecte, de refaire mes modifications, puis de faire plusieurs validations, une pour chaque fichier.

Pas à pas:

1) Retournez à avant le mauvais commit.

% cd <top of repo>
% hg log -l 5
<identify the last good revision>
% hg update -r <last good revision number>

2) Refaites les modifications: j'obtiendrais un correctif décrivant les modifications souhaitées et l'appliquerais à l'arborescence. (Je suppose que les astuces indiquent actuellement où nous avons commencé)

% hg diff -r .:tip | patch -p1
patching file a/b/c/d
patching file a/b/e/f

3) Faites de nouveaux commits: Nous sommes maintenant de retour à l'état avant que vous ne fassiez le commit que vous vouliez séparer. Faites hg status et examinez les fichiers modifiés, assurez-vous que tout est conforme à vos attentes. À ce stade, vous pouvez soit valider les fichiers un à un en les nommant sur la ligne de commande, soit utiliser une extension telle que record ou crecord pour les sélectionner de manière interactive.

% hg commit a/b/c/d
% hg commit a/b/e/f

...ou...

% hg crecord
<select files in UI>
% hg crecord
<select files in UI>

Vous allez vous retrouver avec un dépôt qui ressemble à ceci:

o----o----B
      \
       \
        --o----o----o----T

Où B est l'ancien mauvais commit, et T est le nouveau conseil du repo. Si vous voulez ensuite que cette branche soit fermée, afin qu'elle n'apparaisse pas dans les journaux, etc., vous pouvez ...

% hg update -r <revision B>
% hg commit --close_branch
% hg update -r tip

Si vous voulez l'enlever complètement, vous pouvez le dépouiller.

% hg strip -r <revision B>

Dans tous les cas, votre journal n'aura l'air de rien.

1
Paul S

commenter et élaborer sur le post de @ crobar # nombre de caractères ne suffit pas.

lorsqu’il effectue une validation locale (pas de Push), puis exécute hg strip -r -1 --keep, il supprime votre validation précédente ET préserve votre liste de fichiers en attente de validation. fondamentalement, c’est une annulation complète . si j’utilise hg stripe -r -1 sans le --keep, il supprime tout de même votre commit précédent MAIS lorsque j’essaie d’énumérer les fichiers à valider, il ne peut pas trouver de changement, je ne le recommanderais donc pas.

si je fais un commit puis fais un Push (à distance) puis un hg strip -r -1 --keep, il fait exactement ce qu'il est censé faire MAIS quand vous faites un autre commit puis Push, il crée une autre branche. 

I.E. 

o----o----Branch(local)
      \
       \
        --o----o----o----Branch(with previous Push)

ma source/référence: tester ces scénarios