Comment fusionner mes modifications locales non validées dans une autre branche Git?

621

Comment puis-je faire ce qui suit dans Git?

Ma branche actuelle est branch1 et j'ai apporté quelques modifications locales. Cependant, je me rends compte maintenant que je voulais réellement appliquer ces modifications à branch2. Existe-t-il un moyen d'appliquer / fusionner ces modifications afin qu'elles deviennent des modifications locales sur branch2 sans les valider sur branch1?

solsberg
la source
2
Il y a un excellent tutoriel Git ici sur SO. C'est une sorte de central pour toutes les questions git sur le débordement de pile.
Decio Lira

Réponses:

898

Étant donné que vos fichiers ne sont pas encore validés dans branch1:

git stash
git checkout branch2
git stash pop

ou

git stash
git checkout branch2
git stash list       # to check the various stash made in different branch
git stash apply x    # to select the right one

Comme commenté par benjohn (voir git stashpage man ):

Pour également cacher les fichiers actuellement non suivis (nouvellement ajoutés), ajoutez l'argument -u, donc:

git stash -u
VonC
la source
2
Je vous en prie. Plus d'exemples d'utilisation de stash sur unethicalblogger.com/posts/2008/11/… .
VonC
2
Si vous recherchez une solution au même problème, mais avec TFS, la solution équivalente consiste à mettre vos modifications en attente, puis à utiliser TFS Power Tools pour annuler le transfert vers la branche appropriée à l'aide du commutateur / migrate.
xr280xr
1
Cela a fonctionné pour moi. Cependant, j'ai également dû créer une branche locale pour que la «stash pop» fonctionne. Consultez stackoverflow.com/questions/1783405/git-checkout-remote-branch si quelque chose de similaire vous arrive.
mimoralea
21
Stash aussi actuellement trassez fichiers (nouvellement ajoutés) , ajoutez l'argument -u, donc: git stash -u.
Benjohn
2
@Benjohn Bon point. J'ai inclus votre commentaire dans la réponse pour plus de visibilité.
VonC
84

Le stashing, les validations temporaires et le rebasage peuvent tous être exagérés. Si vous n'avez pas encore ajouté les fichiers modifiés à l'index, vous pourrez peut-être simplement extraire l'autre branche.

git checkout branch2

Cela fonctionnera tant qu'aucun fichier que vous modifiez n'est différent entre branch1 et branch2. Il vous laissera sur branch2 avec vos modifications de travail préservées. S'ils sont différents, vous pouvez spécifier que vous souhaitez fusionner vos modifications locales avec les modifications introduites en changeant de branche avec l' -moption de retrait.

git checkout -m branch2

Si vous avez ajouté des modifications à l'index, vous voudrez d'abord annuler ces modifications avec une réinitialisation. (Cela préservera votre copie de travail, il supprimera simplement les modifications par étapes.)

git reset
CB Bailey
la source
3
Je pensais que la cachette était "plus simple" à comprendre, mais votre approche est meilleure pour prendre en compte le répertoire de travail dans différentes branches. +1
VonC
6
Un simple paiement traditionnel semblait plus approprié au problème en cours. le paiement est plus léger, il ne fait que mettre à jour les fichiers à modifier. Il est peut-être plus facile de comprendre l'approche cachée, ou il se peut simplement que ce ne soit pas assez évident que le paiement soit «sûr» dans ce cas d'utilisation.
CB Bailey
Si ce checkout -mn'est pas "sûr" dans certaines situations (peut-être que cela provoquerait un conflit de fusion), la cachette fournirait-elle un avantage (par exemple, pouvez-vous annuler le pop d'une cachette)?
Craig McQueen
1
@craigMcQueen Vous ne pouvez pas ouvrir une cachette sautée mais la cachette se plaindrait de conflits lorsque vous la faites éclater. Vous pouvez corriger les conflits puis valider, mais la cachette d'origine est toujours dans la pile dans ce cas! :)
Shaun F
En cas de conflit de fusion, les fichiers ne sont-ils pas sauvegardés comme .orig?
jocull
13

