Comment modifier un commit spécifié dans git?

Je soumets généralement une liste de commits pour examen. Si j’ai:

  • HEAD
  • Commit3
  • Commit2
  • Commit1

Je sais que je peux modifier head commit avec git commit --amend , mais comment puis-je modifier Commit1 , étant donné que ce n’est pas le commit HEAD ?

Vous pouvez utiliser git rebase, par exemple, si vous souhaitez modifier en arrière pour valider bbc643cd , exécutez

 $ git rebase --interactive 'bbc643cd^' 

Dans l’éditeur par défaut, modifiez pick pour edit dans la ligne dont vous souhaitez modifier le commit. Apportez vos modifications et validez-les avec le même message que vous aviez auparavant:

 $ git commit --all --amend --no-edit 

modifier le commit et après cela

 $ git rebase --continue 

revenir à l’engagement de tête précédent.

AVERTISSEMENT : Notez que cela changera le SHA-1 de cette validation ainsi que tous les enfants – en d’autres termes, cela réécrira l’historique à partir de ce moment. Vous pouvez casser les repos en faisant cela si vous appuyez en utilisant la commande git push --force

Utilisez le rebase interactif génial:

 git rebase -i @~9 # Show the last 9 commits in a text editor 

Trouvez le commit souhaité, changez le pick en e ( edit ) et enregistrez et fermez le fichier. Git reviendra sur ce commit, vous permettant de:

  • utiliser git commit --amend pour apporter des modifications, ou
  • Utilisez git reset @~ pour ignorer le dernier commit, mais pas les modifications apscopes aux fichiers (c’est-à-dire vous amenez au point où vous étiez lorsque vous avez édité les fichiers, mais que vous ne les avez pas encore validés).

Ce dernier est utile pour faire des choses plus complexes, comme la division en plusieurs commits.

Ensuite, lancez git rebase --continue , et Git git rebase --continue les modifications suivantes en plus de votre commit modifié. Vous pouvez être invité à résoudre certains conflits de fusion.

Remarque: @ est un raccourci pour HEAD et ~ est la validation avant la validation spécifiée.

En savoir plus sur la réécriture de l’historique dans les documents Git.

N’ayez pas peur de rebaser

ProTip ™: n’ayez pas peur d’expérimenter des commandes “dangereuses” qui réécrivent l’historique * – Git ne supprime pas vos commits pendant 90 jours par défaut; vous pouvez les trouver dans le reflog:

 $ git reset @~3 # go back 3 commits $ git reflog c4f708b HEAD@{0}: reset: moving to @~3 2c52489 HEAD@{1}: commit: more changes 4a5246d HEAD@{2}: commit: make important changes e8571e4 HEAD@{3}: commit: make some changes ... earlier commits ... $ git reset 2c52489 ... and you're back where you started 

* Surveillez les options comme --hard et --force si – elles peuvent rejeter des données.
* En outre, ne réécrivez pas l’historique sur les twigs sur lesquelles vous collaborez.


Sur de nombreux systèmes, git rebase -i ouvrira Vim par défaut. Vim ne fonctionne pas comme la plupart des éditeurs de texte modernes, alors jetez un œil à la façon de le rebaser avec Vim . Si vous préférez utiliser un éditeur différent, modifiez-le avec git config --global core.editor your-favorite-text-editor .

Le rebase interactif avec --autosquash est quelque chose que j’utilise souvent lorsque je dois corriger des commits antérieurs plus en profondeur dans l’historique. Il accélère essentiellement le processus que la réponse de ZelluX illustre, et est particulièrement utile lorsque vous devez en modifier plusieurs.

De la documentation:

--autosquash

Lorsque le message du journal de validation commence par “squash! …” (ou “fixup! …”), et qu’il y a un commit dont le titre commence par le même…, modifiez automatiquement la liste de tâches de rebase -i pour que le commit marqué pour écrasement vient juste après le commit à modifier

Supposons que vous ayez une histoire qui ressemble à ceci:

 $ git log --graph --oneline * b42d293 Commit3 * e8adec4 Commit2 * faaf19f Commit1 

et vous avez des modifications que vous souhaitez modifier à Commit2 puis valider vos modifications en utilisant

 $ git commit -m "fixup! Commit2" 

Vous pouvez également utiliser le message commit-sha au lieu du message de validation, donc "fixup! e8adec4 ou même simplement un préfixe du message de validation.

Ensuite, lancez un rebase interactif sur le commit avant

 $ git rebase e8adec4^ -i --autosquash 

