J'ai deux référentiels. Dans l'un, je modifie le fichier ./hello.test
. Je valide les modifications et crée un patch à partir de ce commit avec git format-patch -1 HEAD
. Maintenant, j'ai un second référentiel qui contient un fichier qui a le même contenu que hello.test mais est placé dans un autre répertoire sous un autre nom: ./blue/red/hi.test
. Comment puis-je appliquer le correctif susmentionné au hi.test
fichier? J'ai essayé git am --directory='blue/red' < patch_file
mais cela se plaint bien sûr que les fichiers ne sont pas nommés de la même manière (ce qui ne me préoccupait pas de Git?). Je sais que je pourrais probablement modifier le diff pour l'appliquer à ce fichier spécifique, mais je recherche une solution de commande.
100
Réponses:
Vous pouvez créer le correctif à l'aide de
git diff
, puis l'appliquer à l'aide de l'patch
utilitaire, qui vous permet de spécifier le fichier auquel vous souhaitez appliquer la différence.Par exemple:
la source
am
ouapply
, mais je ne le trouve pas. Si vous vous retrouvez à dupliquer beaucoup les modifications, il pourrait y avoir une meilleure solution en utilisant des sous-modules, ou tout ce que votre choix de langue fournit pour partager du code (par exemple, dans Ruby, vous pouvez extraire le code dupliqué sous forme de gemme).Il existe une solution simple qui n'implique pas d'édition manuelle de patch ni de script externe.
Dans le premier référentiel (cela peut également exporter une plage de commit, utilisez
-1
si vous ne voulez sélectionner qu'un seul commit):Dans le deuxième référentiel:
Au lieu d'utiliser
--relative
ingit format-patch
, une autre solution consiste à utiliser l'-p<n>
option ingit am
pour supprimer lesn
répertoires du chemin des correctifs, comme mentionné dans une réponse à une question similaire .Il est également possible de s'exécuter
git format-patch --relative <committish>
sans le--stdout
, et cela générera un ensemble de.patch
fichiers. Ces fichiers peuvent ensuite être alimentés directementgit am
avecgit am --directory blue/red/ path/to/*.patch
.la source
--directory
option semble vous obliger à spécifier le chemin complet du répertoire par rapport à la racine du dépôt; quelque chose comme--directory=./
while chdir'd dans un sous-répertoire du dépôt ne fonctionnera pas.--3way
aides avecdoes not exist in index
:git am --3way --directory (relative-path) (patch)
-k
clé dans les deux commandes pour ne pas supprimer la première ligne du message de validation.--3way
non seulement aide à résoudre les erreurs "n'existe pas dans l'index" (comme indiqué par @nobar), mais vous permet également de gérer proprement les conflits de fusion. Au lieu de laisser les fichiers en conflit intacts, un bloc de conflit est ajouté qui peut ensuite être résolu.Répondre à ma propre question avec un script qui fait exactement cela: https://github.com/mprpic/apply-patch-to-file
Plutôt que de modifier le fichier de correctif manuellement, il demande à l'utilisateur le fichier cible, modifie le correctif et l'applique au dépôt dans lequel vous vous trouvez actuellement.
la source
Sur la base de la réponse de @georgebrock, voici une solution que j'ai utilisée:
Commencez par créer les fichiers de patch comme d'habitude (par exemple
git format-patch commitA..commitB
).Assurez-vous ensuite que votre référentiel cible est propre (il ne devrait y avoir aucun fichier modifié ou non suivi) et appliquez les correctifs comme ceci:
Pour chaque fichier de correctif, vous obtiendrez une erreur du type "erreur: XYZ n'existe pas dans l'index". Vous pouvez maintenant appliquer ce fichier de correctif manuellement:
Vous devez effectuer ces trois étapes pour chaque fichier de correctif.
Cela conservera le message de validation d'origine, etc. sans nécessiter de
git format-patch
commande spéciale ni modifier les fichiers de patch.la source
git format-patch -1 commitA --stdout > thing.diff
; (2) Modifiez le fichier de patch jusqu'à ce qu'il fasse ce dont j'ai besoin; (3) Texte à validergit am --3way thing.diff
qui présente l'avantage que vous pouvez accepter les parties du correctif qui s'appliquent proprement, et utilisergit
le processus de résolution de conflit standard pour les parties qui ne le font pas.Je comprends que les deux fichiers sont exactement les mêmes dans votre situation, donc le correctif est susceptible de réussir.
Cependant, si vous souhaitez appliquer un correctif à un fichier similaire, mais pas exactement le même, ou si vous souhaitez effectuer un correctif interactif, vous utiliserez la fusion à trois.
Supposons que vous ayez modifié le fichier
A
, désignonsA~1
la version précédente et que vous souhaitiez appliquer la différence entreA~1
à etA
au fichierB
.Ouvrez un outil de fusion à trois voies, par exemple Au-delà de la comparaison, le chemin du panneau de gauche est
A
, le panneau du milieu est l'ancêtre commun donc le chemin estA~1
, le chemin du panneau de droite estB
. Ensuite, le panneau inférieur affiche le résultat de l'application de la différence entreA~1
àA
dans un fichierB
.La figure suivante illustre l'idée.
la source
FYI: J'ai récemment eu des problèmes en essayant de télécharger un correctif depuis Github et de l'appliquer à un fichier local (qui était un «remplacement» dans un nouvel emplacement).
git am
n'appliquerait pas le correctif non plus parce que le fichier n'était «pas dans l'index» ou «sale». Mais, j'ai trouvé que la simplepatch
commande pouvait appliquer le correctif. Cela m'a demandé le nom du fichier à corriger.J'ai fait le travail, de toute façon ...
la source