Créer un patch git à partir des modifications dans le répertoire de travail actuel

880

Disons que j'ai des modifications non validées dans mon répertoire de travail. Comment puis-je créer un patch à partir de ceux-ci sans avoir à créer de commit?

vrish88
la source
29
La réponse acceptée devrait probablement être modifiée, étant donné que la deuxième réponse est presque quatre fois plus populaire.
Tim Ogilvy
5
@TimOgilvy a accepté. OP devrait le faire. La deuxième réponse est beaucoup plus populaire et donne plus d'informations
John Demetriou
1
Je pense qu'il vaut la peine de mentionner que vous avez besoin d'un correctif contre les modifications non validées du titre.
2i3r

Réponses:

401

git diffpour les modifications non mises en scène. git diff --cachedpour les changements par étapes.

sigjuice
la source
12
yup, git diff est l'inverse de git apply
Spike Gronim
33
git format-patchcomprend également des différences binaires et quelques méta-informations. En fait, ce serait le meilleur pari pour créer un patch, mais afaik, cela ne fonctionne que pour les sources / modifications enregistrées, non?
Eric
20
Parfois, il peut être utile de créer un patch par rapport au répertoire courant. Pour ce faire, utilisezgit diff --relative
ejboy
30
git diff> a.patch pour l'écrire dans un fichier
qasimzee
139
Verset bordant le sarcastique, la réponse ci-dessous est plus utile.
Air
1865

Si vous n'avez pas encore validé les modifications, alors:

git diff > mypatch.patch

Mais parfois, il arrive qu'une partie des choses que vous faites sont de nouveaux fichiers qui ne sont pas suivis et ne seront pas dans votre git diffsortie. Donc, une façon de faire un patch est de tout mettre en scène pour un nouveau commit ( git addchaque fichier, ou juste git add .) mais ne faites pas le commit, puis:

git diff --cached > mypatch.patch

Ajoutez l'option «binaire» si vous souhaitez ajouter des fichiers binaires au patch (par exemple des fichiers mp3):

git diff --cached --binary > mypatch.patch

Vous pouvez ensuite appliquer le patch:

git apply mypatch.patch

Remarque: Vous pouvez également utiliser --stagedcomme synonyme de --cached.

jcarballo
la source
128
Merci beaucoup pour l'exemple. Contrairement à la réponse acceptée, vous montrez aux commandes comment le faire et pas seulement à parler. Très utile et a fonctionné sans faille pour moi :)
nuala
4
J'ai fait exactement cela et j'ai obtenu "fatal: entrée non reconnue" lors de l'exécution de git apply. Une idée de ce qui peut provoquer cela et comment y remédier?
Vitaly
6
@Vitaly: votre patch est-il lisible si vous l'ouvrez avec un éditeur de texte? il doit être propre et sans caractères étranges, par exemple si le paramètre color.diff est défini, votre patch aura des «caractères de couleur» qui peuvent faire échouer «git apply», dans ce cas essayez git diff --no-color. Sinon, cela ressemble à un problème d'encodage.
jcarballo
3
Concernant les "nouveaux fichiers non suivis": "git diff" et "git diff --cached" ne fonctionnent que si "git add <file>" a été appelé en premier. (Je suis nouveau sur git et je me demandais pourquoi j'avais un patch vide à chaque fois)
Anonyme
5
Cela m'a fait sortir d'un enfer étrange de fusion / rebase assez facilement, merci :)
John Hunt
86

git diffet git applyfonctionnera pour les fichiers texte, mais ne fonctionnera pas pour les fichiers binaires.

Vous pouvez facilement créer un patch binaire complet, mais vous devrez créer un commit temporaire. Une fois que vous avez effectué vos validations temporaires, vous pouvez créer le patch avec:

git format-patch <options...>

Après avoir créé le correctif, exécutez cette commande:

git reset --mixed <SHA of commit *before* your working-changes commit(s)>

Cela annulera vos validations temporaires. Le résultat final laisse votre copie de travail (intentionnellement) sale avec les mêmes modifications que vous aviez à l'origine.

Côté réception, vous pouvez utiliser la même astuce pour appliquer les modifications à la copie de travail, sans avoir l'historique de validation. Appliquez simplement le (s) patch (s) et git reset --mixed <SHA of commit *before* the patches>.

