Question Rompre un commit précédent en plusieurs validations


Sans créer une branche et faire un tas de travail funky sur une nouvelle branche, est-il possible de décomposer un commit unique en quelques commits différents après qu'il a été validé dans le dépôt local?


831
2018-06-02 16:11


origine


Réponses:


git rebase -i le fera.

Commencez par commencer par un répertoire de travail propre: git status ne doit pas afficher de modifications, de suppressions ou d'ajouts en attente.

Pour diviser votre commit le plus récent, commencez par:

$ git reset HEAD~

Maintenant commettez les morceaux individuellement de la manière habituelle, en produisant autant de commits que vous avez besoin.

Si c'était plus loin dans l'arbre, alors

$ git rebase -i HEAD~3

3 est combien de retours en arrière c'est.

Si c'était plus loin dans l'arbre que vous voulez compter, alors

$ git rebase -i 123abcd~

123abcd est le SHA1 du commit que vous voulez diviser.

Lorsque vous obtenez l'écran de modification de la reprise, recherchez le commit que vous voulez séparer. Au début de cette ligne, remplacez pick avec edit (e pour faire court). Enregistrez le tampon et quittez. Rebase va maintenant s'arrêter juste après le commit que vous voulez éditer. Alors:

$ git reset HEAD~

Engagez les pièces individuellement de la manière habituelle, en produisant autant de commissions que nécessaire, puis

$ git rebase --continue

1279
2018-06-02 16:26



De git-rebase manuel (section SPLITTING COMMITS)

En mode interactif, vous pouvez marquer des commits avec l'action "edit". Cependant, cela ne signifie pas nécessairement que git rebase s'attend à ce que le résultat de cette édition soit exactement un commit. En effet, vous pouvez annuler la validation, ou vous pouvez ajouter d'autres validations. Cela peut être utilisé pour diviser un commit en deux:

  • Démarrer un rebasage interactif avec git rebase -i <commit>^, où <commit> est l'engagement que vous voulez diviser. En fait, toute plage de validation fera l'affaire, tant qu'elle contient ce commit.

  • Marquez le commit que vous voulez scinder avec l'action "edit".

  • Quand il s'agit d'éditer ce commit, exécutez git reset HEAD^. L'effet est que le HEAD est rembobiné par un, et l'index suit. Cependant, l'arbre de travail reste le même.

  • Maintenant, ajoutez les changements à l'index que vous voulez avoir dans le premier commit. Vous pouvez utiliser git add (peut-être interactif) ou git gui (ou les deux) pour le faire.

  • Validez l'index actuel avec le message de validation approprié.

  • Répétez les deux dernières étapes jusqu'à ce que votre arbre de travail soit propre.

  • Continuez le rebase avec git rebase --continue.


244
2018-01-22 15:05



Utilisation git rebase --interactive pour modifier cette validation antérieure, exécutez git reset HEAD~, et alors git add -p pour en ajouter, puis faire un commit, puis en ajouter d'autres et en faire un autre, autant de fois que vous le souhaitez. Quand vous avez terminé, courez git rebase --continue, et vous aurez tous les commits de split plus tôt dans votre pile.

Important: Notez que vous pouvez jouer et faire tous les changements que vous voulez, et ne pas avoir à vous soucier de perdre les anciens changements, car vous pouvez toujours courir git reflog pour trouver le point dans votre projet qui contient les changements que vous voulez, (appelons-le a8c4ab), et alors git reset a8c4ab.

Voici une série de commandes pour montrer comment cela fonctionne:

mkdir git-test; cd git-test; git init

Ajoutez maintenant un fichier A

vi A

ajoutez cette ligne:

one

git commit -am one

puis ajoutez cette ligne à A:

two

git commit -am two

puis ajoutez cette ligne à A:

three

git commit -am three

maintenant le fichier A ressemble à ceci:

one
two
three

