git merge: appliquer les modifications au code déplacé dans un autre fichier
Je cherche un assez costaud git merge manœuvre de la droite maintenant. Un problème que je suis à venir à travers, c'est que j'ai apporté quelques modifications à certains de code dans ma branche, mais mon collègue a déplacé ce code dans un nouveau fichier dans sa direction. Alors, quand je n'ai git merge my_branch his_branch
, git n'a pas remarqué que le code dans le nouveau fichier est le même que l'ancien, et donc aucun de mes modifications sont là.
Quelle est la meilleure façon d'aller sur l'application de mes changements de nouveau le code dans les nouveaux fichiers. Je ne vais pas avoir trop de problèmes à trouver qui commet doivent être renouvelés (je peux utiliser git log --stat
). Mais autant que je sache, il n'est aucun moyen d'obtenir git pour réappliquer les modifications dans les nouveaux fichiers. La meilleure chose que je vois est de faire manuellement réappliquer les modifications, ce qui n'est pas à la recherche comme une bonne idée.
Je sais que git reconnaît les gouttes, pas les fichiers, donc il doit sûrement y avoir un moyen de lui dire, "d'appliquer ce code exact du changement à partir de ce commit, sauf de ne pas où il était mais où il est maintenant dans ce nouveau fichier".
- Pas exactement le même, mais ici, c'est une question similaire, avec une bonne anwsers qui pourraient s'appliquer: stackoverflow.com/questions/2701790/...
- Aucune des réponses pour tenter d'expliquer pourquoi git n'est pas en mesure d'effectuer des fusions comme cela automatiquement. Je pensais que c'était censé être assez intelligent pour détecter renomme et effectuer la fusion automatiquement?
- Peut-être que ce n'était pas vrai, lorsque la question a été posée, mais les versions modernes de git (je suis en utilisant 1.9.5) peut fusionner des modifications à l'ensemble de renommé et déplacé des fichiers. Il y a même un
--rename-threshold
option pour ajuster le degré de similarité qui est nécessaire. - qui ne fonctionnera que si vous le faites à la vanille, rebase de l'amont de la branche, mais vous devez toujours exécuter des ennuis si vous êtes la cueillette de cerises ou de retour-le transfert d'une série de changements qui peuvent ne pas inclure le commit qui renomme les fichiers.
Vous devez vous connecter pour publier un commentaire.
J'ai eu un problème similaire, et je résolus par la relocalisation de mon travail pour correspondre à la cible de l'organisation des fichiers.
Dire que vous avez modifié
original.txt
sur votre branche (lalocal
branche), mais sur la branche master,original.txt
a été copié à un autre, direcopy.txt
.Cette copie a été faite dans un commit qui nous nom de commettre
CP
.Vous voulez appliquer toutes vos modifications locales, s'engage
A
etB
ci-dessous, qui ont été faites suroriginal.txt
, pour le nouveau fichiercopy.txt
.Créer un jetable branche
move
au point de départ de vos modifications avecgit branch move X
. C'est-à-dire, mettre lemove
direction générale de commettreX
, celle d'avant les commits que vous souhaitez fusionner; le plus probable, c'est l'engager à partir de laquelle vous ramifié pour appliquer vos modifications. En tant qu'utilisateur @digory doo écrit ci-dessous, vous pouvez fairegit merge-base master local
pour trouverX
.Sur cette branche, l'émission d'un renommage de commande:
Cette renomme le fichier. Notez que
copy.txt
n'existe pas encore dans votre arbre à ce point.Validez vos changements (nous le nom de ce commit
MV
).Vous pouvez maintenant rebase votre travail sur le dessus de
move
:Cela devrait fonctionner sans problème, et vos modifications sont appliquées à
copy.txt
dans votre succursale locale.Maintenant, vous n'avez pas forcément envie ou le besoin d'avoir de s'engager
MV
dans votre branche principale de l'histoire, parce que l'opération de déplacement peut entraîner un conflit avec l'opération de copie à commettreCP
dans la branche principale.Vous n'avez qu'à rebase votre travail encore une fois, en supprimant l'opération de déplacement, comme suit:
... où
CP
est le commit oùcopy.txt
a été introduit dans l'autre branche.Cette rebases tous les changements sur
copy.txt
sur le dessus de laCP
commettre.Maintenant, votre
local
branche est exactement comme si vous avez toujours modifiécopy.txt
et pasoriginal.txt
, et vous pouvez continuer à fusionner avec d'autres.Il est important que les modifications sont appliquées sur
CP
ou autrementcopy.txt
n'existerait pas et les modifications seront appliquées suroriginal.txt
.Espère que c'est clair.
Cette réponse est tardive, mais cela peut être utile à quelqu'un d'autre.
patch
(ce qui implique aussi potentiellement beaucoup de travail), et c'est pourquoi j'ai pensé qu'il pourrait être intéressant de le montrer. Notez également que j'ai pris plus de temps pour écrire la réponse que de réellement appliquer les modifications, dans mon cas. À quelle étape serait de vous la recommander à l'aide d'une fusion? et pourquoi? La seule différence que je vois est que par la relocalisation, je fais un temporaire s'engager c'est plus tard rejeté (commitMV
), ce qui n'est pas possible avec des fusions.git merge local
demove
, puis manuellement copier le fichier d'originelocal
branche. Cela a git de faire moins de travail pour vous (vous êtes en copiant manuellement le fichier), mais il sera plus facile parce que les conflits de fusion sont plus simples lors de la fusion que lors de l'année de référence.local
demove
, en effet, et puis déplacez le fichier. Dans la pratique, cela dépend du contexte et de goût. Je voudrais juste souligner que ces rebase opérations sont peu susceptibles d'introduire des conflits par eux-mêmes (il peut y avoir conflit entrelocal
etmaster
par la suite, mais c'est une autre question). Merci de bien vouloir accepter cette réponse 🙂git checkout move -- file
.local
deX
àCP
, et malheureusement, si cela est le cas, cela dépend du contexte réel; ensuite, vous pouvez décider qu'il est plus efficace de copier le fichier résultant, ou tout ce qui fonctionne, que pour résoudre chaque conflit dans le rebase. Je ne débattrai pas, car cela pourrait être le bon choix dans la pratique.copy.txt
réellement existé à l'avance et il a été remplacé par leCP
engager?git rebase move local
. Suis-je en train de faire quelque chose de mal?Vous pouvez toujours utiliser
git diff
(ougit format-patch
) pour générer le patch, puis aller modifier manuellement les noms de fichiers dans le patch, et de l'appliquer avecgit apply
(ougit am
).À court de cela, le seul moyen c'est d'aller travailler est automatiquement si git renommer détection peut comprendre que les anciens et les nouveaux fichiers sont la même chose - on dirait qu'ils ne sont pas vraiment dans votre cas, seulement une partie d'entre eux. C'est vrai que git utilise les gouttes, pas les fichiers, mais un blob est juste le contenu d'un dossier complet, sans le nom de fichier et les métadonnées attachées. Donc, si vous avez un morceau de code de déplacés entre les deux fichiers, ils ne sont pas vraiment les mêmes blob - le reste de la goutte du contenu est différent, tout le morceau en commun.
git format-patch
de travail pour une livraison. Si je negit format-patch SHA1
, il génère tout un tas de fichiers de correctif pour l'ensemble de l'histoire. Mais je suppose quegit show SHA1 > diff.patch
fonctionnera tout aussi bien.-1
option. En mode de fonctionnement normal pour format-patch est une révision de la gamme, commeorigin/master..master
, de sorte que vous pouvez facilement préparer un patch de la série.git apply
etgit am
sont trop pointilleux, parce qu'ils veulent la même chose sur les numéros de ligne. Mais je suis actuellement en train de réussir avec les UNIXpatch
de commande.Ici est un de fusion solution de la rencontre d'un conflit de fusion avec les renommer et de les éditer et de les résoudre avec mergetool reconnaissance de la bonne 3 fusionner des fichiers source.
Après une fusion échoue en raison de "supprimer le fichier' que vous vous rendez compte a été renommé et modifié:
De plain-pied à travers:
Créer un file.txt:
Créer une branche où vous pourrez modifier par la suite:
Créer les renommer et de les éditer sur le master:
Swap de la direction générale, et de modifier par là aussi:
Tentative de fusion de maître:
Avis le conflit est difficile à résoudre et que les fichiers ont été renommés. Abandonner, imiter le renommer:
Essayer de fusionner de nouveau:
Grand! Fusionner les résultats à un niveau "normal" les conflits qui peuvent être résolus avec mergetool:
B.txt -> C.txt
etA.txt -> B.txt
avec git mv, et git ne pouvait pas s'adapter automatiquement les conflits de fusion correctement (a été d'obtenir des conflits de fusion entre les anciensB.txt
et de nouvellesB.txt
). En utilisant cette méthode, les conflits de fusion sont maintenant entre les fichiers corrects.