Notez que vous devrez peut-être être bien synchronisé pour que cette option fonctionne. J'ai vu des erreurs lors de l'application de correctifs alors que la personne qui les fabriquait n'avait pas supprimé autant de modifications que moi. Il y a probablement des moyens de le faire fonctionner, mais je n'y suis pas allé bien loin.


Voici comment créer les mêmes correctifs dans Tortoise Git (pas que je recommande d'utiliser cet outil):

  1. Validez vos changements de travail
  2. Cliquez avec le bouton droit sur le répertoire racine de la branche et cliquez sur Tortoise Git->Create Patch Serial
    1. Choisissez la plage la plus appropriée ( Since: FETCH_HEADfonctionnera si vous êtes bien synchronisé)
    2. Créer le (s) patch (s)
  3. Cliquez avec le bouton droit sur le répertoire racine de la branche et cliquez sur Tortise Git->Show Log
  4. Cliquez avec le bouton droit sur la validation avant vos validations temporaires, puis cliquez surreset "<branch>" to this...
  5. Sélectionnez l' Mixedoption

Et comment les appliquer:

  1. Cliquez avec le bouton droit sur le répertoire racine de la branche et cliquez sur Tortoise Git->Apply Patch Serial
  2. Sélectionnez le ou les correctifs appropriés et appliquez-les
  3. Cliquez avec le bouton droit sur le répertoire racine de la branche et cliquez sur Tortise Git->Show Log
  4. Cliquez avec le bouton droit sur la validation avant les validations du correctif, puis cliquez surreset "<branch>" to this...
  5. Sélectionnez l' Mixedoption
Merlyn Morgan-Graham
la source
5
Techniquement, cela nécessite de créer une validation que OP a demandé d'éviter, mais elle est temporaire et la réponse est utile malgré tout.
davenpcj
33

Pour créer un patch avec à la fois des fichiers modifiés et nouveaux (par étapes), vous pouvez exécuter:

git diff HEAD > file_name.patch
Ionel Sirbu
la source
Merci, dans mon cas, cette réponse fonctionne, mais git diff --cached > mypatch.patchne fonctionne pas.
exploitation minière le
J'ai une question: peut file_name.patchêtre utilisé par la patchcommande? Sont-ils compatibles entre eux?
Rakshith Ravi
git diff + git diff --cached / staged == git diff HEAD (affiche toutes les modifications depuis le dernier commit)
K. Symbol
20

J'aime:

git format-patch HEAD~<N>

<N>est le nombre de dernières validations à enregistrer en tant que correctifs.

Les détails sur l'utilisation de la commande se trouvent dans le DOC

UPD
Ici, vous pouvez trouver comment les appliquer ensuite.

UPD Pour ceux qui n'ont pas eu l'idée d' format-patch
ajouter un alias:

git config --global alias.make-patch '!bash -c "cd ${GIT_PREFIX};git add .;git commit -m ''uncommited''; git format-patch HEAD~1; git reset HEAD~1"'

Ensuite, dans n'importe quel répertoire de votre référentiel de projet, exécutez:

git make-patch

Cette commande créera 0001-uncommited.patchdans votre répertoire actuel. Le correctif contiendra toutes les modifications et les fichiers non suivis qui sont visibles pour la commande suivante:

git status .
Eugen Konkov
la source
@jcarballo: J'ai mis à jour la réponse. N'hésitez pas à m'envoyer tous les avis que vous avez.
Eugen Konkov
2
Il existe un moyen plus simple que de créer un commit et de ne pas s'engager. git diff --cached --binary
Gaurav Agarwal
9

Si vous voulez faire du binaire, donnez une --binaryoption lorsque vous exécutez git diff.

gitster
la source
0

Nous pourrions également spécifier les fichiers, pour inclure uniquement les fichiers avec des changements relatifs, en particulier lorsqu'ils s'étendent sur plusieurs répertoires ex

git diff ~/path1/file1.ext ~/path2/file2.ext...fileN.ext > ~/whatever_path/whatever_name.patch

J'ai trouvé que cela n'était pas spécifié dans les réponses ou les commentaires, qui sont tous pertinents et corrects, j'ai donc choisi de l'ajouter. Explicite vaut mieux qu'implicite!

Anshu Kumar
la source