J'ai deux branches de travail, maître et forum et je viens de faire quelques modifications dans la branche forum, que j'aimerais bien sélectionner dans maître. Mais malheureusement, le commit que je souhaite sélectionner contient également des modifications que je ne souhaite pas.
La solution consisterait probablement en quelque sorte à supprimer le mauvais commit et à le remplacer par deux validations distinctes, l'une 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
Ma question est donc la suivante: quel est le meilleur moyen de scinder le dernier commit en deux commits distincts?
Vous devriez utiliser l'index. Après avoir effectué une réinitialisation mixte (" git reset HEAD ^"), ajoutez Le premier ensemble de modifications à l’index, puis validez-les. Puis commettez lerest.
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, seules certaines d'entre elles peuvent utiliser "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 qu'il ressemble maintenant à ceci:
1
something
something else
something again
2
Maintenant, je décide que je veux le scinder 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 pour êtredans le deuxième commit.
Je reviens d'abord au parent de HEAD, mais je veux conserver les modifications dans le système de fichiers, J'utilise donc "git reset" sans argument (ce qui fera un soi-disant "mixte" Reset):
$ git reset HEAD^
myfile: locally modified
$ cat myfile
1
something
something else
something again
2
J'utilise maintenant "git add -p" pour ajouter les modifications que je veux valider à l'index (= les mettre en scène). "git add -p" est un outil interactif qui vous demande quelles modifications du fichier devrait être ajouté à 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
Puis 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 tous les autres changements (à savoir le chiffre "2" dans la dernière ligne):
$ git commit -am "Added last line"
[master 5e284e6] Added last line
1 files changed, 1 insertions(+), 0 deletions(-)
Examinons le journal pour voir quels commits 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
splitme
) en deux.splitme
. splitme
. Les étapes de base (1 et 7) peuvent être ignorées si la variable splitme
est 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, je reformerais ensuite -i et changerais l'ordre.
git rebase -i splitme^
# swap order of splitme and 'just some files'
Pour modifier le commit actuel en deux commits, vous pouvez procéder comme suit.
Non plus:
git reset --soft HEAD^
Cela annule le dernier commit mais laisse tout en scène. Vous pouvez ensuite décomposer certains fichiers:
git reset -- file.file
Restaurez éventuellement des parties de ces fichiers:
git add -p file.file
Faites un nouveau premier commit:
git commit
L'étape et commet le reste des modifications dans un deuxième commit:
git commit -a
Ou:
Annule et annule toutes les modifications depuis le dernier commit:
git reset HEAD^
Organisez de manière sélective le premier tour de modifications:
git add -p
Commettre:
git commit
Validez le reste des modifications:
git commit -a
(Dans l'une ou l'autre étape, si vous avez annulé une validation qui ajoute un nouveau fichier et souhaitez l'ajouter à la deuxième validation, vous devrez l'ajouter manuellement en tant que commit -a
ne modifie que les modifications des fichiers déjà suivis.)
Exécutez git gui
, sélectionnez le bouton radio "Modifier la dernière validation", puis annulez (Validation> Annuler la validation depuis ou Ctrl-U) changements que vous ne voulez pas entrer dans le premier commit. Je pense que c'est le moyen le plus facile de s'y prendre.
Une autre chose que vous pouvez faire est de sélectionner le changement sans valider (git cherry-pick -n
), puis manuellement ou avec git gui
, de sélectionner les modifications souhaitées avant de les valider.
git reset HEAD^
la - dure est ce qui tue vos changements.
Je suis surpris que personne n'ait suggéré git cherry-pick -n forum
. Cela mettra en place les modifications depuis le dernier forum
commit mais pas les valider. Vous pouvez alors reset
supprimer les modifications dont vous n'avez pas besoin et commettre ce que vous souhaitez conserver.
git checkout HEAD~1 -- files with unwanted changes
et git commit
. Sinon, les fichiers contenant des modifications mixtes peuvent être partiellement mis en scène par git reset file
et git add -p file
en tant qu'étape intermédiaire.) Appelez ceci le revert .git revert HEAD
- Effectuez un autre commit, qui rajoute les modifications indésirables. C'est le double-revert git rebase -i HEAD~3
). Ce commit est maintenant exempt de modifications indésirables, car celles-ci sont dans le second commit.Puisque vous choisissez les cerises, vous pouvez:
cherry-pick
il avec l'option --no-commit
ajoutée.reset
et utilisez add --patch
, add --edit
ou simplement add
pour organiser ce que vous souhaitez conserver.commit
les changements mis en scène .--reuse-message=<old-commit-ref>
ou --reedit-message=<old-commit-ref>
à la commande commit
.reset --hard
.Une autre façon, en préservant ou en modifiant le message de validation d'origine:
cherry-pick
le commit original comme d'habitude.add
pour organiser l'inversion .commit --amend
pour effectuer l'inversion sur le commit choisi par les cerises .Cela pourrait être une autre solution ciblée dans les cas où le commit est énorme et qu'un petit nombre de fichiers doit être déplacé dans un nouveau commit. Cela fonctionnera si un ensemble de fichiers <path>
doit être extrait du dernier commit à HEAD et tous déplacé vers un nouveau commit. Si plusieurs validations sont nécessaires, les autres solutions peuvent être utilisées.
Commencez par créer des correctifs dans les zones étagées et non étalées contenant les modifications pour rétablir le code avant modification et après modification:
git reset HEAD^ <path>
$ git status
On branch <your-branch>
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: <path>
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: <path>
Pour comprendre ce qui va se passer (la flèche et les commentaires ne font pas partie de la commande):
git diff --cached -> show staged changes to revert <path> to before HEAD
git diff -> show unstaged changes to add current <path> changes
Annule les changements de <path>
dans le dernier commit:
git commit --amend -> reverts changes on HEAD by amending with staged changes
Créez un nouveau commit avec les modifications <path>
:
git commit -a -m "New Commit" -> adds new commit with unstaged changes
Cela a pour effet de créer un nouveau commit contenant les modifications extraites du dernier commit.