votre éditeur s’ouvrira avec les commits déjà correctement commandés

 pick e8adec4 Commit2 fixup 54e1a99 fixup! Commit2 pick b42d293 Commit3 

tout ce que vous avez à faire est de sauvegarder et de quitter

Courir:

$ git rebase --interactive commit_hash^

chaque ^ indique combien de commits vous souhaitez modifier, si ce n’est qu’un seul (le hash de validation que vous avez spécifié), alors vous en ajoutez simplement un ^ .

En utilisant Vim, vous changez les mots pick pour reword les commits que vous souhaitez modifier, sauvegarder et quitter ( :wq ). Ensuite, git vous invitera à chaque validation que vous avez marquée en tant que reword afin que vous puissiez modifier le message de validation.

Chaque message de validation que vous devez enregistrer et quitter ( :wq ) pour accéder au prochain message de validation

Si vous souhaitez quitter sans appliquer les modifications, appuyez sur :q!

EDIT : pour naviguer dans vim utilisez j pour monter, k pour descendre, h pour aller à gauche, et l pour aller à droite (tout cela en mode NORMAL , appuyez sur ESC pour passer en mode NORMAL ). Pour éditer un texte, appuyez sur i pour entrer dans le mode INSERT , où vous insérez du texte. Appuyez sur ESC pour revenir au mode NORMAL 🙂

MISE À JOUR : Voici un excellent lien de la liste github Comment annuler (presque) quelque chose avec git

Si pour une raison quelconque vous n’aimez pas les éditeurs interactifs, vous pouvez utiliser git rebase --onto .

Disons que vous voulez modifier Commit1 . Tout d’abord, Commit1 avant Commit1 :

 git checkout -b amending [commit before Commit1] 

Deuxièmement, prenez Commit1 avec le cherry-pick :

 git cherry-pick Commit1 

Commit1' maintenant vos modifications en créant Commit1' :

 git add ... git commit --amend -m "new message for Commit1" 

Et enfin, après avoir caché d’autres modifications, transformez le rest de vos commits en master sur votre nouveau commit:

 git rebase --onto amending Commit1 master 

Lisez: “rebase, sur la amending la twig, tous les commits entre Commit1 (non inclusif) et master (inclus)”. C’est-à-dire Commit2 et Commit3, en supprimant entièrement l’ancien Commit1. Vous pouvez simplement les choisir, mais cette façon est plus facile.

N’oubliez pas de nettoyer vos twigs!

 git branch -d amending 

Vient à cette approche (et c’est probablement exactement la même chose que l’utilisation de rebase interactif) mais pour moi, c’est un peu simple.

Note: Je présente cette approche pour illustrer ce que vous pouvez faire plutôt qu’une alternative quotidienne. Comme il comporte de nombreuses étapes (et peut-être quelques réserves).

Supposons que vous souhaitiez modifier le commit 0 et que vous soyez actuellement dans la feature-branch

 some-commit---0---1---2---(feature-branch)HEAD 

Checkout à ce commit et créer une quick-branch . Vous pouvez également cloner votre twig d’entités en tant que sharepoint récupération (avant de commencer).

 ?(git checkout -b feature-branch-backup) git checkout 0 git checkout -b quick-branch 

Vous allez maintenant avoir quelque chose comme ça:

 0(quick-branch)HEAD---1---2---(feature-branch) 

Changements de scène, ranger tout le rest.

 git add ./example.txt git stash 

Validez les modifications et revenez à la feature-branch

 git commit --amend git checkout feature-branch 

Vous allez maintenant avoir quelque chose comme ça:

 some-commit---0---1---2---(feature-branch)HEAD \ ---0'(quick-branch) 

Rebase la feature-branch sur quick-branch (résout tout conflit en cours de route). Appliquez la cachette et retirez quick-branch .

 git rebase quick-branch git stash pop git branch -D quick-branch 

Et vous vous retrouvez avec:

 some-commit---0'---1'---2'---HEAD(feature-branch) 

Git ne va pas dupliquer (bien que je ne puisse pas vraiment dire dans quelle mesure) le 0 s’engage lors du rebasage.

Remarque: tous les hachages de validation sont modifiés à partir de la validation que nous avions initialement l’intention de modifier.

Pour obtenir une commande non interactive, placez un script avec ce contenu dans votre PATH:

 #!/bin/sh # # git-fixup # Use staged changes to modify a specified commit set -e cmt=$(git rev-parse $1) git commit --fixup="$cmt" GIT_EDITOR=true git rebase -i --autosquash "$cmt~1" 

