web-dev-qa-db-fra.com

Comment appliquer plusieurs correctifs à l'aide de la ligne de commande hg lorsqu'il y a déjà des modifications non validées?

J'utilise la commande suivante pour appliquer un correctif dans Mercurial sans le commettre:

hg import patch.diff --no-commit

Cela fonctionne très bien, cependant, si j'essaie d'appliquer plusieurs correctifs à la fois, comme ceci:

hg import patch1.diff --no-commit
hg import patch2.diff --no-commit
...

Je reçois ce message d'erreur après la deuxième validation:

abort: uncommitted changes

Si je fais exactement la même chose dans SourceTree (appliquer le patch1, puis le patch2 et choisir "Modifier les fichiers de la copie de travail"), cela fonctionne: les deux patchs sont appliqués sur la copie de travail, les modifications apportées aux patch1 et patch2 sont combinées/repliées.

Comment faire la même chose en utilisant la ligne de commande hg?

14
tigrou

C’est ce comportement qui a été conçu par les auteurs de Mercurial: imaginez que vous ayez "manuellement" apporté des modifications non validées à une copie de travail, nous ne voudrions pas que hg import applique automatiquement le correctif, et validera à la fois vos modifications et les modifications du correctif. enregistrer le message et les deux modifications empêtrées ensemble.

C'est pourquoi le hg help import dit:

Because import first applies changes to the working directory, import will
abort if there are outstanding changes.

La commande d'importation sert davantage à importer des ensembles de modifications (avec metedata lorsque les données proviennent de hg export) qu'à la simple application de correctifs. Si vous avez vos propres modifications dans la copie de travail, vous pouvez par exemple toujours utiliser hg import --bypass et aucune erreur ne s'y produira car la validation est directement appliquée au référentiel et non à la copie de travail. (Remarque: mais si vous ne faites que valider vos modifications, vous obtiendrez deux têtes que vous devrez fusionner .. :-).

Une solution avec la ligne de commande pour les systèmes Unix consiste à utiliser directement la commande patch au lieu de hg import car aucune vérification des modifications locales ne sera effectuée. Par exemple.,

for i in 1 2 etc.
do 
   patch -p1 < patch$i.diff
done
hg commit ...

Pour les systèmes non-Unix, vous pouvez également disposer d'une solution Mercurial pure en installant l'extension shelve, en l'activant dans votre fichier de configuration globale (Mercurial.ini), puis en utilisant shelve pour gérer les correctifs de fusion l'un après l'autre:

hg import --no-commit patch1.diff
hg shelve
hg import --no-commit patch2.diff
hg unshelve
etc.

Si jamais un conflit devait se produire, shelve le détectera et vous devrez le résoudre, puis indiquer à shelve qu'il est résolu avec l'option --continue.

J'espère que ça va aider.

13
Christophe Muller

Voici ce qui a fonctionné pour moi (solution Windows), une idée a été prise de Christophe Muller réponse:

copy /b "patch01.diff" + "patch02.diff" + ... + "patchXX.diff" "all.diff"

hg import "all.diff" --no-commit

Il suffit simplement de concaténer tous les correctifs (en tant que gros fichier), puis de les appliquer.

4
tigrou

Une solution possible consiste à utiliser Files d'attente Mercurial (remarque - il semble que cette extension soit "souvent considérée comme obsolète", mais elle n'est pas encore obsolète et est livrée pré-installée avec Mercurial).

Si vous n'avez pas utilisé MQ auparavant, c'est très pratique, même si c'est un peu complexe. Mais cela vous permet effectivement de créer des files de patchs, qui peuvent être poussés, sautés, réordonnés, etc.

Vous pouvez l’utiliser pour vous aider à résoudre votre problème de la manière suivante:

:: if you don't already have MQ initialised for the repo, do so
hg init --mq

:: import the patches you want as queue entries
hg qimport -P patch1.diff
hg qimport -P patch2.diff
hg qimport -P patch3.diff

L'option -P applique les modifications au fur et à mesure que vous les importez, ce qui signifie que vous vérifiez bien qu'elles s'appliquent correctement . Lorsque tous les correctifs sont importés dans MQ, supprimez-les tous. commencé) et pliez-les tous dans un nouveau patch combiné:

:: go back to no patches applied, and create a new patch at the front of the queue
hg qpop --all
hg qnew -m "Your planned commit message" combined_patches
:: fold the named patches into the current one
hg qfold patch1 patch2 patch3

Ensuite, si vous êtes satisfait du correctif résultant, convertissez-le simplement en un "vrai" ensemble de modifications:

:: convert combined_patches into a "real" changeset
hg qfinish combined_patches
2
icabod

Je pense qu'il pourrait y avoir une manière plus élégante de faire ceci:

(si vous voulez d'abord extraire un patch inverse):

hg diff -c xxx --reverse > 1.diff

En supposant que le pourboire actuel est txxx

hg import 1.diff #creates changeset cxxx1
Hg import 2.diff #creates changeset cxxx2
Hg import 3.diff #creates changeset cxxx3
hg rebase -r cxxx1::cxxx3 -d txxx --collapse
0
Zang XC