web-dev-qa-db-fra.com

Comment modifier les anciens Git commit?

J'ai fait 3 commits git, mais je n'ai pas été poussé. Comment puis-je modifier l'ancien (ddc6859af44) et (47175e84c), qui n'est pas le plus récent?

$git log
commit f4074f289b8a49250b15a4f25ca4b46017454781
Date:   Tue Jan 10 10:57:27 2012 -0800

commit ddc6859af448b8fd2e86dd0437c47b6014380a7f
Date:   Mon Jan 9 16:29:30 2012 -0800

commit 47175e84c2cb7e47520f7dde824718eae3624550
Date:   Mon Jan 9 13:13:22 2012 -0800
141
michael
git rebase -i HEAD^^^

Marquez maintenant ceux que vous souhaitez modifier avec edit ou e (remplacez pick). Maintenant, enregistrez et quittez.

Maintenant, faites vos modifications, puis

git add -A
git commit --amend --no-edit
git rebase --continue

Si vous souhaitez ajouter une suppression supplémentaire, supprimez les options de la commande commit. Si vous souhaitez ajuster le message, omettez simplement le --no-edit option.

178
Adam Dymitruk

J'ai préparé mon engagement que je voulais modifier avec un ancien et j'ai été surpris de voir que Rebase -i se plaignait de modifications non engagées. Mais je ne voulais plus effectuer mes modifications en spécifiant l’option d’édition du commit précédent. La solution était donc simple et facile:

  1. préparez votre mise à jour vers une ancienne version, ajoutez-la et validez
  2. git rebase -i <commit you want to amend>^ - remarquez le ^ donc vous voyez le dit commit dans l'éditeur de texte
  3. vous obtiendrez quelque chose comme ceci:

    pick 8c83e24 use substitution instead of separate subsystems file to avoid jgroups.xml and jgroups-e2.xml going out of sync
    pick 799ce28 generate ec2 configuration out of subsystems-ha.xml and subsystems-full-ha.xml to avoid discrepancies
    pick e23d23a fix indentation of jgroups.xml
    
  4. maintenant, pour combiner e23d23a avec 8c83e24, vous pouvez modifier l’ordre des lignes et utiliser squash comme ceci:

    pick 8c83e24 use substitution instead of separate subsystems file to avoid jgroups.xml and jgroups-e2.xml going out of sync    
    squash e23d23a fix indentation of jgroups.xml
    pick 799ce28 generate ec2 configuration out of subsystems-ha.xml and subsystems-full-ha.xml to avoid discrepancies
    
  5. écrivez et quittez le fichier, vous serez présent avec un éditeur pour fusionner les messages de commit. Faites-le et enregistrez/quittez le document texte

  6. Vous avez terminé, vos commits sont modifiés

le crédit va à: http://git-scm.com/book/en/Git-Tools-Rewriting-History Il y a aussi une autre magie démontrée utile.

99
akostadinov

Vous pouvez utiliser git rebase pour réécrire l'historique de commit. Cela peut être potentiellement destructeur pour vos modifications, utilisez-le avec précaution.

Commencez par valider votre modification "amendée" comme une validation normale. Faites ensuite une rebase interactive à partir du parent de votre plus ancien commit.

git rebase -i 47175e84c2cb7e47520f7dde824718eae3624550^

Cela lancera votre éditeur avec tous les commits. Réorganisez-les pour que votre engagement de modification vienne en dessous de celui que vous souhaitez modifier. Remplacez ensuite le premier mot sur la ligne par le mot-clé "modifier" avec s qui le combinera (s quash) avec le commit avant. Enregistrez et quittez votre éditeur et suivez les instructions.

13
Benjamin Bannier

J'ai utilisé un autre moyen plusieurs fois. En fait, c’est un manuel git rebase -i et il est utile lorsque vous souhaitez réorganiser plusieurs commits, notamment en écrasant ou en divisant certains d'entre eux. Le principal avantage est que vous n'avez pas à décider du destin de chaque engagement à un moment donné. Toutes les fonctionnalités de Git seront également disponibles au cours du processus, contrairement à ce qui se passe au cours d’une base Par exemple, vous pouvez afficher le journal de l'historique original et de l'historique réécrit à tout moment, ou même effectuer une autre base!

Je vais faire référence aux commits de la manière suivante, pour que ce soit facilement lisible:

C # good commit after a bad one
B # bad commit
A # good commit before a bad one

Votre histoire au début ressemble à ceci:

x - A - B - C
|           |
|           master
|
Origin/master

Nous allons le recréer de cette façon:

x - A - B*- C'
|           |
|           master
|
Origin/master

Procédure

git checkout B       # get working-tree to the state of commit B
git reset --soft A   # tell Git that we are working before commit B
git checkout -b rewrite-history   # switch to a new branch for alternative history

Améliorez votre ancien commit en utilisant git add (git add -i, git stash etc.) maintenant. Vous pouvez même diviser votre ancien commit en deux ou plus.

git commit           # recreate commit B (result = B*)
git cherry-pick C    # copy C to our new branch (result = C')

Résultat intermédiaire:

x - A - B - C 
|    \      |
|     \     master
|      \
|       B*- C'
|           |
|           rewrite-history
|
Origin/master

Finissons:

git checkout master
git reset --hard rewrite-history  # make this branch master

Ça y est, vous pouvez Push votre progression maintenant.

11
Melebius

Vous pouvez utiliser git rebase --interactive , en utilisant la commande edit sur le commit que vous souhaitez modifier.

10
Avi

Dans le cas où l'OP voudrait écraser les 2 commits spécifiés en 1, voici une autre façon de le faire sans changer de base.

git checkout HEAD^               # go to the first commit you want squashed
git reset --soft HEAD^           # go to the second one but keep the tree and index the same
git commit --amend -C HEAD@{1}   # use the message from first commit (omit this to change)
git checkout HEAD@{3} -- .       # get the tree from the commit you did not want to touch
git add -A                       # add everything
git commit -C HEAD@{3}           # commit again using the message from that commit

Le @{N) _ La syntaxe est pratique à connaître car elle vous permettra de référencer l’historique de vos références. Dans ce cas, c’est HEAD qui représente votre commit actuel.

2
Adam Dymitruk