Utilisez-le en organisant vos modifications (avec git add ), puis lancez git fixup . Bien sûr, il sera toujours interactif si vous rencontrez des conflits.

Commande totalement non interactive (1)

Je pensais juste que je partagerais un alias que j’utilise pour cela. Il est basé sur un rebase interactif non interactif. Pour l’append à votre git, lancez cette commande (explication ci-dessous):

 git config --global alias.amend-to '!f() { SHA=`git rev-parse "$1"`; git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"; }; f' 

Le plus grand avantage de cette commande est le fait que ce soit sans vim .


(1) étant donné qu’il n’y a pas de conflit lors du rebase, bien sûr

Usage

 git amend-to  # eg git amend-to HEAD~1 git amend-to aaaa1111 

Le nom de l’ amend-to semble approprié à mon humble avis. Comparez le stream avec --amend :

 git add . && git commit --amend --no-edit # vs git add . && git amend-to  

Explication

  • git config --global alias. '!' – crée un alias global git nommé qui exécutera la commande non-git
  • f() { }; f f() { }; f – une fonction bash “anonyme”.
  • SHA=`git rev-parse "$1"`; – convertit l’argument en révision git et assigne le résultat à la variable SHA
  • git commit --fixup "$SHA" – correction de correction pour SHA . Voir les documents de git-commit
  • GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"
    • git rebase --interactive "$SHA^" partie a été couverte par d’autres réponses.
    • --autosquash est ce qui est utilisé en conjonction avec git commit --fixup , voir git-rebase pour plus d’informations
    • GIT_SEQUENCE_EDITOR=true est ce qui rend l’ensemble non interactif. Ce hack j’ai appris de cet article de blog .

Pour moi, c’était pour supprimer certaines informations d’identification d’un repository. J’ai essayé de me repasser et j’ai rencontré une tonne de conflits apparemment sans rapport tout au long du processus lorsque je tentais de me rebobiner – continuer. Ne vous embêtez pas à essayer de vous rebaser, utilisez l’outil appelé BFG (brew install bfg) sur mac.

J’ai résolu cela,

1) en créant de nouveaux commit avec les modifications que je veux ..

 r8gs4r commit 0 

2) Je sais quel engagement je dois fusionner avec elle. qui est commettre 3.

donc, git rebase -i HEAD~4 # 4 représente 4 commit récent (ici commit 3 est à la 4ème place)

3) dans le rebase interactif, les dernières commandes seront placées en bas. il se ressemblera,

 pick q6ade6 commit 3 pick vr43de commit 2 pick ac123d commit 1 pick r8gs4r commit 0 

4) Ici, nous devons réorganiser les validations si vous voulez fusionner avec un spécifique. ça devrait être comme,

 parent |_child pick q6ade6 commit 3 f r8gs4r commit 0 pick vr43de commit 2 pick ac123d commit 1 

après le réarrangement, vous devez remplacer p pick par f (le fixage fusionnera sans le message de validation) ou s (la fusion de squash avec le message de validation peut changer au moment de l’exécution)

puis enregistrez votre arbre.

maintenant fusionner avec commit existant

Remarque: sa méthode n’est pas préférable à moins que vous soyez seul. Si vous avez une grande taille d’équipe, ce n’est pas une méthode acceptable pour réécrire git tree va se retrouver dans des conflits que vous connaissez autrement. si vous voulez vous maintenir propre avec moins de commits vous pouvez essayer ceci et si sa petite équipe sinon c’est pas préférable …..

Basé sur la documentation

Modifier le message des messages de validation plus anciens ou multiples

 git rebase -i HEAD~3 

La liste ci-dessus affiche une liste des 3 derniers commits sur la twig en cours, changez 3 en autre si vous en voulez plus. La liste ressemblera à ce qui suit:

 pick e499d89 Delete CNAME pick 0c39034 Better README pick f7fde4a Change the commit message but push the same commit. 

Remplacez pick par reword avant chaque message de validation que vous souhaitez modifier. Disons que vous modifiez le deuxième commit dans la liste, votre fichier ressemblera à ceci:

 pick e499d89 Delete CNAME reword 0c39034 Better README pick f7fde4a Change the commit message but push the same commit. 

Enregistrez et fermez le fichier de liste de validation, cela affichera un nouvel éditeur pour que vous puissiez modifier votre message de validation, modifier le message de validation et enregistrer.

Pousser enfin les commits modifiés.

 git push --force