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?
Oui, vous pouvez le faire en utilisant Mercurial sans aucune extension en Concatenating Changesets .
Si vous souhaitez utiliser une extension, vous pouvez également utiliser:
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
:]
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:
(from http://Mercurial-scm.org/wiki/RebaseExtension#Collapsing )
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
.
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
où 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
où 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.
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 dehg 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 parhg histedit
ougit 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 parhg histedit
ougit rebase -i
échouerait.
Supposons que vous vouliez écraser (unir) les 2 derniers commits.
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
Branche de réinitialisation logicielle
hg strip --keep -r 155
Valider à nouveau les modifications
hg commit -m "new commit message"
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 =
J'utilise:
hg phase --draft --force -r 267
...
hg rebase --dest 282 --source 267 --collapse
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 =