Une alternative plus courte à l'approche cachée précédemment mentionnée serait:

Déplacer temporairement les modifications dans une cachette.

  1. git stash

Créez et basculez vers une nouvelle branche, puis ajoutez-y la cachette en une seule étape.

  1. git stash branch new_branch_name

Alors juste addet commitles changements à cette nouvelle branche.

rbento
la source
10

AVERTISSEMENT: pas pour les débutants git.

Cela revient suffisamment dans mon flux de travail que j'ai presque essayé d'écrire une nouvelle commande git pour cela. Le git stashflux habituel est le chemin à parcourir mais est un peu gênant. Je fais généralement un nouveau commit d'abord car si j'ai regardé les changements, toutes les informations sont fraîches dans mon esprit et il vaut mieux commencer juste git commitce que j'ai trouvé (généralement un correctif appartenant au maître que je découvre en travaillant sur un branche caractéristique) tout de suite.

Il est également utile, si vous rencontrez souvent des situations comme celle-ci, d'avoir un autre répertoire de travail à côté de votre répertoire actuel avec toujours la masterbranche extraite.

Alors, comment j'y parviens va comme ceci:

  1. git commit les changements tout de suite avec un bon message de validation.
  2. git reset HEAD~1 pour annuler la validation de la branche actuelle.
  3. (facultatif) continuez à travailler sur la fonction.

Parfois plus tard (de manière asynchrone), ou immédiatement dans une autre fenêtre de terminal:

  1. cd my-project-master qui est un autre WD partageant le même .git
  2. git reflog pour trouver le correctif que je viens de faire.
  3. git cherry-pick SHA1 du commit.

En option (toujours asynchrone), vous pouvez ensuite rebaser (ou fusionner) votre branche de fonctionnalités pour obtenir le correctif, généralement lorsque vous êtes sur le point de soumettre un PR et que vous avez déjà nettoyé votre branche de fonctionnalités et WD:

  1. cd my-project qui est le principal WD sur lequel je travaille.
  2. git rebase master pour obtenir les corrections de bugs.

De cette façon , je peux continuer à travailler sur la fonction ininterrompue et ne pas avoir à vous soucier de git stash-ment quoi que ce soit ou d' avoir à nettoyer mon WD devant un git checkout(et ayant le contrôle backout branche de fonction à nouveau.) Et ont encore toutes mes corrections de bugs va au masterlieu de caché dans ma branche de fonctionnalité.

IMO git stashet git checkoutest un véritable PIA lorsque vous êtes en train de travailler sur une grande fonctionnalité.

chakrit
la source
Alternative intéressante et valable à ma réponse. +1
VonC
Vous venez de mercurial? Le my-project-masterpartage le même .gitdonne l'impression qu'il en a l'air. Pourquoi ne pas git checkout -b bugfixABC; git commit -a; git reset HEAD^ --hard, puis plus tard ( de façon asynchrone) pendant master, git cherry-pick <SHA1 of the commit(s) in bugfixABC? (ou même, pour éviter d'avoir à découvrir le SHA1, git rebase --onto master feature bugfixABCd'où que vous soyez actuellement. Ce qui signifie que vous pouvez le faire directement après ce qui git resetprécède, pendant que vous êtes en ligne feature.)
Gauthier
Cependant, OP sonne comme s'ils n'étaient pas prêts à valider les changements, dans ce cas, checkout -mc'est mieux.
Gauthier
2

S'il s'agissait de changements validés, vous devriez jeter un œil à git-rebase, mais comme le souligne VonC, lorsque vous parlez de changements locaux, git-stash serait certainement le bon moyen de le faire.

claf
la source
Je ne comprends pas cette solution: elle réécrirait l'historique des validations de branch2 de branch1 ... pourquoi obtenir toutes les modifications validées de branch1 dans branch2 alors que nous voulons seulement obtenir les modifications locales non validées de branch1 dans branch2? ...
VonC
@VonC: convenu, dans ce cas, le rebase obtient toutes les modifications validées depuis la dernière fusion entre les branches dans branch1. Je n'ai pas obtenu le paramètre "non engagé" de cette question au début. rebaser n'est pas la bonne réponse.
claf
@claferri: pfew ... Je commençais à avoir mal à la tête;) J'aurais rétrogradé votre réponse, mais puisque j'en avais moi-même publié une, il y avait un "conflit d'intérêts clair". Avec votre message mis à jour, je n'ai plus du tout à voter. Merci :)
VonC
@VonC: la prochaine fois, n'hésitez pas à voter contre tant que ma réponse est aussi fausse que celle-ci;)
claf
1