et notre git log ressemble à ce qui suit (bien, j'utilise git log --pretty=oneline --pretty="%h %cn %cr ---- %s"

bfb8e46 Rose Perrone 4 seconds ago ---- three
2b613bc Rose Perrone 14 seconds ago ---- two
9aac58f Rose Perrone 24 seconds ago ---- one

Disons que nous voulons diviser le second commit, two.

git rebase --interactive HEAD~2

Cela amène un message qui ressemble à ceci:

pick 2b613bc two
pick bfb8e46 three

Changer le premier pick à un e pour éditer ce commit.

git reset HEAD~

git diff nous montre que nous venons d'annuler le commit que nous avons pris pour le second commit:

diff --git a/A b/A
index 5626abf..814f4a4 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
 one
+two

Appliquons ce changement, et ajoutons "et un tiers" à cette ligne dans le fichier A.

git add .

Ceci est généralement le point lors d'un rebasage interactif où nous courrions git rebase --continue, parce que nous voulons simplement retourner dans notre pile de validations pour éditer un commit précédent. Mais cette fois, nous voulons créer un nouveau commit. Nous allons donc courir git commit -am 'two and a third'. Maintenant, nous modifions le fichier A et ajoutez la ligne two and two thirds.

git add . git commit -am 'two and two thirds' git rebase --continue

Nous avons un conflit avec notre engagement, three, alors résolvons-le:

Nous allons changer

one
<<<<<<< HEAD
two and a third
two and two thirds
=======
two
three
>>>>>>> bfb8e46... three

à

one
two and a third
two and two thirds
three

git add .; git rebase --continue

Maintenant, notre git log -p ressemble à ça:

commit e59ca35bae8360439823d66d459238779e5b4892
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 13:57:00 2013 -0700

    three

diff --git a/A b/A
index 5aef867..dd8fb63 100644
--- a/A
+++ b/A
@@ -1,3 +1,4 @@
 one
 two and a third
 two and two thirds
+three

commit 4a283ba9bf83ef664541b467acdd0bb4d770ab8e
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 14:07:07 2013 -0700

    two and two thirds

diff --git a/A b/A
index 575010a..5aef867 100644
--- a/A
+++ b/A
@@ -1,2 +1,3 @@
 one
 two and a third
+two and two thirds

commit 704d323ca1bc7c45ed8b1714d924adcdc83dfa44
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 14:06:40 2013 -0700

    two and a third

diff --git a/A b/A
index 5626abf..575010a 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
 one
+two and a third

commit 9aac58f3893488ec643fecab3c85f5a2f481586f
Author: Rose Perrone <roseperrone@fake.com>
Date:   Sun Jul 7 13:56:40 2013 -0700

    one

diff --git a/A b/A
new file mode 100644
index 0000000..5626abf
--- /dev/null
+++ b/A
@@ -0,0 +1 @@
+one

34
2017-07-07 21:10



Les réponses précédentes ont couvert l'utilisation de git rebase -i pour éditer le commit que vous voulez diviser, et le valider en parties.

Cela fonctionne bien lorsque vous divisez les fichiers en différents commits, mais si vous voulez séparer les modifications des fichiers individuels, vous devez en savoir plus.

Après avoir obtenu le commit que vous voulez diviser, en utilisant rebase -i et le marquer pour edit, vous avez deux options.

  1. Après avoir utilisé git reset HEAD~, passez en revue les correctifs individuellement en utilisant git add -p pour sélectionner ceux que vous voulez dans chaque commit

  2. Editez la copie de travail pour supprimer les modifications que vous ne voulez pas; commettre cet état provisoire; puis retirez le commit complet pour le tour suivant.

L'option 2 est utile si vous fractionnez un commit important, car elle vous permet de vérifier que les versions intermédiaires sont bien construites et exécutées correctement dans le cadre de la fusion. Cela se passe comme suit.

Après avoir utilisé rebase -i et editEn utilisant le commit, utilisez

git reset --soft HEAD~

pour annuler la validation, mais laissez les fichiers validés dans l'index. Vous pouvez également effectuer une réinitialisation mixte en omettant --soft, en fonction de la proximité du résultat final. La seule différence est de savoir si vous commencez avec tous les changements mis en scène ou avec eux tous sans mise en scène.

Maintenant, entrez et éditez le code. Vous pouvez supprimer les modifications, supprimer les fichiers ajoutés et faire ce que vous voulez pour construire la première validation de la série que vous recherchez. Vous pouvez également le créer, l'exécuter et confirmer que vous disposez d'un ensemble cohérent de sources.

Une fois que vous êtes satisfait, mettez en scène / désinstallez les fichiers au besoin (j'aime utiliser git gui pour cela), et validez les modifications via l'interface utilisateur ou la ligne de commande

git commit

C'est le premier commit fait. Vous voulez maintenant restaurer votre copie de travail dans l'état où elle se trouvait après le commit que vous partagez, de sorte que vous puissiez prendre plus de modifications pour votre prochaine validation. Pour trouver le sha1 du commit que vous éditez, utilisez git status. Dans les premières lignes de l'état, vous verrez la commande rebase en cours d'exécution, dans laquelle vous pouvez trouver le sha1 de votre commit d'origine:

$ git status
interactive rebase in progress; onto be83b41
Last commands done (3 commands done):
   pick 4847406 US135756: add debugging to the file download code
   e 65dfb6a US135756: write data and download from remote
  (see more in file .git/rebase-merge/done)
...

Dans ce cas, le commit que je suis en train d'éditer a sha1 65dfb6a. Sachant cela, je peux vérifier le contenu de ce commit sur mon répertoire de travail en utilisant le formulaire de git checkout qui prend à la fois un commit et un emplacement de fichier. Ici j'utilise . comme l'emplacement du fichier pour remplacer l'ensemble de la copie de travail:

git checkout 65dfb6a .

Ne manquez pas le point à la fin!

Cela vérifiera et mettra en scène les fichiers tels qu'ils étaient après la validation que vous êtes en train de modifier, mais par rapport à la validation précédente que vous avez effectuée, de sorte que les modifications que vous avez déjà effectuées ne feront pas partie du commit.

Vous pouvez soit aller de l'avant maintenant et le commettre tel quel pour terminer la scission, soit recommencer, en supprimant certaines parties de la validation avant de faire une autre validation intermédiaire.

Si vous souhaitez réutiliser le message de validation d'origine pour un ou plusieurs validations, vous pouvez l'utiliser directement depuis les fichiers de travail de la reprise:

git commit --file .git/rebase-merge/message

Enfin, une fois que vous avez engagé tous les changements,

git rebase --continue

poursuivra et terminera l'opération de rebasage.


19
2018-03-31 10:23



git rebase --interactive peut être utilisé pour diviser un commit en commits plus petits. le Les docs Git sur rebase ont une procédure pas à pas concise du processus - Split Commits:

En mode interactif, vous pouvez marquer des commits avec l'action "edit". Cependant, cela ne signifie pas nécessairement que git rebase s'attend à ce que le résultat de cette modification soit exactement un commit. En effet, vous pouvez annuler la validation, ou vous pouvez ajouter d'autres validations. Cela peut être utilisé pour diviser un commit en deux:

  • Démarrer un rebasage interactif avec git rebase -i <commit>^, où <commit> est l'engagement que vous voulez diviser. En fait, toute plage de validation fera l'affaire, tant qu'elle contient ce commit.

  • Marquez le commit que vous voulez scinder avec l'action "edit".

  • Quand il s'agit d'éditer ce commit, exécutez git reset HEAD^. L'effet est que le HEAD est rembobiné par un, et l'index suit. Cependant, l'arbre de travail reste le même.

  • Maintenant, ajoutez les changements à l'index que vous voulez avoir dans le premier commit. Vous pouvez utiliser git add (éventuellement interactivement) ou git gui (ou les deux) pour le faire.

  • Validez l'index actuel avec le message de validation approprié.

  • Répétez les deux dernières étapes jusqu'à ce que votre arbre de travail soit propre.

  • Continuez le rebase avec git rebase --continue.

Si vous n'êtes pas absolument certain que les révisions intermédiaires sont cohérentes (compiler, réussir la suite de tests, etc.), vous devez utiliser git stash pour stocker les modifications non encore validées après chaque validation, test et modifier la validation si des correctifs sont nécessaires.


17
2017-07-14 22:25



Vous pouvez faire une refonte interactive git rebase -i. La page Man a exactement ce que vous voulez:

http://git-scm.com/docs/git-rebase#_splitting_commits


10
2018-06-02 16:15



S'il vous plaît noter qu'il y a aussi git reset --soft HEAD^. C'est similaire à git reset (par défaut --mixed) mais il conserve le contenu de l'index. Donc, si vous avez ajouté / supprimé des fichiers, vous les avez déjà dans l'index.

Cela s'avère très utile en cas de commits géants.


7
2017-11-27 15:23



Maintenant, dans la dernière TortoiseGit sur Windows, vous pouvez le faire très facilement.

Ouvrez la boîte de dialogue de rebasage, le configureret effectuez les étapes suivantes.

  • Cliquez avec le bouton droit sur le commit que vous souhaitez diviser et sélectionnez "Edit"(parmi pick, squash, delete ...).
  • Cliquez sur "Start"pour commencer à rebaser.
  • Une fois arrivé à l'engagement de se séparer, cochez la case "Edit/Split"bouton et cliquer sur "Amend"directement" La boîte de dialogue de validation s'ouvre.
    Edit/Split commit
  • Désélectionnez les fichiers que vous souhaitez placer dans un commit séparé.
  • Editez le message de validation, puis cliquez sur "commit".
  • Jusqu'à ce qu'il y ait des fichiers à valider, la boîte de dialogue de validation s'ouvrira encore et encore. Quand il n'y a plus de fichier à valider, il vous demandera quand même si vous voulez ajouter un commit.

Très utile, merci TortoiseGit!


7
2018-04-22 10:32



Je pense que la meilleure façon d'utiliser git rebase -i. J'ai créé une vidéo pour montrer les étapes à suivre pour diviser un commit: https://www.youtube.com/watch?v=3EzOz7e1ADI


1
2017-07-25 11:47



La chose la plus simple à faire sans rebasage interactif est (probablement) de faire une nouvelle branche en commençant par le commit avant celui que vous voulez diviser, cerise-pick -n le commit, réinitialise, stash, valide le déplacement du fichier, réapplique le stash et validez les modifications, puis fusionnez avec l'ancienne branche ou choisissez les commits qui suivent. (Ensuite, changez le nom de l'ancienne branche en tête actuelle.) (Il est probablement préférable de suivre les conseils de MBO et de faire un rebasage interactif.)


0
2018-01-22 17:04