Comment diviser le dernier commit en deux dans Git

J'ai deux branches, maître - et forum et j'ai juste fait quelques modifications dans forum branche, que je tiens à piocher dans maître - . Mais malheureusement, le commit que je veux cherry-pick contient également des modifications que je ne veux pas.

La solution serait probablement de supprimer le mauvais commit et de le remplacer par deux commits distincts, l'un avec des modifications que je veux choisir en maître, et d'autres qui n'appartiennent pas y.

J'ai essayé de faire

git reset --hard HEAD^

Qui a supprimé toutes les modifications, donc j'ai dû revenir avec

git reset ORIG_HEAD

Donc ma question est, quelle est la meilleure façon de split dernier commit en deux s'engage?

270
demandé sur Jakub Arnold 2009-09-17 20:53:15

8 réponses

Vous devriez utiliser l'index. Après avoir effectué une réinitialisation mixte (" git reset HEAD^"), Ajoutez la première série de changements dans l'index, puis les valider. Puis engagez-le reste.

Vous pouvez utiliser le bouton "git add" pour mettre toutes les modifications apportées à un fichier à l'index. Si vous vous ne voulez pas mettre en scène toutes les modifications apportées dans un fichier, seulement certaines d'entre elles, vous peut utiliser "git add-p".

Voyons un exemple. Supposons que j'avais un fichier appelé myfile, qui contient la suite texte:

something
something else
something again

Je l'ai modifié dans mon dernier commit de sorte que maintenant il ressemble à ceci:

1
something
something else
something again
2

Maintenant, je décide que je veux la couper en deux, et je veux l'insertion de la première ligne à être dans le premier commit, et l'insertion de la dernière ligne à dans la deuxième commettre.

D'abord, je retourne au parent de HEAD, mais je veux garder les modifications dans le système de fichiers, j'utilise donc "git reset" sans argument (ce qui fera un soi-disant "mixte" réinitialiser):

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

Maintenant j'utilise "git add -p" pour ajouter les modifications que je veux commettre à l'index (=je stade de mer). "git add-p" est un outil interactif qui vous demande de quoi modifications apportées au fichier devrait-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

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" mettre 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 commits:

$ 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
323
répondu hcs42 2012-10-25 12:44:08

Objectifs:

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

Plan:

  1. rebase interactif à partir d'un avant splitme.
  2. modifier splitme.
  3. réinitialise les fichiers pour les diviser en une seconde validation.
  4. modifier commit, maintenir le message, modifier si nécessaire.
  5. ajoutez les fichiers séparés de la première validation.
  6. Commit avec un nouveau message.
  7. continuer à rebaser.

Les étapes de rebase (1 & 7) peuvent être ignorées si le splitme est le commit le plus récent.

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 divisés soient validés en premier, je rebaserais-je à nouveau et changerais l'ordre

git rebase -i splitme^
# swap order of splitme and 'just some files'
81
répondu spazm 2014-09-27 20:55:15

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

Soit:

git reset --soft HEAD^

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

git reset -- file.file

Éventuellement restage des parties de ces fichiers:

git add -p file.file

Faire un nouveau premier commit:

git commit

L'étape et commit le reste des modifications dans un second commit:

git commit -a

Ou:

Annuler et annuler toutes les modifications du dernier commit:

git reset HEAD^

Etape sélectivement le premier tour de changements:

git add -p

Commettre:

git commit

Commit le reste des modifications:

git commit -a

(dans les deux étapes, si vous avez défait un commit qui a ajouté un tout nouveau fichier et que vous voulez l'ajouter à la deuxième validation, vous devrez l'ajouter manuellement car commit -a ne modifie que les fichiers déjà suivis.)

52
répondu CB Bailey 2009-09-17 21:13:25

Exécutez git gui, sélectionnez le bouton radio "modifier le dernier commit", et unstage (Commit > Unstage de Commit, ou Ctrl-U) changements que vous ne voulez pas entrer dans le premier commit. Je pense que c'est la façon la plus simple de s'y prendre.

Une autre chose que vous pouvez faire est de choisir la modification sans valider (git cherry-pick -n), puis manuellement ou avec git gui sélectionnez les modifications souhaitées avant de valider.

22
répondu Michael Krelin - hacker 2014-02-04 03:37:19
git reset HEAD^

Le -- dur est ce qui tue vos changements.

15
répondu semanticart 2009-09-17 16:58:42

Je suis surpris que personne n'ait suggéré git cherry-pick -n forum. Cela mettra en scène les modifications de la dernière validation forum mais ne les validera pas - vous pouvez ensuite reset supprimer les modifications dont vous n'avez pas besoin et valider ce que vous voulez conserver.

13
répondu dahlbyk 2011-12-12 22:12:41

La méthode double-revert-squash

  1. effectuez une autre validation qui supprime les modifications indésirables. (Si c'est par fichier, c'est vraiment facile: git checkout HEAD~1 -- files with unwanted changes et git commit. Sinon, les fichiers avec des modifications mixtes peuvent être partiellement mis en scène git reset file et git add -p file comme une étape intermédiaire.) Appellent cela le revenir.
  2. git revert HEAD - Faites encore un autre commit, qui ajoute les modifications indésirables. C'est le double-revenir
  3. sur les 2 commits que vous avez maintenant effectués, squash le premier sur le commit à diviser (git rebase -i HEAD~3). Ce commit devient maintenant libre des changements indésirables, car ceux-ci sont dans le deuxième commit.

Avantages

  • conserve le message de validation
  • fonctionne même si le commit à split n'est pas le dernier. Cela exige seulement que les modifications indésirables ne soient pas en conflit avec les commits ultérieurs
2
répondu user2394284 2017-07-06 15:33:57

Puisque vous êtes en train de cueillir des cerises, vous pouvez:

  1. cherry-pick avec l'option --no-commit ajoutée.
  2. reset et utiliser add --patch, add --edit ou juste {[5] } pour mettre en scène ce que vous voulez garder.
  3. commit les changements par étapes.
    • pour réutiliser le message de validation d'origine, vous pouvez ajouter des options --reuse-message=<old-commit-ref> ou --reedit-message=<old-commit-ref> à la commande commit.
  4. éliminez les changements non marqués avec reset --hard.

Une autre façon, en préservant ou en éditant le commit d'origine message:

  1. cherry-pick le commit d'origine comme d'habitude.
  2. inverser les modifications que vous ne voulez pas et utiliser add pour mettre en scène l'inversion.
    • Cette étape serait facile si vous supprimez ce que vous avez ajouté, mais un peu délicate si vous ajoutez ce que vous avez supprimé ou si vous annulez une modification.
  3. {[13] } pour effectuer l'inversion sur le commit choisi.
    • vous obtiendrez à nouveau le même message de validation, que vous pouvez conserver ou réviser en tant que nécessaire.
0
répondu ADTC 2018-04-08 04:22:23