Les réponses données jusqu'à présent ne sont pas idéales car elles nécessitent beaucoup de travail inutile pour résoudre les conflits de fusion, ou elles font trop d'hypothèses qui sont souvent fausses. Voilà comment le faire parfaitement. Le lien est vers mon propre site.

Comment s'engager dans une autre branche dans git

Vous avez des modifications non validées sur my_branchlesquelles vous souhaitez vous engager master, sans valider toutes les modifications de my_branch.

Exemple

git merge master
git stash -u
git checkout master
git stash apply
git reset
git add example.js
git commit
git checkout .
git clean -f -d
git checkout my_branch
git merge master
git stash pop

Explication

Commencez par fusionner masterdans votre branche, car vous devrez le faire de toute façon, et c'est maintenant le meilleur moment pour résoudre tout conflit.

L' -uoption de (aka --include-untracked) en git stash -uvous empêche de perdre des fichiers non suivis quand vous faites plus tard git clean -f -ddans les master.

Après, git checkout masteril est important de ne PAS le faire git stash pop, car vous aurez besoin de cette cachette plus tard. Si vous pop la planque créé my_branchpuis faites git stashen master, vous causer des conflits de fusion inutiles lorsque vous appliquez plus tard que dans Stash my_branch.

git resetmet en scène tout ce qui en résulte git stash apply. Par exemple, les fichiers qui ont été modifiés dans la cachette mais qui n'existent pas sont mastermis en scène comme des conflits «supprimés par nous».

git checkout .et git clean -f -dsupprimez tout ce qui n'est pas validé: toutes les modifications apportées aux fichiers suivis et tous les fichiers et répertoires non suivis. Ils sont déjà enregistrés dans la cachette et s'ils sont laissés dans, mastercela provoquerait des conflits de fusion inutiles lors du retour à my_branch.

Le dernier git stash popsera basé sur l'original my_branchet ne provoquera donc aucun conflit de fusion. Cependant, si votre cachette contient des fichiers non suivis que vous vous êtes engagé à maîtriser, git se plaindra qu'il "n'a pas pu restaurer les fichiers non suivis à partir de la cachette". Pour résoudre ce conflit, supprimez ces fichiers de votre arborescence de travail, puis git stash pop, git add .et git reset.

Vladimir Kornea
la source
2
Votre réponse n'a pas été supprimée car elle est liée à votre site Web, elle a été supprimée car elle était identique à cette autre réponse d'un autre compte. Je vois que l'autre compte a le même profil que le vôtre, utilisez-vous deux comptes? Vous pouvez fusionner les deux comptes. Signalez également un mod pour expliquer la situation et vous pourrez obtenir votre réponse originale (avec le vote positif) non supprimée.
1
Vous ne pouvez pas les séparer s'ils sont fusionnés, mais vous êtes autorisé à avoir plusieurs comptes, tant que vous ne les utilisez pas pour commettre une fraude au vote (ou les faire interagir les uns avec les autres en général). Expliquez votre situation à un mod. De plus, la suppression était une erreur honnête, comment pouvez-vous vous attendre à ce que quelqu'un dise que vous utilisez deux comptes différents?
3
Vous devez signaler votre message et utiliser l'option Autre pour attirer l'attention d'un mod, ils ne feront pas attention lorsque vous modifiez votre réponse supprimée. J'ai déjà signalé vos messages à l'attention du mod, mais ils sont assez occupés, alors soyez patient, ils finiront par vous contacter.
1
Ne publiez pas de contenu en double, en particulier à partir de différents comptes. Votez ou marquez pour fermer en double si deux questions sont identiques.
Bill the Lizard