web-dev-qa-db-fra.com

Cacher uniquement les changements mis en scène dans git - est-ce possible?

Y a-t-il un moyen de cacher mes changements mis en scène? Le problème avec lequel je rencontre des problèmes, c’est que j’ai travaillé sur plusieurs bogues à la fois et que plusieurs modifications ont été apportées. J'aimerais pouvoir organiser ces fichiers individuellement, créer mes fichiers .patch et les ranger jusqu'à ce que le code soit approuvé. De cette façon, une fois approuvé, je peux cacher toute ma session (en cours), supprimer ce bogue et transmettre le code.

Est-ce que je m'y prends mal? Est-ce que je comprends mal comment git peut utiliser d'autres méthodes pour simplifier mon processus?

274
MrDuk

Oui, c'est possible avec DOUBLE STASH, croyance ou non,

  1. Mettez en scène tous vos fichiers que vous devez stocker.
  2. Exécutez git stash --keep-index. Cette commande créera une réserve avec TOUS de vos modifications ( mises en scène et non mises en scène ), mais laissera les modifications mises en scène. dans votre répertoire de travail (toujours en état mis en scène).
  3. Exécuter git stash Push "good stash"
  4. Maintenant votre "good stash" a SEULEMENT les fichiers mis en scène.

Maintenant, si vous avez besoin de fichiers non stockés avant stash, appliquez simplement la première stash ( celle créée avec --keep-index) et vous pouvez maintenant supprimer les fichiers que vous avez cachés. à "good stash".

Prendre plaisir

371

Avec le dernier git, vous pouvez utiliser l’option --patch

git stash Push --patch

Et git vous demandera d’ajouter ou non des modifications dans vos fichiers. Vous venez de répondre y ou n

81
Eugen Konkov

J'ai fait un script qui ne cache que ce qui est actuellement mis en scène et laisse tout le reste. C’est génial quand je commence à faire trop de changements indépendants. Il suffit de mettre en scène ce qui n’est pas lié au commit voulu et de le cacher.

(Merci à Bartłomiej pour le point de départ)

#!/bin/bash

#Stash everything temporarily.  Keep staged files, discard everything else after stashing.
git stash --keep-index

#Stash everything that remains (only the staged files should remain)  This is the stash we want to keep, so give it a name.
git stash save "$1"

#Apply the original stash to get us back to where we started.
git stash apply stash@{1}

#Create a temporary patch to reverse the originally staged changes and apply it
git stash show -p | git apply -R

#Delete the temporary stash
git stash drop stash@{1}
43
Joe

Pourquoi ne pas valider la modification pour un certain bogue et créer un patch à partir de ce commit et de son prédécesseur?

# hackhackhack, fix two unrelated bugs
git add -p                   # add hunks of first bug
git commit -m 'fix bug #123' # create commit #1
git add -p                   # add hunks of second bug
git commit -m 'fix bug #321' # create commit #2

Ensuite, pour créer les correctifs appropriés, utilisez git format-patch:

git format-patch HEAD^^

Cela créera deux fichiers: 0001-fix-bug-123.patch et 0002-fix-bug-321.patch

Vous pouvez également créer des branches distinctes pour chaque bogue. Vous pouvez ainsi fusionner ou redéfinir les corrections de bogues individuellement, voire les supprimer, si elles ne fonctionnent pas.

6
knittl

Pour accomplir la même chose ...

  1. Mettez en scène uniquement les fichiers sur lesquels vous souhaitez travailler.
  2. git commit -m 'temp'
  3. git add .
  4. git stash
  5. git reset HEAD~1

Boom. Les fichiers que vous ne voulez pas sont stockés. Les fichiers que vous voulez sont tous prêts pour vous.

4
Michael

Dans ce scénario, je préfère créer de nouvelles branches pour chaque problème. J'utilise un préfixe temp/donc je sais que je peux supprimer ces branches plus tard.

git checkout -b temp/bug1

Mettez en scène les fichiers qui corrigent bug1 et validez-les.

git checkout -b temp/bug2

Vous pouvez ensuite sélectionner les commits dans les branches respectives selon vos besoins et soumettre une demande d'extraction.

4
Shamps

git stash --keep-index est une bonne solution ... sauf que cela ne fonctionnait pas correctement sur les chemins supprimés, ce qui a été corrigé dans Git 2.23 (Q3 2019).

Voir commit b932f6a (16 juillet 2019) par Thomas Gummerer (tgummerer) .
(Fusion par Junio ​​C Hamano - gitster - dans commit f8aee85 , 25 juillet 2019)

stash: correction du traitement des fichiers supprimés avec --keep-index

git stash Push --keep-index est supposé conserver toutes les modifications qui ont été ajoutées à l'index, à la fois dans l'index et sur le disque.

Actuellement, cela ne se comporte pas correctement lorsqu'un fichier est supprimé de l'index.
Au lieu de le garder supprimé sur le disque, ** - keep-index restaure actuellement le fichier. **

