105 votes

Comment changer un commit passé pour inclure un fichier manqué ?

J'ai validé une modification et j'ai oublié d'ajouter un fichier à l'ensemble des modifications. Après d'autres commits, j'ai réalisé que le fichier est maintenant absent d'un ensemble de modifications. HEAD^4 commettre.

Comment réécrire un commit précédent pour inclure le fichier manquant ?

287voto

Dr Beco Points 1668

Je réalise que les gens peuvent chercher sur Google et venir ici pour trouver une réponse plus simple : Et si c'était juste la dernière livraison ? (La question de l'OP concerne la correction du 4ème commit de l'histoire)

Dans le cas où vous commettez et réalisez que vous avez oublié d'ajouter un fichier immédiatement fais-le :

# edited file-that-i-remember.txt
git add file-that-i-remember.txt
git commit

# realize you forgot a file
git add file-that-i-forgot.txt
git commit --amend --no-edit

--no-edit conservera le même message de validation.

C'est facile !

59voto

Rafał Rawicki Points 10069

Utilisez git rebase --interactive HEAD~4 et mettre edit pour le commit que vous souhaitez modifier.

N'oubliez pas que vous ne devrait pas modifier les commits poussés vers le dépôt distant de cette façon. Il est préférable d'ajouter un nouveau commit avec le fichier manquant dans ce cas.


Pour que cela soit plus clair, il faut d'abord cacher les modifications en cours avec git stash . Alors, git rebase --interactive HEAD~4 . Vous obtenez ce qui suit dans un éditeur de texte (notez que vous obtiendrez 5 commits, dans l'ordre décroissant) :

pick 123e123 fifth last commit message
pick 321e122 fourth last commit message
pick 1d23e3f third last commit message
pick 987a987 second last commit message
pick 8a8a8a8 last commit message

Modifier le préfixe de l'entrée de changement de pick a edit . Ce serait edit 321e122 ... pour le PO.

git rebase passe en revue les entrées, dans l'ordre. Comme nous n'en changeons qu'une, vous n'aurez qu'une seule entrée à modifier. Maintenant, ajoutez vos fichiers avec git add y git commit --amend pour modifier le commit actuel avec ces fichiers ajoutés.

Enfin, git rebase --continue passe au fichier suivant. Comme il n'y en a qu'un, le rebasement est terminé.

13voto

mvp Points 29360

Si vous n'avez PAS poussé ces 4 commits, vous pouvez le faire comme suit :

Créez des fichiers patch pour tous ces commits :

git format-patch -4

Retour en arrière de 4 engagements :

git reset --hard HEAD~4

Ajouter le fichier manquant :

git add missing-file

Engagez-le avec --amend :

git commit --amend

Réappliquez tous les correctifs sauvegardés :

git am *.patch

Si vous avez poussé, vous ne devez PAS utiliser cette méthode. Au lieu de cela, admettez simplement votre erreur et créez un commit supplémentaire au-dessus de HEAD qui corrige ce problème.

9voto

dominik Points 861

Bien que la réponse acceptée soit correcte, elle ne contient pas d'instructions détaillées sur la façon de modifier un commit pendant un processus de rebasement.

  • Tout d'abord, lancez un processus de rebasement :

    git rebase --interactive HEAD~4
  • Une liste de commits sera présentée, choisissez un commit que vous voulez modifier en changeant le mot pick a edit et enregistrez le fichier.

  • Apportez les modifications nécessaires à votre code (n'oubliez pas d'invoquer la fonction git add pour les nouveaux fichiers)

  • Une fois que toutes les modifications ont été effectuées, émettez git commit --amend - ceci modifiera un commit marqué comme edit

  • Appeler git rebase --continue qui terminera le processus (s'il y a plus de commits marqués en tant que edit les étapes ci-dessus doivent être répétées)

Notes importantes :

  • NE PAS supprimer les lignes marquées comme pick que vous ne voulez pas modifier - laissez-les telles quelles. La suppression de ces lignes aura pour conséquence la suppression des commits associés.

  • GIT vous oblige à stash avant de rebaser si votre répertoire de travail n'est pas propre ; vous pouvez cependant git stash pop / git stash apply pendant le rebasement, afin d'amender ces changements (c'est-à-dire les changements cachés avant le début du processus de rebasement) vers un commit marqué en tant que edit

  • si quelque chose s'est mal passé et que vous voulez annuler les changements effectués pendant le processus de rebasement avant qu'il ne soit terminé (c'est-à-dire que vous voulez revenir au point précédant le début du rebasement), utilisez la méthode suivante git rebase --abort - lire aussi : Comment interrompre un rebasement interactif si --abort ne fonctionne pas ?

  • Comme indiqué dans la réponse acceptée :

    Rappelez-vous que vous ne devez pas modifier les commits poussés vers le référentiel distant de cette façon. Il est préférable d'ajouter un nouveau commit avec le fichier manquant dans ce cas.

    La réponse à cette question se trouve dans le Livre Git (paragraphe intitulé " Les dangers du rebasage ") :

    Ne pas rebaser les commits qui existent en dehors de votre référentiel.

    Si vous suivez cette ligne directrice, tout ira bien. Si vous ne le faites pas, les gens vous détesteront, et vous serez méprisé par vos amis et votre famille.

    Lorsque vous rebasez des choses, vous abandonnez des commits existants et en créez de nouveaux qui sont similaires mais différents. Si vous poussez des commits quelque part et que d'autres les descendent et basent leur travail dessus, puis que vous réécrivez ces commits avec git rebase et que vous les repoussez à nouveau, vos collaborateurs devront fusionner leur travail et les choses se compliqueront lorsque vous essaierez de réintégrer leur travail dans le vôtre.

    [...]

0voto

Dennis Points 600

Voici un exemple non interactif rebase approche.

Cela nécessite un commit supplémentaire (et ne permet donc pas de "réécrire un commit précédent" comme demandé par le PO), mais je trouve cela plus facile à retenir.

État initial :

* e834111 (HEAD -> master) do something that depends on file x
* 6dde62a do stuff, forget to add file x
...

Etape 1 - vérifier une nouvelle branche temporaire au commit qui aurait dû inclure le fichier ( git checkout -b temp 6dde ):

* e834111 (master) do something that depends on file x
* 6dde62a (HEAD -> temp) do stuff, forget to add file x
...

Étape 2 - add le fichier manquant et commit :

* 50d1412 (HEAD -> temp) add file x
| * e834111 (master) do something that depends on file x
|/  
* 6dde62a do stuff, forget to add file x
...

Étape 3 - vérifier la branche originale et rebase sur temp :

* dd6f2dd (HEAD -> master) do something that depends on file x
* 50d1412 (temp) add file x
* 6dde62a do stuff, forget to add file x
...

Étape 4 - supprimer la branche temporaire ( git branch -d temp )

Note : Ceci peut aussi être fait sans créer de branche temporaire, en utilisant par exemple git checkout 6dde suivi d'un commit y rebase sur la tête détachée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X