72 votes

Quel est le moyen le plus simple de livrer et de pousser un seul fichier tout en laissant les autres modifications intactes ?

Je suis relativement nouveau dans le domaine de Mercurial et mon équipe l'essaie en ce moment en remplacement de Subversion.

Comment puis-je commiter et pousser un seul fichier vers un autre dépôt tout en laissant les autres modifications dans mon répertoire de travail non commitées (ou au moins non poussées vers l'autre dépôt) ?

Cela nous arrive avec les migrations de bases de données. Nous voulons livrer la migration au contrôle de la source pour qu'un DBA puisse la voir et la modifier pendant que nous travaillons sur les modifications du code qui accompagnent cette migration de base de données. Les modifications ne sont pas encore prêtes et nous ne voulons pas les publier toutes.

En subversion, je ferais simplement :

svn add my_migration.sql  
# commit only the migration, but not the other files I'm working on
svn commit -m "migration notes" my_mygration.sql

et continuer à travailler localement.

Cela ne fonctionne pas avec mercurial, car lorsque je le pousse vers l'autre dépôt, s'il y a des modifications que je n'ai pas retirées, il veut que je les retire, les fusionne et commette cette fusion dans le dépôt. Les livraisons après une fusion ne vous permettent pas d'omettre des fichiers, ce qui vous oblige à livrer tout ce qui se trouve dans votre dépôt local.

La solution la plus simple que j'ai trouvée est de livrer le fichier dans mon référentiel local, de cloner mon référentiel local, de récupérer toutes les nouvelles modifications du référentiel actuel, de les fusionner et de livrer cette fusion, puis de pousser mes modifications.

hg add my_migration.sql 
hg commit -m "migration notes" my_migration.sql 
cd ..
hg clone project project-clone
cd project-clone
hg fetch http://hg/project
hg push  http://hg/project

Cela fonctionne, mais j'ai l'impression qu'il me manque quelque chose de plus simple, un moyen de dire à mercurial d'ignorer les fichiers déjà présents dans mon répertoire de travail, de faire simplement la fusion et d'envoyer les fichiers. Je pense que les files d'attente de mercurial peuvent le faire, mais je ne connais pas encore très bien mq.

39voto

Ted Naleid Points 13349

Cela fait presque deux ans que j'ai posé cette question. Je le ferais différemment maintenant (comme je l'ai mentionné dans un commentaire au-dessus de la question ci-dessus). Ce que je ferais maintenant serait de commettre mes changements dans le seul fichier de mon dépôt local (vous pouvez utiliser l'extension hg record pour ne commettre que des parties d'un fichier) :

hg commit -m "commit message" filename

Ensuite, il suffit de pousser.

hg push

S'il y a un conflit parce que d'autres changements ont été apportés au dépôt et que je dois les fusionner en premier, je mettrais à jour la révision parente (que l'on peut voir avec "hg parents -r ." si vous ne savez pas ce que c'est), j'y livrerais mes autres changements pour avoir deux têtes. Ensuite, je reviens au commit d'origine avec un seul fichier et je tire/fusionne les changements dans cette version. Puis pousser les changements avec

hg push --rev .

Pour pousser uniquement le fichier unique et la fusion de cette révision. Ensuite, vous pouvez fusionner les deux têtes que vous avez localement.

De cette façon, on se débarrasse de l'aspect mq et du potentiel de rejet des hunks et on garde tout le suivi par le contrôle de source. Vous pouvez également supprimer les révisions "hg strip" si vous décidez plus tard que vous n'en voulez pas.

31voto

Josh Matthews Points 4026

Il existe une fonctionnalité de Mercurial qui implémente les commandes shelve et unshelve, qui vous donnent un moyen interactif de spécifier les changements à stocker jusqu'à une date ultérieure : Abri .

Alors vous pouvez hg shelve y hg unshelve pour stocker temporairement les changements. Il vous permet de travailler au niveau du "patch hunk" pour choisir les éléments à mettre de côté. Il ne semble pas que l'on puisse mettre de côté un fichier qui a été listé pour être ajouté, mais seulement les fichiers déjà présents dans le dépôt avec des modifications.

Il est inclus dans Mercurial en tant qu'"extension", ce qui signifie simplement que vous devez l'activer dans votre fichier de configuration hg.


