web-dev-qa-db-fra.com

Puis-je écraser les commits dans Mercurial?

J'ai deux commits qui ne devraient en être qu'un. Si j'utilisais git, j'utiliserais:

git rebase -i <some-commit-before>

et ensuite les écraser.

Puis-je faire cela dans Mercurial? Si c'est le cas, comment?

99

Oui, vous pouvez le faire en utilisant Mercurial sans aucune extension en Concatenating Changesets .

Si vous souhaitez utiliser une extension, vous pouvez également utiliser:

85
Ry4an Brase

Mon préféré est la commande hg strip --keep. Et puis je commets toutes les modifications en une seule.

C’est le moyen le plus rapide et le plus confortable pour moi, car j’aime faire beaucoup de petits commits au cours de mon travail quotidien;)


Remarque 1: strip a besoin d'une extension intégrée mq pour être activé.
Remarque 2: Mon client Git/Mercurial préféré (SmartGit/Hg) ajoute par défaut le paramètre --keep pendant la strip. Et ce qui est encore plus pratique: il fournit une option appelée join commits:]

38
G. Demecki

L'extension Rebase a fonctionné comme un charme. Pour écraser 2 commits:

$ hg rebase --dest .~2 --base . --collapse

Le point est un raccourci pour la révision en cours.

C'est encore plus facile quand vous avez quelques commits sur une branche et que vous voulez tous les réduire en un seul:

$ hg rebase --dest {destination branch (e.g. master)} --base . --collapse

Comment ça marche:

enter image description here

