Valider uniquement une partie d'un fichier dans Git

2766

Lorsque j'apporte des modifications à un fichier dans Git, comment puis-je valider uniquement certaines des modifications?

Par exemple, comment pourrais-je valider seulement 15 lignes sur 30 lignes qui ont été modifiées dans un fichier?

freddiefujiwara
la source
3
connexes stackoverflow.com/q/34609924/52074 : si vous avez besoin de diviser un gros morceau en gros morceaux plus petits.
Trevor Boyd Smith
Résumé: en termes de capacité: git gui= git add -e> git add -i -p; en termes de commodité: git gui> git add -i -p> git add -e. Donc: choisissez git guiquand vous avez accès à X. choisissez git add -i -ppour des choses simples et quand vous n'avez pas ou ne voulez pas utiliser X. git add -epour une mise en scène complexe sans X.
Penghe Geng

Réponses:

3689

Vous pouvez utiliser git add --patch <filename>(ou -ppour faire court), et git commencera à décomposer votre fichier en ce qu'il pense être des "mecs" sensés (parties du fichier). Il vous posera alors cette question:

Stage this hunk [y,n,q,a,d,/,j,J,g,s,e,?]?

Voici une description de chaque option:

  • y mettre en scène ce morceau pour le prochain commit
  • n ne pas mettre en scène ce morceau pour le prochain commit
  • qquitter; ne mettez pas en scène ce morceau ou l'un des autres morceaux
  • a mettre en scène ce morceau et tous les mecs ultérieurs dans le fichier
  • d ne pas mettre en scène ce morceau ou l'un des derniers morceaux du fichier
  • g sélectionner un morceau pour aller
  • / rechercher un morceau correspondant à l'expression régulière donnée
  • j laisser ce morceau indécis, voir le prochain morceau indécis
  • J laisser ce morceau indécis, voir le morceau suivant
  • k laisser ce morceau indécis, voir le morceau indécis précédent
  • K laisser ce morceau indécis, voir le morceau précédent
  • s diviser le morceau actuel en plus petits morceaux
  • e éditer manuellement le morceau actuel
  • ? imprimer l'aide du morceau

Si le fichier n'est pas encore dans le référentiel, vous pouvez d'abord le faire git add -N <filename>. Ensuite, vous pouvez continuer avecgit add -p <filename> .

Ensuite, vous pouvez utiliser:

  • git diff --staged pour vérifier que vous avez mis en place les modifications correctes
  • git reset -p pour mettre en scène des mecs ajoutés par erreur
  • git commit -v pour afficher votre validation pendant que vous modifiez le message de validation.

Notez que cela est très différent de la git format-patchcommande, dont le but est d'analyser les données de validation dans un .patchfichier.

Référence pour l'avenir: Git Tools - Interactive Staging

mac
la source
83
Il peut être utile de noter qu'il -p/--patchs'agit d'un raccourci vers l'action du correctif à l'intérieur de la -i/--interactivecommande qui lance le mode interactif utile .
tutuDajuju
5
> Que se passe-t-il si ce fichier est déjà mis en scène? Il affichera uniquement les modifications non mises en scène. Même chose git diff.
Eugen Konkov
3
Comment puis-je modifier manuellement le morceau actuel? Je ne sais pas quoi faire après avoir tapé e.
Hunsu
23
Après avoir appuyé sur e, vous pouvez éditer le morceau manuellement en remplaçant +ou -en#
veksen
1
c'est super mais maintenant comment puis-je réellement le pousser? si je le fais, git pushil est déjà à jour. et si je le fais, git diffje vois les mecs que j'ai dit n. si je le vois, git diff --stagedje vois le commit que je veux pousser. En supposant que je puisse pousser le commit, comment supprimer les mecs auxquels j'ai dit no?
chovy
250

Vous pouvez utiliser git add --interactiveou , puis ( non ); voir le mode interactif dans git-addgit add -p <file>git commit git commit -a page de manuel , ou suivez simplement les instructions.

