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. Engagez ensuite le reste.
Vous pouvez utiliser " git add " pour mettre toutes les modifications apportées dans un fichier à l'index. Si vous ne voulez pas mettre en scène toutes les modifications apportées dans un fichier, seulement certaines d'entre elles, vous pouvez utiliser "git add -p".
Voyons un exemple. Supposons que j'avais un fichier appelé monfichier, qui contient le texte suivant:
something
something else
something again
Je l'ai modifié dans mon dernier commit pour que maintenant ça 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 l'insertion de la dernière ligne dans le deuxième commit.
Je reviens d'abord 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 ajouter les changements que je veux valider à l'index (= je les mets en scène). "git add -p" est un outil interactif qui vous demande quelles modifications du fichier doit-il ajouter à 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
Ensuite, 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 valider toutes les autres modifications (à savoir le chiffre "2" mis à 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 quels engagements 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
git reset [--patch|-p] <commit>
que vous pouvez utiliser pour vous éviter d'avoir à le fairegit add -p
après la réinitialisation. Ai-je raison? Utiliser git 1.7.9.5.Buts:
splitme
) passé en deux.Plan:
splitme
.splitme
.Les étapes de rebase (1 et 7) peuvent être ignorées s'il
splitme
s'agit du commit le plus récent.Si je voulais que les fichiers fractionnés soient validés en premier, je rebase ensuite -i à nouveau et je change l'ordre
la source
git reset HEAD^
était la pièce manquante du puzzle. Fonctionne bien avec-p
aussi. Merci!-- $files
argumentgit reset
. Avec les chemins passés,git reset
restaure ces fichiers à l'état de la validation référencée mais ne modifie aucune validation. Si vous quittez les chemins, vous "perdez" le commit que vous souhaitez modifier à l'étape suivante.git reset HEAD^ -- .
. Il est extrêmement surprenant que ce ne soit pas exactement le comportement degit reset HEAD^
.Pour changer le commit actuel en deux commits, vous pouvez faire quelque chose comme ceci.
Soit:
Cela annule le dernier commit mais laisse tout en scène. Vous pouvez ensuite décompresser certains fichiers:
Restaurez éventuellement des parties de ces fichiers:
Faites un nouveau premier commit:
Étape et validez le reste des modifications dans un deuxième commit:
Ou:
Annulez et annulez toutes les modifications du dernier commit:
Organisez de manière sélective le premier cycle de modifications:
Commettre:
Validez le reste des modifications:
(Dans l'une ou l'autre étape, si vous annulez une validation qui a ajouté un nouveau fichier et que vous souhaitez l'ajouter à la deuxième validation, vous devrez l'ajouter manuellement, car
commit -a
seules les modifications des étapes dans les fichiers déjà suivis seront effectuées .)la source
Exécutez
git gui
, sélectionnez le bouton radio "Modifier le dernier commit" et annulez (Commit> Unstage From Commit ou Ctrl- U) les modifications que vous ne souhaitez pas entrer dans le premier commit. Je pense que c'est la façon la plus simple de procéder.Une autre chose que vous pouvez faire est de sélectionner la modification sans commettre (
git cherry-pick -n
), puis manuellement ou avecgit gui
les modifications souhaitées avant de valider.la source
le --hard est ce qui tue vos changements.
la source
Je suis surpris que personne ne l'ait suggéré
git cherry-pick -n forum
. Cela mettra en scène les modifications de la dernièreforum
validation, mais pas les valider - vous pouvez ensuitereset
supprimer les modifications dont vous n'avez pas besoin et valider ce que vous souhaitez conserver.la source
La méthode du double-retour-squash
git checkout HEAD~1 -- files with unwanted changes
etgit commit
. Sinon, les fichiers avec des changements mixtes peuvent être partiellement organisésgit reset file
etgit add -p file
comme étape intermédiaire.) Appelez cela le retour .git revert HEAD
- Faites encore un autre commit, qui ajoute les changements indésirables. Ceci est le double retourgit rebase -i HEAD~3
). Ce commit devient maintenant libre des changements indésirables, car ceux-ci sont dans le deuxième commit.Avantages
la source
Puisque vous choisissez des cerises, vous pouvez:
cherry-pick
avec--no-commit
option ajoutée.reset
et utiliseradd --patch
,add --edit
ou tout simplementadd
pour mettre en scène ce que vous souhaitez conserver.commit
les changements par étapes.--reuse-message=<old-commit-ref>
ou--reedit-message=<old-commit-ref>
à lacommit
commande.reset --hard
.Une autre façon, en conservant ou en modifiant le message de validation d'origine:
cherry-pick
le commit d'origine comme d'habitude.add
pour mettre en scène l'inversion.commit --amend
pour effectuer l'inversion sur le commit choisi par les cerises.la source
Cela pourrait être une autre solution ciblée pour les cas où il y a une énorme validation et une petite quantité de fichiers doit être déplacée dans une nouvelle validation. Cela fonctionnera si un ensemble de
<path>
fichiers doit être extrait du dernier commit sur HEAD et tous déplacés vers un nouveau commit. Si plusieurs validations sont nécessaires, les autres solutions peuvent être utilisées.Effectuez d'abord des correctifs dans les zones par étapes et non par étapes qui contiendraient les modifications pour rétablir le code respectivement avant et après modification:
Pour comprendre ce qui va se passer (la flèche et les commentaires ne font pas partie de la commande):
Annuler les
<path>
modifications du dernier commit:Créez un nouveau commit avec des
<path>
modifications:Cela a pour effet de créer un nouveau commit contenant les modifications extraites du dernier commit.
la source