Casser un engagement précédent en plusieurs commits

Sans créer une twig et faire un tas de travail génial sur une nouvelle twig, est-il possible de diviser un seul engagement en plusieurs commits après avoir été validé dans le référentiel local?

git rebase -i fera.

Tout d’abord, commencez par un répertoire de travail propre: l’ git status ne doit afficher aucune modification, suppression ou ajout en attente.

Pour séparer votre engagement le plus récent, commencez par:

 $ git reset HEAD~ 

Commencez maintenant les pièces individuellement de la manière habituelle, produisant autant de commits que vous en avez besoin.

S’il était plus loin dans l’arbre, alors

 $ git rebase -i HEAD~3 

3 est combien il y a de commits.

Si c’était plus en arrière dans l’arbre que vous voulez compter, alors

 $ git rebase -i 123abcd~ 

123abcd est le SHA1 du commit à diviser.

Lorsque vous obtenez l’écran de modification de rebase, trouvez le commit que vous souhaitez séparer. Au début de cette ligne, remplacez pick par edit ( e en abrégé). Enregistrez le tampon et quittez. Rebase va maintenant s’arrêter juste après la validation que vous souhaitez modifier. Alors:

 $ git reset HEAD~ 

Commencez les pièces individuellement de la manière habituelle, produisant autant de commits que nécessaire, puis

 $ git rebase --continue 

A partir du manuel git-rebase (section SPLITTING COMMITS)

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

  • Démarrez un rebase interactif avec git rebase -i ^ , où est le commit que vous souhaitez diviser. En fait, toute plage de validation fera l’affaire, tant qu’elle contient cette validation.

  • Marquez le commit que vous souhaitez partager avec l’action “edit”.

  • Quand il s’agit de modifier cette validation, exécutez git reset HEAD^ . L’effet est que le HEAD est rembobiné de un et que l’index suit. Cependant, l’arbre de travail rest le même.

  • Ajoutez maintenant les modifications à l’index que vous souhaitez avoir dans le premier commit. Vous pouvez utiliser git add (éventuellement interactivement) ou git gui (ou les deux) pour le faire.

  • Validez l’index maintenant avec n’importe quel 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 .

Utilisez git rebase --interactive pour éditer cette validation antérieure, lancez git reset HEAD~ , puis git add -p pour en append, puis faites un commit, puis ajoutez-en d’autres et faites un autre commit, autant de fois que vous le souhaitez. Une fois que vous avez terminé, lancez git rebase --continue , et vous aurez tout le partage validé plus tôt dans votre stack.

