Briser un précédent commit en commits multiples
sans créer une branche et sans faire un tas de travail funky sur une nouvelle branche, est-il possible de casser une seule propagation en quelques propagation différentes après qu'elle ait été engagée dans le dépôt local?
11 réponses
git rebase -i
je le ferai.
tout d'abord, commencez par un répertoire de travail propre: git status
ne doit pas afficher de modifications, suppressions ou ajouts en attente.
pour séparer votre plus récent commit, d'abord:
$ git reset HEAD~
maintenant, commettez les pièces individuellement de la manière habituelle, en produisant autant de commits que vous avez besoin.
S'il était plus loin dans l'arbre, puis
$ git rebase -i HEAD~3
où 3
est combien de commit back il est.
S'il était plus loin dans l'arbre que vous voulez compter, alors
$ git rebase -i 123abcd~
où 123abcd
est la SHA1 de la commission que vous voulez diviser.
lorsque vous obtenez l'écran rebase edit, trouvez la propagation que vous voulez séparer. Au début de cette ligne, remplacer pick
avec edit
( e
). Économiser de la mémoire tampon et de sortie. Rebase va maintenant s'arrêter juste après la propagation que vous voulez éditer. Puis:
$ git reset HEAD~
Commettre les pièces individuellement de la manière habituelle, la production comme de nombreux engage que vous en avez besoin, puis
$ git rebase --continue
From git-rebase manual (SPLITTING COMMITS section)
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 une propagation. En effet, vous pouvez annuler la livraison, ou vous pouvez ajouter d'autres validations. Cela peut être utilisé pour diviser un commit en deux:
Démarrer une rebase interactive avec
git rebase -i <commit>^
, où<commit>
est le commit que vous voulez partager. En fait, n'importe quelle plage de propagation fera l'affaire, tant qu'elle contient cette propagation.marquez le commit que vous voulez partager avec l'action"edit".
quand il s'agit d'éditer ce commit, exécutez
git reset HEAD^
. L'effet est que la tête est rebondie par un, et l'indice suit la même. Cependant, l'arbre de travail reste le même.ajoutez maintenant les modifications à l'index que vous voulez avoir dans la première propagation. Vous pouvez utiliser
git add
(peut-être de façon interactive) ougit gui
(ou les deux) pour faire cela.Commettre l'indice actuel avec ce message de commit est approprié maintenant.
répétez les deux dernières étapes jusqu'à ce que votre arbre de travail soit propre.
continuer le rebase avec
git rebase --continue
.
utilisez git rebase --interactive
pour éditer ce commit, Lancez git reset HEAD~
, puis git add -p
pour en ajouter, puis faites un commit, puis ajoutez un autre et faites un autre commit, autant de fois que vous le souhaitez. Quand vous aurez terminé, lancez git rebase --continue
, et vous aurez toutes les Split commits 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 la perte de vieux changements, parce que vous pouvez toujours exécuter git reflog
pour trouver le point votre projet qui contient les modifications que vous souhaitez, (appelons-le a8c4ab
), puis git reset a8c4ab
.
Voici une série de commandes pour montrer comment ça marche:
mkdir git-test; cd git-test; git init
maintenant ajouter un fichier A
vi A
ajouter cette ligne:
one
git commit -am one
puis ajouter cette ligne à A:
two
git commit -am two
puis ajouter 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 la Deuxième Commission, two
.
git rebase --interactive HEAD~2
ceci amène un message qui ressemble à ceci:
pick 2b613bc two
pick bfb8e46 three
Modifier le premier pick
à une e
pour modifier les commettre.
git reset HEAD~
git diff
s'engager:
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 ajoutez" et un tiers "à cette ligne dans le fichier A
.
git add .
c'est habituellement le point lors d'un rebase interactif où nous exécutons git rebase --continue
, parce que nous voulons simplement retourner dans notre pile de propagations pour éditer une propagation antérieure. Mais cette fois, nous voulons créer un nouveau commit. Donc on va lancer git commit -am 'two and a third'
. Maintenant, nous éditons le fichier A
et ajouter 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
, donc, nous allons le résoudre:
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 à ceci:
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
les réponses précédentes ont couvert l'utilisation de git rebase -i
pour éditer la propagation que vous voulez diviser, et la propager en plusieurs parties.
cela fonctionne bien lors de la division des fichiers en différentes propagations, mais si vous voulez séparer les modifications des fichiers individuels, il y a plus que vous devez savoir.
ayant obtenu le commit que vous voulez partager, en utilisant rebase -i
et en le marquant pour edit
, vous avez deux options.
-
après avoir utilisé
git reset HEAD~
, passez en revue les patches individuellement en utilisantgit add -p
pour sélectionner ceux que vous voulez dans chaque propagation -
éditez la copie de travail pour supprimer les changements que vous ne voulez pas; commit cet état provisoire; et puis retirez le commit complet pour le tour suivant.
L'Option 2 est utile si vous divisez un grand commit, car elle vous permet de vérifier que les versions intermédiaires se construisent et fonctionnent correctement dans le cadre de la fusion. Cela se déroule comme suit.
après rebase -i
et edit
dans la commande, Utiliser
git reset --soft HEAD~
pour annuler la propagation, mais laisser les fichiers engagé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 commit initial. La seule différence est si vous commencez avec tous les changements mis en place ou avec eux tous les unstaged.
allez maintenant éditer le code. Vous pouvez supprimer des modifications, supprimer des fichiers ajoutés, et faire tout ce que vous voulez pour construire la première propagation de la série que vous recherchez. Vous pouvez aussi le construire, l'exécuter et confirmer que vous avez un ensemble cohérent de sources.
une fois que vous êtes heureux, étape/décompactage des fichiers au besoin (j'aime utiliser git gui
pour cela), et commit les modifications à travers L'UI ou la ligne de commande
git commit
C'est la première fois. Maintenant, vous voulez restaurer votre copie de travail à l'état qu'il avait après la validation, vous êtes fractionnement, de sorte que vous pouvez prendre plus de changements pour votre prochain commit. Pour trouver le sha1 de la propagation que vous éditez, utilisez git status
. Dans les premières lignes de l'état, vous verrez la commande rebase qui est en cours d'exécution, dans laquelle vous pouvez trouver le sha1 de votre commit original:
$ 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 comit que je suis en train d'éditer a sha1 65dfb6a
. Sachant cela, je peux vérifier le contenu de cette propagation sur mon répertoire de travail en utilisant la forme git checkout
qui prend à la fois une propagation et une localisation de fichier. Ici j'utilise .
comme emplacement du fichier pour remplacer toute la copie de travail:
git checkout 65dfb6a .
ne manquez pas le point à la fin!
cela vérifiera, et mettra en scène, les fichiers comme ils étaient après la propagation que vous éditez, mais relatif à la propagation précédente que vous avez faite, de sorte que les changements que vous avez déjà commis ne feront pas partie de la propagation.
vous pouvez soit aller de l'avant maintenant et le commettre comme-est pour terminer la scission, ou aller autour de nouveau, en supprimant certaines parties de la commit avant de faire une autre commit intérimaire.
si vous voulez réutiliser le message de propagation original pour une ou plusieurs propagations, vous pouvez l'utiliser directement à partir des fichiers de travail de la base de données:
git commit --file .git/rebase-merge/message
Enfin, une fois que vous avez engagé tous les changements,
git rebase --continue
va poursuivre et compléter l'opération rebase.
git rebase --interactive
peut être utilisé pour diviser un commit en commits plus petits. Le Git docs sur rebase ont un aperçu concis du processus-fractionnement Commits :
en mode interactif, vous pouvez marquer 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 une propagation. En effet, vous pouvez annuler la livraison, ou vous pouvez ajouter d'autres validations. Cela peut être utilisé pour diviser un commit en deux:
lancez un rebase interactif avec
git rebase -i <commit>^
, où<commit>
est le commit que vous voulez partager. En fait, n'importe quelle plage de propagation fera l'affaire, tant qu'elle contient cette propagation.Marquez l'engagement que vous voulez partager avec l'action "edit".
quand il s'agit d'éditer ce commit, exécutez
git reset HEAD^
. L'effet est que la tête est rebondie par un, et l'indice suit la même. Cependant, l'arbre de travail reste la même.Maintenant, ajoutez les modifications à l'index que vous voulez avoir dans la première propagation. Vous pouvez utiliser
git add
(peut-être de façon interactive) ou git gui (ou les deux) pour faire cela.Commettre l'indice actuel avec ce message de commit est approprié maintenant.
répétez les deux dernières étapes jusqu'à ce que votre arbre de travail soit propre.
Continue le rebase avec
git rebase --continue
.si vous n'êtes pas absolument sûr que les révisions intermédiaires sont cohérentes (elles compilent, passent le test, etc.) vous devez utiliser
git stash
pour cacher les changements non-encore engagés après chaque propagation, test, et modifier la propagation si les corrections sont nécessaire.
vous pouvez faire le rebase interactif git rebase -i
. Page de manuel a exactement ce que vous voulez:
veuillez noter qu'il y a aussi git reset --soft HEAD^
. Il est similaire à git reset
(qui par défaut à --mixed
) mais il conserve le contenu de l'index. De sorte que si vous avez ajouté ou supprimé des fichiers, vous les avez dans l'index.
S'avère très utile en cas de propagation géante.
maintenant dans le dernier TortoiseGit sur Windows, vous pouvez le faire très facilement.
ouvrez la boîte de dialogue rebase, configurez-la , et faites les étapes suivantes.
- faites un clic droit sur le commit que vous voulez partager et sélectionnez"
Edit
" (au choix, au hasard, supprimer)...). - , Cliquez sur
Start
" pour démarrer l'année de référence. - une fois qu'il arrive à la commit to split, vérifiez le " "151920920 le bouton" " et
cliquez sur "
Amend
" directement. Le dialogue de propagation s'ouvre.
- Désélectionner les fichiers que vous voulez mettre sur une autre validation.
- édite le message de propagation, puis clique sur "
commit
". - Jusqu'à ce qu'il y ait des fichiers à propager, le dialogue de propagation s'ouvrira encore et encore. Quand il n'y a plus de fichier à propager, il vous demander si vous voulez ajouter un plus commettre.
très utile, merci TortoiseGit !
je pense que la meilleure façon que j'utilise git rebase -i
. J'ai créé une vidéo pour montrer les étapes pour partager un commit: https://www.youtube.com/watch?v=3EzOz7e1ADI
la chose la plus facile à faire sans un rebase interactif est (probablement) de faire une nouvelle branche à partir de la propagation avant celle que vous voulez diviser, cherry-pick-n la propagation, reset, stash, commit le mouvement de fichier, reapply la propagation et commit les changements, et puis soit fusionner avec l'ancienne branche ou cherry-pick les commits qui ont suivi. (Puis changer le nom de l'ancienne branche à la tête courante.) (Il est probablement préférable de suivre les conseils de MBOs et de faire un rebase interactif.)
si vous avez ceci:
A - B <- mybranch
où vous avez commis un contenu en 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 diviser le contenu comme ceci par exemple (contenu de différents répertoires dans différentes propagations)...
réinitialiser la branche de nouveau à la commit avant celle à split:
git checkout mybranch
git reset --hard A
Créer le premier commit (C):
git checkout B /modules/a
git add -u
git commit -m "content of /modules/a"
Créer un deuxième commit (D):
git checkout B /modules/b
git add -u
git commit -m "content of /modules/b"