Comment diviser le dernier engagement en deux dans Git

J’ai deux twigs de travail, master et forum et je viens de faire quelques modifications dans la twig forum , que je voudrais bien choisir dans master . Mais malheureusement, le commit que je veux choisir comprend aussi des modifications que je ne veux pas.

La solution serait probablement de supprimer d’une manière ou d’une autre le commit erroné et de le remplacer par deux commits distincts, l’un avec les modifications que je veux choisir dans master et les autres qui n’y appartiennent pas.

J’ai essayé de faire

git reset --hard HEAD^ 

qui a supprimé tous les changements, donc je devais revenir avec

 git reset ORIG_HEAD 

Donc, ma question est la suivante: quelle est la meilleure façon de diviser le dernier commit en deux commits distincts?

Vous devez utiliser l’index. Après avoir effectué une réinitialisation mixte (” git reset HEAD ^”), ajoutez le premier ensemble de modifications dans l’index, puis validez-les. Commence alors le rest.

Vous pouvez utiliser ” git add ” pour mettre toutes les modifications apscopes dans un fichier à l’index. Si vous ne voulez pas mettre en scène toutes les modifications apscopes dans un fichier, vous ne pouvez utiliser que “git add -p”.

Voyons un exemple. Supposons que j’ai un fichier appelé myfile, qui contient le texte suivant:

 something something else something again 

Je l’ai modifié dans mon dernier commit pour que maintenant il ressemble à ceci:

 1 something something else something again 2 

Maintenant, je décide que je veux le diviser en deux, et je veux que l’insertion de la première ligne soit dans le premier commit et que l’insertion de la dernière ligne soit dans le second commit.

D’abord, je reviens au parent de HEAD, mais je veux conserver les modifications dans le système de fichiers, donc j’utilise “git reset” sans argument (ce qui fera une réinitialisation dite “mixte”):

 $ git reset HEAD^ myfile: locally modified $ cat myfile 1 something something else something again 2 

Maintenant, j’utilise “git add -p” pour append les modifications que je veux engager dans l’index (= je les met en scène). “git add -p” est un outil interactif qui vous demande quelles modifications il convient d’append à l’index.

 $ git add -p myfile diff --git a/myfile b/myfile index 93db4cb..2f113ce 100644 --- a/myfile +++ b/myfile @@ -1,3 +1,5 @@ +1 something something else something again +2 Stage this hunk [y,n,a,d,/,s,e,?]? s # split this section into two! Split into 2 hunks. @@ -1,3 +1,4 @@ +1 something something else something again Stage this hunk [y,n,a,d,/,j,J,g,e,?]? y # yes, I want to stage this @@ -1,3 +2,4 @@ something something else something again +2 Stage this hunk [y,n,a,d,/,K,g,e,?]? n # no, I don't want to stage this 

Alors je commets ce premier changement:

 $ git commit -m "Added first line" [master cef3d4e] Added first line 1 files changed, 1 insertions(+), 0 deletions(-) 

Maintenant, je peux commettre tous les autres changements (à savoir le chiffre “2” mis dans la dernière ligne):

 $ git commit -am "Added last line" [master 5e284e6] Added last line 1 files changed, 1 insertions(+), 0 deletions(-) 

Vérifions le journal pour voir ce que nous avons:

 $ git log -p -n2 | cat Commit 5e284e652f5e05a47ad8883d9f59ed9817be59d8 Author: ... Date: ... Added last line Diff --git a/myfile b/myfile Index f9e1a67..2f113ce 100644 --- a/myfile +++ b/myfile @@ -2,3 +2,4 @@ something something else something again +2 Commit cef3d4e0298dd5d279a911440bb72d39410e7898 Author: ... Date: ... Added first line Diff --git a/myfile b/myfile Index 93db4cb..f9e1a67 100644 --- a/myfile +++ b/myfile @@ -1,3 +1,4 @@ +1 something something else something again 

Buts:

  • Je veux diviser un engagement passé ( splitme ) en deux.
  • Je veux maintenir le message de validation .

Plan:

  1. rebase interactive à partir d’un avant splitme .
  2. éditer splitme .
  3. Réinitialisez les fichiers à diviser en un deuxième commit.
  4. Modifier l’engagement, maintenir le message, modifier si nécessaire.
  5. Ajoutez les fichiers séparés du premier commit.
  6. S’engager avec un nouveau message.
  7. Continuer rebase.