Corrigez ce problème en utilisant 'git checkout' en mode sans incrustation, qui permet de restaurer fidèlement l'index et l'arborescence de travail.
Ceci simplifie également le code.

Notez que cela écrasera les fichiers non suivis si le fichier non suivi a le même nom qu'un fichier supprimé dans l'index.

1
VonC

Est-il absolument nécessaire de travailler sur plusieurs bugs à la fois? Et par "à la fois", je veux dire "avoir des fichiers édités pour plusieurs bogues en même temps". Parce que si vous n'en avez absolument pas besoin, je ne travaillerais que sur un seul bogue à la fois dans votre environnement. De cette façon, vous pouvez utiliser des branches et des bases locales, ce que je trouve beaucoup plus facile que de gérer un stock/stade complexe.

Disons que master est à commit B. Travaillez maintenant sur le bogue n ° 1.

git checkout -b bug1

Maintenant, vous êtes sur la branche bug1. Apportez des modifications, validez, attendez la révision du code. Ceci est local, vous n'affecterez donc personne, et il devrait être assez facile de créer un patch à partir de git diffs.

A-B < master
   \
    C < bug1

Vous travaillez maintenant sur bug2. Allez en arrière à maîtriser avec git checkout master. Créez une nouvelle branche, git checkout -b bug2. Apportez des modifications, validez, attendez la révision du code.

    D < bug2
   /
A-B < master
   \
    C < bug1

Supposons que quelqu'un d'autre confie E & F au maître pendant que vous attendez un examen.

    D < bug2
   /
A-B-E-F < master
   \
    C < bug1

Lorsque votre code a été approuvé, vous pouvez le rebaser pour le maîtriser en procédant comme suit:

git checkout bug1
git rebase master
git checkout master
git merge bug1

Cela se traduira par:

    D < bug2
   /
A-B-E-F-C' < master, bug1

Ensuite, vous pouvez pousser, supprimer votre branche locale de bug1, et c'est parti. Un bogue à la fois dans votre espace de travail, mais avec l’utilisation de branches locales, votre référentiel peut gérer plusieurs bogues. Et cela évite une danse de scène/stash compliquée.

Réponse à la question de ctote dans les commentaires:

Eh bien, vous pouvez revenir à la sauvegarde de chaque bogue et ne travailler qu’avec un seul bogue à la fois. Au moins, cela vous évite le problème de la mise en scène. Mais après avoir essayé cela, je trouve personnellement cela gênant. Les caches sont un peu en désordre dans un graphe de journal git. Et plus important encore, si vous faites foirer quelque chose, vous ne pouvez plus revenir en arrière. Si vous avez un répertoire de travail sale et que vous ouvrez une réserve, vous ne pouvez pas "annuler" cette suppression. Il est beaucoup plus difficile de bousiller des commits déjà existants.

Donc, git rebase -i.

Lorsque vous rebassez une branche sur une autre, vous pouvez le faire de manière interactive (le drapeau -i). Lorsque vous faites cela, vous avez la possibilité de choisir ce que vous voulez faire avec chaque commit. Pro Git est un livre génial qui est également disponible en ligne au format HTML et qui comporte une section intéressante sur le rebasage et l'écrasement:

http://git-scm.com/book/ch6-4.html

Je vais voler leur exemple textuellement pour plus de commodité. Imaginez que vous avez l'historique de validation suivant et que vous souhaitez redéfinir & écraser bug1 sur master:

    F < bug2
   /
A-B-G-H < master
   \
    C-D-E < bug1

Voici ce que vous verrez lorsque vous tapez git rebase -i master bug1

pick f7f3f6d changed my name a bit
pick 310154e updated README formatting and added blame
pick a5f4a0d added cat-file
#
# Commands:
#  p, pick = use commit
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

Pour écraser tous les commits d'une branche en un seul, gardez le premier commit en tant que "pick" et remplacez toutes les entrées "pick" suivantes par "squash" ou simplement "s". Vous aurez également la possibilité de modifier le message de validation.

pick f7f3f6d changed my name a bit
s 310154e updated README formatting and added blame
s a5f4a0d added cat-file
#
# Commands:
#  p, pick = use commit
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit

Alors oui, écraser est un peu pénible, mais je le recommanderais quand même à une utilisation intensive de caches.

1
Mike Monkiewicz

Parmi vos commentaires à Mike Monkiewicz, je suggère d'utiliser un modèle plus simple: utilisez des branches de développement normales, mais utilisez l'option squash de la fusion pour obtenir un seul commit dans votre branche principale:

git checkout -b bug1    # create the development branch
* hack hack hack *      # do some work
git commit
* hack hack hack *
git commit
* hack hack hack *
git commit
* hack hack hack *
git commit
git checkout master     # go back to the master branch
git merge --squash bug1 # merge the work back
git commit              # commit the merge (don't forget
                        #    to change the default commit message)
git branch -D bug1      # remove the development branch

L'avantage de cette procédure est que vous pouvez utiliser le flux de travail normal de git.

0
Rudi