Ajouter le changement à un commit précédent avec Magit

44

J'ai 2 commits, A puis B, prêt à être poussé. Je réalise que j'ai oublié d'ajouter quelque chose en A.

Comment puis-je ajouter ce changement à A en utilisant Magit? Je ne sais même pas quelle partie de la documentation Git je devrais regarder.

Mathieu Marques
la source

Réponses:

69

Supposons un instant que vous souhaitiez ajouter quelque chose au HEADcommit, c'est-à-dire "le second commit B" dans votre exemple.

Le popup de commit sur ccomporte un lien " aAmend". Appuyez sur cette touche pour "modifier" les modifications apportées au HEADcommit. Comme les commits ne sont pas modifiables dans Git, cela remplacera l'ancien commit par un nouveau commit. Un tampon avec l'ancien message de validation apparaîtra afin que vous puissiez le modifier si le changement ajouté nécessite également que vous ajustiez le message. Comme toujours, appuyez sur C-c C-clorsque vous avez terminé de modifier le message. Cela équivaut à une exécution git commit --amendsur la ligne de commande.

  • a Amend - ajoute les modifications planifiées et modifie HEADson message de validation

Comme il arrive souvent que vous ne deviez ajuster que la modification ou le message, Magit propose deux variantes supplémentaires:

  • e Étendre - ajouter les modifications planifiées à HEADsans modifier le message de validation
  • w Reformuler - change le message de HEADsans lui ajouter les modifications programmées

Lorsque vous voulez éditer un commit qui ne l’est pas HEAD, cela ne fonctionne pas. Ces commandes toujours "modifier" (c'est-à-dire remplacer) le HEADcommit. Git ne fournit pas une seule commande pour modifier un commit HEAD, c'est donc un peu plus compliqué.

Magit ne fournissent une telle commande, mais parce qu'il ya des situations où il est préférable de le faire en plusieurs étapes, nous allons discuter de cette première.

Modifier un commit autre que HEADpeut être divisé en trois étapes:

  1. Rendre temporairement cet autre commit ( A) le HEAD.
  2. Modifiez le HEAD(comme décrit ci-dessus), entraînant une validation A'.
  3. Dites à Git de réappliquer les commits qui ont suivi A, mais en plus de A'.

Cela peut être fait en utilisant une base interactive. Tapez rpour afficher la popup de rebase. Tapez ensuite mpour appeler la variante de base "edit a commit". Un tampon avec les commits récents apparaît. Déplacez-vous sur le commit que vous souhaitez modifier et tapez C-c C-cpour le sélectionner. Git rembobine ensuite l'historique dans cette validation et affiche des informations sur la base en cours dans le tampon d'état.

Modifier HEADcomme décrit ci-dessus. Puis dites à Git que vous avez terminé en tapant r r. Si A'et Bconflit alors rebase s'arrête à Bet vous devez résoudre le conflit. Une fois que vous avez terminé, appuyez sur r rpour continuer.

Si vous savez que vos modifications Aentraîneront des conflits B, procédez comme indiqué ci-dessus, sinon utilisez l’approche suivante.


Git permet de créer des "correctifs" avec git commit --fixup A. Cela crée un nouveau commit, qui enregistre les modifications qui "auraient dû être effectuées dans un autre commit". Ce commit devient le nouveau HEAD. Il existe aussi une --squashvariante. Pour plus d'informations sur les différences, voir la git-commitpage de manuel.

Pour combiner réellement le Acommit et le nouveau commit A', puis réappliquer Bpar dessus, vous devez utiliser rebase. Magit fournit une commande pratique pour le faire r f.

La principale différence par rapport à l'approche ci-dessus est qu'ici, nous créons d'abord un nouveau commit, puis nous rebasonnons pour combiner cela avec la "cible" et refaire une nouvelle demande B. Ci-dessus, nous avons commencé par rebasonner au lieu de commettre.

Dans Magit --fixup, les --squashvariantes et sont disponibles dans la fenêtre de validation, sur fet s. Mais Magit fournit également des variantes "instantanées" des commandes fixup et squash sur Fet S. Ces variantes créent un nouveau commit, comme les variantes "non instantanées", mais elles combinent ensuite instantanément le commit de correction avec le commit cible en utilisant rebase, sans que vous ayez à appeler une autre commande.

"Instant fixup" ( c F) est essentiellement la même chose que "extend HEAD" ( c e), sauf que cela fonctionne pour n'importe quel commit, pas seulement HEAD.


Lectures complémentaires:

tarse
la source
Clair comme de l'eau de roche! Merci, forfait génial BTW.
Mathieu Marques
1
Eh bien, je pense qu'il y a des parties détrempées dans la seconde moitié de ma réponse. Mais pour les éviter, il faudrait doubler la longueur de cette réponse déjà longue. Je suis donc ravi que cela fonctionne pour vous ;-)
tarsius
Merci pour cette réponse, Tarsius, cela fonctionne vraiment pour moi.
anquegi
La clarté de la première moitié de cette explication rend la lecture de la seconde partie beaucoup plus difficile à suivre, assez frustrante!
Lyn Headley
git-commitLa page de manuel redirige vers git-rebase(1)les lignes suivantes: Le message de validation suggéré pour la validation pliée est la concaténation des messages de validation de la première validation et de ceux avec la commande "squash", mais en omettant les messages de validation des validations avec la "correction". commander. IOW, utilisez fixup si vous souhaitez simplement corriger le code de la précédente validation, utilisez squash si vous souhaitez également corriger le message de validation.
Yasushi Shoji
3

git commit --amend –C HEADest la commande Git que vous souhaitez rechercher et avec laquelle vous pouvez faire des corrections dans Magit C-c C-a.

Ryan
la source
J'utilise la dernière version de Magit, elle C-c C-aprovient d'une version plus ancienne (je pense). De plus, je ne vois aucune trace de "modifier" dans le tampon d’aide ( ?).
Mathieu Marques
Voir la réponse de Rémi pour l'équivalent magit 2.x.
npostavs
3

Donc, un flux de travail est:

  • faire votre monnaie
  • c (commit) f (fixup - sélectionnez commit votre correction)

ensuite

  • r (rebase) -a (autosquash, peut être paramétré par défaut) i (interactif)

L’autosquash déplacera automatiquement tous les comm! Fixup au bon endroit et les configurera pour être écrasés sur la base.

stsquad
la source
La seule chose que j'ai faite et que vous n'avez pas dite, c'est de jouer entre votre première balle et la seconde. Frapper ime rapporte Cannot rebase: Your index contains uncommitted changes. Please commit or stash them.. Sauf que je n'ai pas de modifications non validées. : /
Mathieu Marques
J'ai essayé à nouveau après avoir tiré, Proceed despite merge in rebase range? [c]ontinue, [s]elect other, [a]bort. Est-ce qu'il essaie de me dire que ma réparation pourrait faire caca lors de la prochaine fusion?
Mathieu Marques
@MathieuMarques: "Sauf que je n'ai aucune modification non validée", pense Git. Notez que le message suggère des modifications progressives et non des modifications non mises en scène. Re merge in rebase:, voir BOGUES sous git help rebase. Je suggère de faire la réparation avant de tirer en amont.
npostavs
1

Pour amender le dernier commit, c'est "c a". La correction sert à amender certains anciens commit.

Rémi
la source
Quel est le cas, j'ai commis A puis B. Post mis à jour pour plus de clarté.
Mathieu Marques