Modern Git a également git commit --interactive(etgit commit --patch , qui est un raccourci vers l'option de patch dans la validation interactive).

Si vous préférez le faire à partir de l'interface graphique, vous pouvez utiliser git-gui . Vous pouvez simplement marquer les morceaux que vous souhaitez inclure dans la validation. Personnellement, je trouve cela plus facile que d'utiliser git add -i. D'autres interfaces graphiques git, comme QGit ou GitX, pourraient également avoir cette fonctionnalité.

Jakub Narębski
la source
1
Il est intéressant de noter que windows.github.com a pris en charge les validations de fichiers partielles mais semble l'avoir abandonné récemment ..
Juri
1
@Juri Je pense que le support des validations de fichiers partielles est de retour.
Ela782
@Juri Vous êtes les bienvenus. En fait, je n'avais jamais remarqué qu'il y était auparavant - je l'ai vu la semaine dernière et j'ai pensé "oh, quelle nouvelle fonctionnalité incroyable"! :-)
Ela782
1
De nos jours, windows.github.com redirige vers le bureau GitHub renommé qui est plus agréable que Git GUI et prend en charge les validations partielles ... mais ne prend pas en charge la signature de validation. Soupir.
147

git gui fournit cette fonctionnalité sous la vue diff. Faites simplement un clic droit sur la ou les lignes qui vous intéressent et vous devriez voir un élément de menu "Mettre cette ligne en ligne pour valider".

Ionuț G. Stan
la source
13
pour les patchs complexes, c'est généralement l'approche la plus rapide pour moi.
hochl
7
Il s'agit d'un moyen très efficace et intuitif d'ajouter des modifications à la zone de transfert de manière fine. De plus, plusieurs lignes peuvent être sélectionnées et toutes les modifications de cette sélection seront ajoutées.
jox
Notez que ce n'est pas le cas gitk, mais il est inclus avec Git Bash pour Windows; vous devriez avoir une entrée de menu de démarrage pour cela ou vous pouvez le démarrer avec la commande git gui. Il y a aussi stage this hunkce qui est probablement plus utile que stage this line. Peut-être nouveau depuis que cette réponse a été créée il y a 10 ans.
Chris
82

je crois que git add -e myfile c'est la façon la plus simple (ma préférence au moins) car elle ouvre simplement un éditeur de texte et vous permet de choisir la ligne que vous souhaitez mettre en scène et celle que vous ne souhaitez pas. Concernant les commandes d'édition:

contenu ajouté:

Le contenu ajouté est représenté par des lignes commençant par "+". Vous pouvez empêcher le transfert de lignes d'ajout en les supprimant.

contenu supprimé:

Le contenu supprimé est représenté par des lignes commençant par "-". Vous pouvez empêcher la mise en scène de leur suppression en convertissant le "-" en "" (espace).

contenu modifié:

Le contenu modifié est représenté par des lignes "-" (suppression de l'ancien contenu) suivies de lignes "+" (ajout du contenu de remplacement). Vous pouvez empêcher la mise en scène de la modification en convertissant les lignes "-" en "" et en supprimant les lignes "+". Attention, la modification de seulement la moitié de la paire risque d'introduire des changements déroutants dans l'indice.

Tous les détails git addsont disponibles surgit --help add

theFreedomBanana
la source
7
Ce serait plus utile s'il y avait une explication claire quelque part sur la façon de choisir réellement ces lignes (c'est-à-dire les commandes réelles à entrer). Je n'ai pas pu en trouver un dans la documentation. Pourriez-vous ajouter une référence?
Alex
4
Pour ceux qui n'aiment pas les options de raccourci, -ec'est --edit.
Kolyunya
2
@Alex Les citations de référence ajoutées par theFreedomBanana proviennent de la section MODIFICATION DES PATCHS dansgit --help add
Randall
8
C'est la seule réponse (ne nécessitant que git) qui résout le problème de l'ajout / de la suppression de ligne lorsque vous ne pouvez pas réduire les morceaux avec le smode patch interactif.
cdosborn
3
Il peut être utile de comprendre que cette commande ( git add -e) * ne * change pas le contenu du fichier sur le disque. Il déplace simplement une partie des modifications de non-étagé à étagé (index).
Penghe Geng
44

Si vous utilisez vim, vous voudrez peut-être essayer l'excellent plugin appelé fugitive .

Vous pouvez voir la différence d'un fichier entre la copie de travail et l'index avec :Gdiff, puis ajouter des lignes ou des morceaux à l'index à l'aide des commandes de diff vim classiques comme dp. Enregistrez les modifications dans l'index et validez avec :Gcommit, et vous avez terminé.

Très bons screencasts d'introduction ici (voir en particulier la partie 2 ).

François
la source
Merci beaucoup pour ces liens. Exactement la même chose dont j'ai besoin. Surtout :diffget/:diffputen mode visuel, où je peux choisir des lignes spécifiques, que je veux réinitialiser / valider. Alors, assurez-vous à nouveau: vim est génial.
goodniceweb
30