Notes pour les très anciennes versions de Mercurial (avant que shelve ne soit inclus -- ce n'est plus nécessaire) :

Je n'ai pas trouvé de bonnes instructions d'installation en cherchant sur Google, alors voici les éléments que j'ai utilisés pour le faire fonctionner :

Obtenez-le avec :

hg clone http://freehg.org/u/tksoh/hgshelve/ hgshelve

Le seul fichier (actuellement) dans le projet est le fichier hgshelve.py.

Modifiez votre ~/.hgrc pour ajouter l'extension shelve, en pointant vers l'endroit où vous avez cloné le repo :

[extensions] 
hgshelve=/Users/ted/Documents/workspace/hgshelve/hgshelve.py

25voto

bresc Points 618

Voir hg help commit

Vous pouvez spécifier certains fichiers lors de la livraison. Ce n'est pas très pratique mais cela fonctionne :

hg commit -I file1.foo -I file2.foo -I file3.foo

vous pouvez également exclure certains fichiers

hg commit -X file1.boo -X file2.boo

10voto

Kobold Points 617

Tl;dr : Mon explication originale semble compliquée, mais j'espère qu'elle explique parfaitement comment utiliser une file d'attente de patchs. Voici la version courte :

$ hg qnew -m "migration notes" -f migration my_migration.sql
$ hg qnew -f working-code
# make some changes to your code
$ hg qrefresh # update the patch with the changes you just made
$ hg qfinish -a # turn all the applied patches into normal hg commits

Mercurial Queues facilite ce genre de choses, et rend possible une manipulation plus complexe des changesets. Cela vaut la peine de l'apprendre.

Dans cette situation, vous voudrez probablement d'abord sauvegarder ce qui se trouve dans votre répertoire actuel avant de récupérer les modifications :

# create a patch called migration containing your migration
$ hg qnew -m "migration notes" -f migration.patch my_migration.sql
$ hg qseries -v # the current state of the patch queue, A means applied
0 A migration.patch
$ hg qnew -f working-code.patch # put the rest of the code in a patch
$ hg qseries -v
0 A migration.patch
1 A working-code.patch

Maintenant, faisons un peu de travail supplémentaire sur le code de travail. Je vais continuer à faire qseries juste pour être explicite, mais une fois que vous aurez construit un modèle mental des files d'attente de patchs, vous n'aurez plus besoin de regarder la liste en permanence.

$ hg qtop # show the patch we're currently editing
working-code.patch
$ ...hack, hack, hack...
$ hg diff # show the changes that have not been incorporated into the patch
blah, blah
$ hg qrefresh # update the patch with the changes you just made
$ hg qdiff # show the top patch's diff

Comme tout votre travail est maintenant sauvegardé dans la file d'attente des correctifs, vous pouvez désappliquer ces modifications et les restaurer une fois que vous avez apporté les modifications à distance. Normalement pour annuler tous les patchs, il suffit de faire hg qpop -a . Pour montrer l'effet sur la file d'attente, je vais les enlever un par un.

$ hg qpop # unapply the top patch, U means unapplied
$ hg qseries -v
0 A migration.patch
1 U working-code.patch
$ hg qtop
migration.patch
$ hg qpop
$ hg qseries -v
0 U migration.patch
1 U working-code.patch

A ce stade, c'est comme s'il n'y avait aucun changement dans votre répertoire. Faites le hg fetch . Vous pouvez maintenant repousser les modifications de votre file d'attente de patchs et les fusionner s'il y a des conflits. Ce concept est quelque peu similaire à celui de rebase de git.

$ hg qpush # put the first patch back on
$ hg qseries -v
0 A migration.patch
1 U working-code.patch
$ hg qfinish -a # turn all the applied patches into normal hg commits
$ hg qseries -v
0 U working-code.patch
$ hg out
migration.patch commit info... blah, blah
$ hg push # push out your changes

À ce stade, vous avez poussé la migration tout en conservant vos autres modifications locales. Vos autres changements sont dans un patch dans la file d'attente. Je fais la plupart de mes développements personnels en utilisant une file de patchs pour m'aider à mieux structurer mes changements. Si vous voulez vous débarrasser de la file d'attente de patchs et revenir à un style normal, vous devrez exporter vos changements et les réimporter dans mercurial "normal".

$ hg qpush
$ hg qseries -v
0 A working-code.patch
$ hg export qtip > temp.diff
$ rm -r .hg/patches # get rid of mq from the repository entirely
$ hg import --no-commit temp.diff # apply the changes to the working directory
$ rm temp.diff

Je suis très accro aux files d'attente de patchs pour le développement et le mq est l'une des implémentations les plus agréables qui existent. La possibilité de créer plusieurs changements simultanément améliore vraiment la précision et la propreté de vos commits. Il faut un certain temps pour s'y habituer, mais cela va incroyablement bien avec un flux de travail DVCS.

3voto

nullptr Points 5432

Une autre option si vous ne voulez pas compter sur les extensions est de conserver localement un clone de votre dépôt amont que vous utiliserez uniquement pour ce genre de tâches d'intégration.

Dans votre exemple, vous pourriez simplement tirer/fusionner votre changement dans le dépôt d'intégration/upstream et le pousser directement vers le serveur distant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X