(from http://Mercurial-scm.org/wiki/RebaseExtension#Collapsing )

28
Martin Konicek

Si vous lisez cette réponse, vous pouvez oublier toutes les autres options mentionné dans cette réponse et utilisez la commande fold à partir de evolve extension .

evolve est une extension de Mercurial qui nous aide à avoir un historique mutable sûr, mais il est toujours expérimental. Vous pouvez l'utiliser en le clonant depuis son repo et en l'ajoutant dans votre .hgrc comme ceci.

[extensions]
evolve = ~/evolve/hgext/evolve.py

En supposant que vous avez cloné, faites évoluer le référentiel dans votre répertoire personnel. Maintenant vous êtes prêt à partir. Vous pouvez également chercher de l'aide par hg help fold.

Commande Plier

Vous dites à fold d’écraser/de plier une chaîne linéaire d’engagements qui n’est pas rompue. Ce qui se plie, c’est qu’il crée un nouveau jeu de modifications qui contient les modifications de tous les jeux de modifications et marque tous les commits comme obsolètes. Vous pouvez avoir une vue plus profonde de ceci dans docs .

Supposons maintenant que vous avez l'historique suivant.

a -> b -> c -> d -> e -> f -> g

Vous voulez écraser e, f et g. Tu peux faire

hg up g
hg fold -r e

Le résultat sera

a -> b -> c -> d -> h

h est le jeu de modifications qui contient les modifications des trois commits e, f et g.

Vous pouvez également plier les changesets à partir du milieu de l’histoire, c’est-à-dire que vous ne devez pas nécessairement choisir une chaîne qui inclut la pointe. Supposons que vous souhaitiez plier b, c et d. Tu peux faire

hg up d
hg fold -r b
hg evolve --all

Cela se traduira par

a -> i -> j

i est l'ensemble de modifications plié de b, c, d et j est le même ensemble de modifications que h. Evolve user guide est une lecture obligatoire.

9
Pulkit Goyal

Avec Mercurial 4.8 (nov. 2018, 9 ans plus tard), vous pouviez envisager la nouvelle commande hg aborb (il s'agissait d'une fonctionnalité expérimentale avant de ).

Voir " Absorbing Commit Changes in Mercurial 4.8 ".

L'extension absorbera chaque modification dans votre répertoire de travail, déterminera le commet de votre série qui a modifié cette ligne et modifiera automatiquement la modification en conséquence.
En cas d’ambiguïté (par exemple, plusieurs commits ont été modifiés sur la même ligne), absorber ignorera simplement cette modification et la laissera dans votre répertoire de travail pour qu’elle soit résolue manuellement.

Au niveau technique, hg absorb recherche toutes les modifications non validées et tente de mapper chaque ligne modifiée à une validation antérieure non ambiguë.
Pour chaque changement qui peut être mappé proprement, les changements non validés sont absorbés dans le commit précédent approprié. Les commits impactés par l'opération sont automatiquement rebasés.
Si une modification ne peut pas être mappée sur une validation antérieure non ambiguë, elle est laissée non validée et les utilisateurs peuvent revenir à un flux de travail existant (par exemple, à l'aide de hg histedit).

La logique de réécriture automatique de hg absorb est implémentée en suivant l'historique des lignes: Ceci est fondamentalement différent de l'approche adoptée par hg histedit ou git rebase, qui ont tendance à s'appuyer sur des stratégies de fusion basées sur le Fusion à 3 voies pour dériver une nouvelle version d'un fichier à partir de plusieurs versions d'entrée.

Cette approche, combinée au fait que hg absorbe les sauts par-dessus les modifications avec une application ambiguë signifie que l'absorption de hg ne rencontrera jamais de conflits de fusion!

Maintenant, vous pensez peut-être que si vous ignorez les lignes avec des cibles d'application ambiguës, le correctif s'appliquerait toujours proprement en utilisant une fusion classique à 3 voies. Cette déclaration semble logiquement correcte. Mais ce n’est pas le cas: hg absorb peut éviter les conflits de fusion lorsque la fusion effectuée par hg histedit ou git rebase -i échouerait.

1
VonC

Supposons que vous vouliez écraser (unir) les 2 derniers commits.

  1. Trouver un numéro de révision

    hg log -G -l 3
    

    sortie possible:

    @  changeset:   156:a922d923cf6f
    |  branch:      default
    |  tag:         tip
    |  user:        naXa!
    |  date:        Thu Dec 13 15:45:58 2018 +0300
    |  summary:     commit message 3
    |
    o  changeset:   155:5feb73422486
    |  branch:      default
    |  user:        naXa!
    |  date:        Thu Dec 13 15:22:15 2018 +0300
    |  summary:     commit message 2
    |
    o  changeset:   154:2e490482bd75
    |  branch:      default
    ~  user:        naXa!
       date:        Thu Dec 13 03:28:27 2018 +0300
       summary:     commit message 1
    
  2. Branche de réinitialisation logicielle

    hg strip --keep -r 155
    
  3. Valider à nouveau les modifications

    hg commit -m "new commit message"
    

Remarques

strip nécessite l'activation d'une extension intégrée. Créez/éditez le fichier de configuration ~/.hgrc avec le contenu suivant:

[extensions]
strip = 
1
naXa

J'utilise:

hg phase --draft --force -r 267
...
hg rebase --dest 282 --source 267 --collapse
0
sasha-ch

Je pense que chistedit (intégré depuis Mercurial 2.3) est le plus proche de rebase -i qui est pur Mercurial (chistedit est la version interactive de histedit). Une fois dans histedit, la commande fold est mappée sur les commandes squash et roll de Rebase mappée sur fixup de ReBase. Voir histedit docs pour plus d’informations.

Voici un exemple simple. Supposons que vous ayez les éléments suivants et que vous souhaitez déplacer toutes les modifications de 1e21c4b1 dans la révision précédente tout en conservant le message de la révision précédente. 

@  1e21c4b1 drees tip
|  A commit you want to squash
o  b4a738a4 drees
|  A commit
o  788aa028 drees
|  Older stuff

Vous pouvez exécuter hg chistedit -r b4a738a4 pour modifier l'historique en b4a738a4. Dans chistedit, placez ensuite le curseur sur 1e21c4b1 et appuyez sur r pour indiquer que vous souhaitez lancer cette révision. Notez que l'ordre dans histedit (du plus ancien au plus récent) est inversé de hg log (du plus récent au plus ancien).

#0  pick   160:b4a738a49916   A commit
#1  ^roll  161:1e21c4b1500c

Après avoir choisi vos modifications, vous choisissez c pour les valider. Le résultat est le suivant:

@ bfa4a3be drees tip | Un commit O 788aa028 drees |. Trucs plus vieux

Si vous êtes relativement nouveau pour eux, alors histedit peut être un meilleur choix que chistedit car il fournit les descriptions de commande dans le fichier histedit pour référence. Il faut juste un peu plus d’édition pour définir les commandes en utilisant l’édition de texte normale (comme pour une base normale).

Notez que pour utiliser histedit ou chistedit, vous devez ajouter histedit à vos extensions dans votre ~/.hgrc:

[extensions]
histedit =

J'ai suggéré chistedit car il est plus proche de rebase -i et fonctionne n'importe où dans l'historique. Si vous voulez simplement subsume/Tweak la révision actuelle dans la précédente puis @G. La suggestion de strip de Demecki peut être bonne, car ce qui se passe est clair. Il est intégré depuis Mercuria 2.8. Pour obtenir les résultats équivalents ci-dessus, vous pouvez procéder comme suit:

hg strip .
hg add
hg commit --amend

Remarque strip, comme histedit, doit être activé dans votre ~/.hgrc:

[extensions]
strip =
0
studgeek