Je recommanderais fortement d'utiliser SourceTree d'Atlassian. (C'est gratuit.) Cela rend cela trivial. Vous pouvez mettre en scène des morceaux de code individuels ou des lignes de code individuelles rapidement et facilement.

entrez la description de l'image ici

Bob Stein
la source
1
Je suis d'accord que SourceTree est un bon outil à cet effet, car il vous donne un contrôle plus fin que ce qui est possible via la ligne de commande.
19
@cupcake Je dirais le contraire, vu que SourceTree utilise probablement ces exécutables git en ligne de commande, intrinsèquement, il sera toujours possible de faire les mêmes (ou plus) actions fines via la "ligne de commande".
tutuDajuju
2
Indépendamment de l' argument fin que je recommanderais fortement SourceTree car la mise en scène de mecs et de lignes individuelles est super facile: i.imgur.com/85bNu4C.png
Mars Robertson
1
@tutuDajuju Dans ce cas, je ne suis pas sûr que ce soit vrai. SourceTree a la possibilité de choisir les portions à mettre en scène ligne par ligne . Vous n'avez pas à mettre en scène un morceau entier; vous pouvez mettre en scène 2 lignes au milieu d'un morceau. Je n'ai cependant aucune idée de la façon dont il y parvient. (En ce moment, j'essaie de contourner l'incapacité de SourceTree à mettre en scène des lignes particulières pour un fichier non suivi. J'ai atterri ici à la recherche d'une solution de contournement, seulement pour découvrir que git ne semble pas offrir la capacité ligne par ligne
Du
1
@Sun vous pouvez cliquer sur la ligne 50 et déplacer + cliquer sur la ligne 100 puis mettre en scène. Vous pouvez facilement mettre en scène la ligne 50-100 à Sourcetree :)
ryan123
26

Il convient de noter que pour utiliser git add --patchun nouveau fichier, vous devez d'abord ajouter le fichier à indexer avec git add --intent-to-add:

git add -N file
git add -p file
user1338062
la source
23

Lorsque j'ai beaucoup de changements et que je vais finir par créer quelques commits à partir des changements, je veux enregistrer temporairement mon point de départ avant de mettre en scène les choses.

Comme ça:

$ git stash -u
Saved working directory and index state WIP on master: 47a1413 ...
$ git checkout -p stash
... step through patch hunks
$ git commit -m "message for 1st commit"
$ git checkout -p stash
... step through patch hunks
$ git commit -m "message for 2nd commit"
$ git stash pop

La réponse de Whymarrh est ce que je fais habituellement, sauf que parfois il y a beaucoup de changements et je peux dire que je peux faire une erreur en mettant en scène les choses, et je veux un état engagé sur lequel je peux me rabattre pour un deuxième passage.

jdsumsion
la source
12

Si vous utilisez emacs, jetez un œil à Magit , qui fournit une interface git pour emacs. Il prend assez bien en charge les segments intermédiaires (parties de fichiers).