Les étapes de rebase (1 et 7) peuvent être ignorées si le splitme est la validation la plus récente.

 git rebase -i splitme^ # mark splitme commit with 'e' git reset HEAD^ -- $files git commit --amend git add $files git commit -m "commit with just some files" git rebase --continue 

Si je voulais que les fichiers fractionnés soient validés en premier, alors je me rebase à nouveau -i et change d’ordre

 git rebase -i splitme^ # swap order of splitme and 'just some files' 

Pour changer le commit actuel en deux commits, vous pouvez faire quelque chose comme ceci.

Non plus:

 git reset --soft HEAD^ 

Cela défait le dernier commit mais laisse tout en scène. Vous pouvez ensuite désinstaller certains fichiers:

 git reset -- file.file 

Eventuellement restituer des parties de ces fichiers:

 git add -p file.file 

Faites un nouveau premier commit:

 git commit 

La scène et commettre le rest des modifications dans un deuxième commit:

 git commit -a 

Ou:

Annuler et décompresser toutes les modifications de la dernière validation:

 git reset HEAD^ 

Mettre en place sélectivement la première série de changements:

 git add -p 

Commettre:

 git commit 

Engagez le rest des modifications:

 git commit -a 

(Dans l’une ou l’autre étape, si vous annulez une validation qui a ajouté un nouveau fichier et souhaitez l’append à la seconde validation, vous devrez l’append manuellement en tant que commit -a que les modifications apscopes aux fichiers déjà suivis.)

Lancez git gui , sélectionnez le bouton radio “Modifier le dernier commit” et installez les modifications (Commit> Unstage From Commit ou CtrlU ) que vous ne voulez pas passer en premier commit. Je pense que c’est la façon la plus simple de s’y prendre.

Une autre chose à faire est de choisir le changement sans valider ( git cherry-pick -n ), puis manuellement ou avec git gui sélectionnez les modifications souhaitées avant de valider.

 git reset HEAD^ 

la –hard est ce qui tue vos changements.

Je suis surpris que personne git cherry-pick -n forum suggéré git cherry-pick -n forum . Cela mettra en scène les modifications depuis la dernière validation du forum mais ne les commettra pas – vous pourrez alors reset les modifications inutiles et commettre ce que vous souhaitez conserver.

La méthode du double-revert-squash

  1. Effectuez une autre validation qui supprime les modifications indésirables. (Si c’est par fichier, c’est très simple: git checkout HEAD~1 -- files with unwanted changes et git commit . Sinon, les fichiers avec des modifications mixtes peuvent être partiellement mis en place git reset file et git add -p file comme étape intermédiaire .) Appelez cela le retour .
  2. git revert HEAD – Crée un autre commit, qui ajoute les modifications indésirables. C’est le double-retour
  3. Sur les 2 commits que vous avez faits, écrasez le premier sur le commit à scinder ( git rebase -i HEAD~3 ). Cette validation est maintenant libérée des modifications indésirables, car celles-ci sont dans le deuxième commit.

Avantages

  • Préserve le message de validation
  • Fonctionne même si l’engagement à diviser n’est pas le dernier. Il suffit que les modifications indésirables ne soient pas en conflit avec des validations ultérieures

Puisque vous faites votre choix, vous pouvez:

  1. cherry-pick le avec l’option --no-commit ajoutée.
  2. reset et utiliser add --patch , add --edit ou simplement add à l’étape ce que vous voulez conserver.
  3. commit les changements par étapes.
    • Pour réutiliser le message de validation original, vous pouvez append les --reuse-message= ou --reedit-message= à la commande commit .
  4. Soufflez les modifications non mises en scène avec reset --hard .

Une autre manière de conserver ou de modifier le message de validation original:

  1. cherry-pick le commit d’origine comme il se doit.
  2. Inversez les modifications que vous ne voulez pas et utilisez add pour mettre en scène l’inversion.
    • Cette étape serait facile si vous supprimez ce que vous avez ajouté, mais un peu difficile si vous ajoutez ce que vous avez supprimé ou annulez une modification.
  3. commit --amend pour effectuer l’inversion sur le commit sélectionné.
    • Vous recevrez à nouveau le même message de validation que vous pourrez conserver ou modifier si nécessaire.