Important : notez que vous pouvez effectuer toutes les modifications souhaitées et ne pas avoir à vous soucier de la perte d’anciennes modifications, car vous pouvez toujours lancer git reflog pour trouver le sharepoint votre projet contenant les modifications souhaitées (appelons il a8c4ab ), puis 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 (eh bien, j’utilise le 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 deuxième commit, two .

git rebase --interactive HEAD~2

Cela fait apparaître un message qui ressemble à ceci:

 pick 2b613bc two pick bfb8e46 three 

Modifiez le premier pick en un e pour modifier ce commit.

git reset HEAD~

git diff nous montre que nous venons de déstabiliser le commit que nous avons fait pour le deuxième commit:

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

Mettons en scène ce changement et ajoutons “et un tiers” à cette ligne du fichier A

git add .

C’est généralement le point lors d’un rebase interactif où nous git rebase --continue , car nous souhaitons généralement revenir dans notre stack de validations pour éditer un commit précédent. Mais cette fois, nous voulons créer un nouveau commit. Nous allons donc lancer git commit -am 'two and a third' . Nous modifions maintenant le fichier A et ajoutons la ligne two and two thirds .

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

Nous avons un conflit avec notre commit, three , résolvons le problème:

Nous changerons

 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 à ceci:

 commit e59ca35bae8360439823d66d459238779e5b4892 Author: Rose Perrone  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  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  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  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 

Les réponses précédentes couvraient l’utilisation de git rebase -i pour éditer le commit que vous souhaitez diviser et le valider en plusieurs parties.

Cela fonctionne bien lors de la division des fichiers en différents commits, mais si vous voulez séparer les modifications apscopes aux fichiers individuels, vous devez en savoir plus.

Après avoir rebase -i à la validation que vous souhaitez diviser, en utilisant rebase -i et en la marquant pour l’ edit , vous avez deux options.

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

  2. Modifiez la copie de travail pour supprimer les modifications inutiles. engager cet état intérimaire; puis retirez le plein engagement pour le tour suivant.

L’option 2 est utile si vous divisez une validation importante, car elle vous permet de vérifier que les versions provisoires sont compilées et exécutées correctement dans le cadre de la fusion. Cela se déroule comme suit.

Après avoir utilisé rebase -i et edit 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 de votre engagement initial. La seule différence est de savoir si vous commencez avec tous les changements mis en scène ou avec tous les changements.

Maintenant, entrez et modifiez le code. Vous pouvez supprimer des modifications, supprimer des fichiers ajoutés et faire ce que vous voulez pour créer le premier commit 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, installez / démontez les fichiers selon vos besoins (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 engagement fait. Maintenant, vous voulez restaurer votre copie de travail dans l’état où elle se trouvait après la validation que vous divisez, afin de pouvoir prendre plus de modifications pour votre prochain commit. Pour trouver le sha1 du commit que vous éditez, utilisez le git status . Dans les premières lignes du statut, 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 65dfb6a a sha1 65dfb6a . Sachant cela, je peux vérifier le contenu de cette validation sur mon répertoire de travail en utilisant la forme de git checkout de git checkout qui prend à la fois un emplacement de validation et un emplacement de fichier. Ici, j’utilise . comme emplacement du fichier pour remplacer la copie de travail entière:

 git checkout 65dfb6a . 

Ne manquez pas le point à la fin!

Cela va extraire et mettre en scène les fichiers tels qu’ils étaient après la validation que vous éditez, mais par rapport à la validation précédente que vous avez effectuée, donc toutes les modifications que vous avez déjà effectuées ne feront pas partie de la validation.

Vous pouvez soit continuer maintenant et le valider tel quel pour terminer le fractionnement, soit recommencer, en supprimant certaines parties de la validation avant de procéder à une nouvelle validation provisoire.

Si vous souhaitez réutiliser le message de validation d’origine pour une ou plusieurs validations, vous pouvez l’utiliser directement à partir des fichiers de travail de la rebase:

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

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

 git rebase --continue 

poursuivra et complétera l’opération de rebase.

git rebase --interactive peut être utilisé pour diviser un commit en petits commits. Les documents de Git sur rebase ont une présentation concise du processus – Splitting Commits :

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

  • Démarrez un rebase interactif avec git rebase -i ^ , où est le commit que vous souhaitez diviser. En fait, toute plage de validation fera l’affaire, tant qu’elle contient cette validation.

  • Marquez le commit que vous souhaitez partager avec l’action “edit”.

  • Quand il s’agit de modifier cette validation, exécutez git reset HEAD^ . L’effet est que le HEAD est rembobiné de un et que l’index suit. Cependant, l’arbre de travail rest le même.

  • Ajoutez maintenant les modifications à l’index que vous souhaitez avoir dans le premier commit. Vous pouvez utiliser git add (éventuellement interactivement) ou git gui (ou les deux) pour le faire.

  • Validez l’index maintenant avec n’importe quel 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 (elles comstacknt, transmettent la suite de tests, etc.), vous devez utiliser git stash pour cacher les modifications non encore validées après chaque validation, modification et modification des validations. sont nécessaires.

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

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

Veuillez noter que git reset --soft HEAD^ . Il est similaire à git reset (qui --mixed défaut – --mixed ) mais conserve le contenu de l’index. Ainsi, si vous avez ajouté / supprimé des fichiers, vous les avez déjà dans l’index.

S’avère très utile en cas de commits géants.

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

Ouvrez la boîte de dialog de rebase, configurez -le et procédez comme suit.

  • Cliquez avec le bouton droit de la souris sur la validation que vous souhaitez diviser et sélectionnez ” Edit ” (parmi les sélections, les squash, les supprimer …).
  • Cliquez sur ” Start ” pour lancer le rebasage.
  • Une fois arrivé à la validation de la division, cochez le bouton ” Edit/Split ” et cliquez sur ” Amend ” directement. La boîte de dialog de validation s’ouvre.
    Edit / Split commit
  • Désélectionnez les fichiers que vous souhaitez placer sur un commit séparé.
  • Modifiez le message de validation, puis cliquez sur ” commit “.
  • Tant qu’il n’y a pas de fichiers à valider, la boîte de dialog de validation s’ouvre à plusieurs resockets. Lorsqu’il n’y a plus de fichier à valider, il vous demandera toujours si vous souhaitez en append un autre.

Très utile, merci TortoiseGit!

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

La chose la plus facile à faire sans un rebasage interactif est (probablement) de faire en sorte qu’une nouvelle twig commence à la validation avant celle que vous voulez diviser, cueillir à la cerise, commettre, réinitialiser, cacher le déplacement du fichier, validez les modifications, puis fusionnez avec la twig précédente ou sélectionnez les commandes qui ont suivi. (Ensuite, changez le nom de l’ancienne twig en son en-tête actuel.) (Il est probablement préférable de suivre les conseils de MBO et de faire un rebase interactif.)

Si vous avez ceci:

 A - B <- mybranch 

Où vous avez commis du contenu dans commit B:

 /modules/a/file1 /modules/a/file2 /modules/b/file3 /modules/b/file4 

Mais vous voulez diviser B en C-D et obtenir ce résultat:

 A - C - D <-mybranch 

Vous pouvez par exemple diviser le contenu comme ceci (contenu de différents répertoires dans différents commits) ...

Réinitialiser la twig à la validation avant celle à séparer:

 git checkout mybranch git reset --hard A 

Créez le premier commit (C):

 git checkout B /modules/a git add -u git commit -m "content of /modules/a" 

Créez un deuxième commit (D):

 git checkout B /modules/b git add -u git commit -m "content of /modules/b"