Mark van Lent
la source
Je trébuche souvent sur une commande git voulant ouvrir un éditeur, lorsque je l'exécute à partir d'une fenêtre shell Mx. Est-ce que magit intercepte cette folie et ouvre juste un nouveau tampon pour cela? (veuillez ne pas avoir d'indices background-emacs-daemon; merci quand même mais la vie est trop courte).
user2066657
Non, pour autant que je sache, cela n'intercepte pas cela. Mais ne vous fiez pas seulement à ma parole car (1) je n'utilise presque jamais la fenêtre shell dans Emacs, et (2) j'utilise normalement emacsclient. Cela dit, si emacsclient est une option pour vous, cela a au moins empêché l'ouverture d'une fenêtre supplémentaire avec emacs et le tampon "COMMIT_EDITMSG" a été ouvert dans ma fenêtre Emacs existante.
Mark van Lent
10

Intellij IDEA (et je suppose que tous les autres produits de la série) prennent en charge les validations partielles depuis v2018.1

entrez la description de l'image ici

Holger Brandl
la source
9

Pour ceux qui utilisent les extensions Git :

Dans la fenêtre Valider, sélectionnez le fichier que vous souhaitez valider partiellement, puis sélectionnez le texte que vous souhaitez valider dans le volet droit, puis cliquez avec le bouton droit sur la sélection et choisissez 'Mettre en scène les lignes sélectionnées' dans le menu contextuel.

srgstm
la source
2
Le raccourci clavier dans Git Extensions pour 'Stage selected lines' est s- très utile pour organiser rapidement des parties de fichiers pour une validation.
Alchemistmatt
8

Tout comme la réponse de jdsumsion, vous pouvez également cacher votre travail actuel, mais utiliser un outil différent comme meld pour extraire les modifications sélectionnées de la cachette. De cette façon, vous pouvez même modifier les mecs manuellement très facilement, ce qui est un peu pénible lorsque git add -p:

$ git stash -u
$ git difftool -d -t meld stash
$ git commit -a -m "some message"
$ git stash pop

L'utilisation de la méthode stash vous donne la possibilité de tester, si votre code fonctionne toujours, avant de le valider.

derhoch
la source
cela fonctionne bien, mais si vous utilisez git commit --amend, il semble que vous ne puissiez pas faire sauter la cachette par la suite, ou existe-t-il un moyen de le faire?
Mark
7

En ajoutant une réponse précédente, si vous préférez utiliser la ligne de commande, entrer git add -e myfilevous donne le choix de choisir ligne par ligne ce que vous voulez valider car cette commande ouvrira un éditeur avec les différences, comme ceci:

entrez la description de l'image ici

Comme vous le savez peut-être, les lignes commençant par +sont des ajouts, les lignes commençant par -sont des suppressions. Donc:

  • Pour ne pas mettre en scène un ajout, supprimez simplement cette ligne.
  • Pour ne pas mettre en scène une suppression, il suffit de la remplacer -par de l'espace .

Voici ce que git add -hdit l'ajout de fichiers de cette façon (patcher des fichiers):

contenu ajouté ajouté est représenté par des lignes commençant par "+". Vous pouvez empêcher le transfert de lignes d'ajout en les supprimant.

contenu supprimé: supprimé est représenté par des lignes commençant par "-". Vous pouvez empêcher la mise en scène de leur suppression en convertissant le "-" en "" (espace).

contenu modifié: le contenu modifié est représenté par des lignes "-" (suppression de l'ancien contenu) suivies de lignes "+" (ajout du contenu de remplacement). Vous pouvez empêcher la mise en scène de la modification en convertissant les lignes "-" en "" et en supprimant les lignes "+". Attention, la modification de seulement la moitié de la paire risque d'introduire des changements déroutants dans l'indice.

Attention: ne modifiez pas le contenu du fichier, ce n'est pas un bon endroit pour le faire. Modifiez simplement les opérateurs des lignes supprimées ou ajoutées.

Beto Aveiga
la source
Quelle réponse précédente? Les réponses sont stockées en fonction du nombre de points qu'elles ont. Votre réponse se trouve donc dans un endroit différent de ce qu'elle était lorsque vous l'avez écrite par rapport aux autres réponses.
KulaGGin
Je crois que la réponse référencée est de @theFreedomBanana
K. Symbol
6

Le plugin vim-gitgutter peut mettre en scène des mecs sans quitter l'éditeur vim en utilisant

:GitGutterStageHunk

En plus de cela, il fournit d'autres fonctionnalités intéressantes comme une colonne de signe diff comme dans certains IDE modernes

Si seulement une partie du morceau doit être mise en scène vim-fugitive

:Gdiff

permet ensuite la sélection visuelle de la plage :'<,'>diffputou :'<,'>diffgetpour mettre en scène / annuler les modifications de ligne individuelles.

c0ffeeartc
la source
4

Avec TortoiseGit:

faites un clic droit sur le fichier et utilisez Context Menu → Restore after commit. Cela créera une copie du fichier tel quel. Ensuite, vous pouvez modifier le fichier, par exemple dans TortoiseGitMerge et annuler toutes les modifications que vous ne souhaitez pas valider. Après avoir enregistré ces modifications, vous pouvez valider le fichier.

Fr0sT
la source
4

Cela fait 10 ans que cette question a été posée. Et j'espère que cette réponse sera utile à quelqu'un. Comme mentionné dans la réponse ici , où l'interface graphique n'est pas une option, l' extension de crecord d' Andrew Shadura permet d'apporter une fenêtre ncurses dans laquelle nous pouvons sélectionner les lignes à valider.

Configurez l'extension comme suit:

git clone https://github.com/andrewshadura/git-crecord
cd git-crecord
./setup.py install
ln -s $PWD/git-crecord ~/.local/bin/git-crecord

cd à votre dépôt git et invoquez-le comme suit:

git crecord

Cela ferait apparaître l'interface ncurses qui peut être utilisée comme indiqué ci-dessous. Appuyez sur les touches suivantes dans la fenêtre ncurses pour effectuer certaines actions:

f       hunk toggle fold (arrow keys can also be used)
space   toggle hunk selection
a       toggle commit or amend
c       confirm and open commit window

Screencast montrant un exemple d'utilisationExemple

Arun
la source
3

Pour les utilisateurs d' Atom , le package github comprend une mise en scène interactive, dans le style de git gui. Pour les raccourcis, voir la documentation du package .

L'utilisation d'Atom permet de travailler avec un thème qui a un fond sombre (par défaut, git guia un fond blanc).

Ioannis Filippidis
la source
2

git-meld-index - extrait du site Web:

git-meld-index exécute meld - ou tout autre outil git difftool (kdiff3, diffus, etc.) - pour vous permettre de mettre en scène de manière interactive les modifications de l'index git (également connu sous le nom de zone de transit git).

Ceci est similaire à la fonctionnalité de git add -p et git add --interactive. Dans certains cas, meld est plus facile / plus rapide à utiliser que git add -p. En effet, meld vous permet, par exemple, de:

  • voir plus de contexte
  • voir les différences intra-ligne
  • modifier à la main et voir les mises à jour de diff en direct (mises à jour après chaque pression de touche)
  • accédez à un changement sans dire «n» à chaque changement que vous souhaitez ignorer

Usage

Dans un référentiel git, exécutez:

git meld-index

Vous verrez meld (ou votre gt difftool configuré) apparaître avec:

GAUCHE : répertoire temporaire contenant les fichiers copiés à partir de votre arborescence de travail

DROITE : répertoire temporaire avec le contenu de l'index. Cela inclut également les fichiers qui ne sont pas encore dans l'index mais qui sont modifiés ou non suivis dans la copie de travail - dans ce cas, vous verrez le contenu du fichier de HEAD.

Modifiez l'index (côté droit) jusqu'à ce que vous soyez satisfait. N'oubliez pas d'enregistrer en cas de besoin.

Lorsque vous avez terminé, fermez meld et git-meld-index mettra à jour l'index pour qu'il corresponde au contenu du répertoire temporaire sur le côté droit de meld que vous venez de modifier.

Croad Langshan
la source
2

Si c'est sur la Windowsplate-forme, à mon avis, git guic'est un très bon outil pour stage/ commitquelques lignes deunstaged fichier

1. En ce qui concerne le gros morceau:

  • Sélectionnez le fichier dans la unstagged Changessection
  • Clic droit morceau de code qui doit être mis en scène
  • Sélectionner Stage Hunk for commit

2. Ligne sage:

  • Sélectionnez le fichier dans la unstagged Changessection
  • Sélectionnez la ou les lignes à mettre en scène
  • Faites un clic droit et sélectionnez Stage Lines for commit

3. Si vous souhaitez mettre en scène le fichier complet sauf quelques lignes:

  • Sélectionnez le fichier dans la unstagged Changessection
  • presse Ctrl+T (Stage file to commit)
  • Le fichier sélectionné est désormais déplacé vers la Staged Changessection
  • Sélectionnez la ou les lignes à mettre en scène
  • Faites un clic droit et sélectionnez UnStage Lines for commit
Anvesh Yalamarthy
la source
1

Comme le montre une des réponses ci-dessus, vous pouvez utiliser git add --patch filename.txt

ou la forme courte git add -p filename.txt

... mais pour les fichiers déjà dans votre référentiel, il est préférable d'utiliser s --patch flag sur la commande commit directement (si vous utilisez une version assez récente de git): git commit --patch filename.txt

... ou, encore une fois, la forme courte git commit -p filename.txt

... puis en utilisant les clés mentionnées, (o / n, etc.) pour choisir les lignes à inclure dans la validation.

Samuel Lampa
la source
Qu'est-ce que cela vous donne? "git add -p filename.txt " moins de marge d'erreur? Si vous gâchez la modification du fichier partiel, l'annulation d'un ajout est préférable à l'annulation d'une validation.
CTMacUser
Je ne sais pas pourquoi, mais quand je dis «n», la ligne est incluse ... et quand je dis «y» sur le 2ème morceau, elle est également incluse.
chovy
1

git-cola est une excellente interface graphique et a également cette fonctionnalité intégrée. Sélectionnez simplement les lignes à mettre en scène et appuyez sur S. Si aucune sélection n'est effectuée, le morceau complet est mis en scène.

AndiDog
la source