Question Comment modifier un commit spécifié dans git?


Je soumets habituellement 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 HEAD commettre?


1700
2017-07-27 05:19


origine


Réponses:


Vous pouvez utiliser git rebase, par exemple, si vous voulez revenir à commit bbc643cd, courir

$ git rebase --interactive 'bbc643cd^'

Dans l'éditeur par défaut, modifiez pick à edit dans la ligne dont vous voulez modifier le commit. Apportez vos modifications, puis engagez-les avec le même message que précédemment:

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

pour modifier le commit, et après

$ git rebase --continue

pour revenir à la tête précédente commit.

ATTENTION: Notez que cela va changer le SHA-1 de ce commit ainsi que tous les enfants - en d'autres termes, cela réécrit l'histoire à partir de ce moment. Vous pouvez casser repos en faisant cela si vous poussez en utilisant la commande git push --force


2232
2017-07-27 05:28



Utilisez le rebase interactif génial:

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

Trouvez le commit que vous voulez, changez pick à e (edit), et enregistrez et fermez le fichier. Git va revenir à ce commit, vous permettant de:

  • utilisation git commit --amend faire des changements, ou
  • utilisation git reset @~ pour annuler la dernière validation, mais pas les modifications apportées aux fichiers (c'est-à-dire vous amener au point où vous étiez lorsque vous avez modifié les fichiers, mais que vous n'aviez pas encore validés).

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

Ensuite, cours git rebase --continue, et Git rejouera 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 histoire de réécriture dans les docs Git.


N'ayez pas peur de rebaser

ProTip: N'ayez pas peur d'expérimenter avec des commandes "dangereuses" qui réécrivent l'histoire * - Git ne supprime pas vos validations 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

* Attention aux options comme --hard et --force Cependant, ils peuvent rejeter des données.
* De même, ne réécrivez pas l'historique sur les branches sur lesquelles vous collaborez.



Sur de nombreux systèmes, git rebase -i va ouvrir Vim par défaut. Vim ne fonctionne pas comme la plupart des éditeurs de texte modernes, alors jetez un oeil à comment rebaser en utilisant Vim. Si vous préférez utiliser un éditeur différent, modifiez-le git config --global core.editor your-favorite-text-editor.


304
2018-04-29 17:50



Interactif rebaser avec --autosquash est quelque chose que j'utilise fréquemment quand j'ai besoin de réparer des commits précédents plus profonds dans l'histoire. Il accélère essentiellement le processus que la réponse de ZelluX illustre, et est particulièrement pratique lorsque vous avez plus d'un commit à éditer.

De la documentation:

--autosquash

Lorsque le message du commit commence par "squash! ..." (ou "fixup! ..."), et qu'il y a un commit dont le titre commence par le même ..., modifier automatiquement la liste todo de rebase -i pour que le commit marqué pour l'écrasement vient juste après l'engagement à être modifié

Supposons que vous avez un historique qui ressemble à ceci:

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

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

$ git commit -m "fixup! Commit2"

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

Ensuite, initiez un rebasage 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 devez faire est de sauvegarder et de quitter


57
2017-09-29 17:59



Courir:

$ git rebase --interactive commit_hash^

chaque ^ indique le nombre de retours que vous souhaitez modifier, s'il s'agit d'un seul (le hash de commit que vous avez spécifié), alors vous en ajoutez un ^.

En utilisant Vim vous changez les mots pick à reword pour les commits que vous voulez changer, sauvegarder et quitter (:wq). Alors git vous demandera avec chaque commit que vous avez marqué comme reword afin que vous puissiez changer le message de commit.

Chaque message de commit que vous devez sauvegarder et quitter (:wq) pour aller au prochain message de validation

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

MODIFIER: naviguer dans vim tu utilises j à monter, k descendre, h aller à gauche, et l aller à droite (tout cela dans NORMAL mode, appuyez sur ESC aller à NORMAL mode). Pour modifier un texte, appuyez sur i de sorte que vous entrez dans le INSERT mode, où vous insérez du texte. presse ESC revenir à NORMAL mode :)

METTRE À JOUR: Voici un excellent lien de la liste de github Comment annuler (presque) n'importe quoi avec git 


30
2017-07-02 19:11



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

Dites que vous voulez modifier Commit1. Premièrement, branche de avant  Commit1:

git checkout -b amending [commit before Commit1]

Deuxièmement, saisir Commit1 avec cherry-pick:

git cherry-pick Commit1

Maintenant, modifiez vos modifications, en créant Commit1':

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

Et enfin, après avoir caché d'autres changements, transplantez le reste de vos commits jusqu'à master au-dessus de votre nouveau commit:

git rebase --onto amending Commit1 master

Lire: "rebase, sur la branche amending, tout commet entre Commit1 (non inclusif) et master (inclusivement) "C'est-à-dire, Commit2 et Commit3, en supprimant complètement l'ancien Commit1, vous pouvez simplement les sélectionner, mais c'est plus facile.

N'oubliez pas de nettoyer vos branches!

git branch -d amending

12
2017-10-22 12:19



Entré dans cette approche (et c'est probablement exactement la même chose que l'utilisation de rebase interactive) mais pour moi, c'est plutôt simple.

Note: Je présente cette approche dans le but d'illustrer ce que vous pouvez faire plutôt qu'une alternative quotidienne. Comme il y a beaucoup d'étapes (et peut-être quelques mises en garde.)

Dites que vous voulez changer de commit 0 et vous êtes actuellement sur feature-branch

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

Passer à cette validation et créer un quick-branch. Vous pouvez également cloner votre branche de fonctionnalité en tant que point de 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)

Les changements d'étape, stash tout le reste.

git add ./example.txt
git stash

Commettre les modifications et valider la commande 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 feature-branch sur quick-branch (résoudre les conflits en cours de route). Appliquer le cachet et enlever 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 dupliquera pas (bien que je ne puisse pas vraiment dire dans quelle mesure) le commit 0 lors du rebasage.

Note: tous les hash de commit sont modifiés à partir du commit que nous avions l'intention de changer.


6
2018-06-01 11:57



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 mettant en scène vos changements (avec git add) et ensuite courir git fixup <commit-to-modify>. Bien sûr, il sera toujours interactif si vous avez des conflits.


4
2018-01-16 15:27



Commande complètement non interactive(1)

Je pensais juste partager un alias que j'utilise pour ça. C'est basé sur non interactif rebasage interactif. Pour l'ajouter à votre git, exécutez 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 c'est no-vim.


(1)étant donné qu'il n'y a pas de conflits lors du rebasage, bien sûr

Usage

git amend-to <REV> # e.g.
git amend-to HEAD~1
git amend-to aaaa1111

Le nom amend-to semble approprié à mon humble avis. Comparez le flux avec --amend:

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

Explication

  • git config --global alias.<NAME> '!<COMMAND>' - crée un alias global git nommé <NAME> qui va exécuter la commande non-git <COMMAND>
  • f() { <BODY> }; f - une fonction bash "anonyme".
  • SHA=`git rev-parse "$1"`; - convertit l'argument en révision git et affecte le résultat à la variable SHA
  • git commit --fixup "$SHA" - fixup-commit pour SHA. Voir git-commit docs
  • GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"
    • git rebase --interactive "$SHA^" la partie a été couverte par d'autres réponses.
    • --autosquash est ce qui est utilisé en conjonction avec git commit --fixupvoir git-rebase docs pour plus d'informations
    • GIT_SEQUENCE_EDITOR=true est ce qui rend l'ensemble non interactif. Ce hack j'ai appris à partir de ce blog.

4
2018-02-27 01:47