C'est encore plus facile que dans la réponse d'OP.
git rebase -i <any earlier commit>. Cela affiche une liste de commits dans votre éditeur de texte configuré.
Trouvez le commit que vous voulez insérer après (supposons que c'est a1b2c3d). Dans votre éditeur, pour cette ligne, changez picken edit.
Commencez le rebase en fermant votre éditeur de texte (enregistrez vos modifications). Cela vous laisse à une invite de commande avec la validation que vous avez choisie précédemment ( a1b2c3d) comme si elle venait d'être validée .
Apportez vos modifications et git commit( PAS de modification, contrairement à la plupart des edits). Cela crée un nouveau commit après celui que vous avez choisi.
git rebase --continue. Cela relit les commits successifs, laissant votre nouveau commit inséré au bon endroit.
Sachez que cela réécrira l'histoire et brisera quiconque essaiera de tirer.
Cela a ajouté le nouveau commit après le commit, qui est après celui sur lequel je rebasais (également le dernier commit), au lieu de juste après celui sur lequel je rebasais. Le résultat était le même que si j'avais simplement fait un nouveau commit à la fin avec les changements que je voulais insérer. Mon histoire est devenue A -- B -- C -- Dau lieu de désirée A -- D -- B -- C.
XedinUnknown
2
@XedinUnknown: Alors vous n'avez pas utilisé Rebase correctement.
SLaks
3
Maintenant Dpourrait être un commit n'importe où. Supposons que nous ayons A - B - Cet que nous ayons un commit Dqui n'est même pas dans cette branche. Nous connaissons son SHA cependant, nous pouvons le faire git rebase -i HEAD~3. Maintenant, entre les lignes Aet Bpick, nous insérons une nouvellepick ligne qui dit pick SHA, en donnant le hachage du désiré D. Il n'est pas nécessaire que ce soit le hachage complet, mais simplement le hachage raccourci. git rebase -icerise choisit simplement les validations listées par picklignes dans le tampon; il n'est pas nécessaire qu'ils soient les originaux répertoriés pour vous.
Kaz
1
@Kaz Cela ressemble à une réponse différente et valide.
BartoszKP
3
Encore plus simple, vous pouvez utiliser le breakmot - clé dans l'éditeur sur sa propre ligne entre deux commits (ou sur la première ligne, pour insérer un commit avant votre commit spécifié).
SimonT
30
S'avère être assez simple, la réponse trouvée ici . Supposons que vous soyez sur une branche branch. Suivez ces étapes:
créez une branche temporaire à partir du commit après avoir voulu insérer le nouveau commit (dans ce cas commit A):
git checkout -b temp A
effectuez les changements et validez-les, en créant un commit, appelons-le N:
git commit -a -m "Message"
(ou git addsuivi de git commit)
rebase les commits que vous voulez avoir après le nouveau commit (dans ce cas commits Bet C) sur le nouveau commit:
Je n'ai pas pu suivre la réponse acceptée par SLaks, mais cela a fonctionné pour moi. Après avoir obtenu l'historique de validation que je voulais, j'ai dû git push --forcechanger le dépôt distant.
escapecharacter
1
Lorsque vous utilisez rebase, l'option -Xtheirs résout automatiquement les conflits correctement git rebase temp branch -Xtheirs. Réponse utile pour l'injection dans un script!
David C
Pour les noobs comme moi, j'aimerais ajouter cela après git rebase temp branch, mais avant git branch -d temp, tout ce que vous avez à faire est de résoudre et de mettre en scène les conflits et les problèmes de fusion git rebase --continue, c'est-à-dire pas besoin de commettre quoi que ce soit, etc.
Pugsley
19
Solution encore plus simple:
Créez votre nouveau commit à la fin, D. Maintenant vous avez:
A -- B -- C -- D
Puis exécutez:
$ git rebase -i hash-of-A
Git ouvrira votre éditeur et il ressemblera à ceci:
pick 8668d21 B
pick 650f1fc C
pick 74096b9 D
Déplacez simplement D vers le haut comme ceci, puis enregistrez et quittez
Bonne idée, mais il peut être difficile d'introduire D sur C, lorsque vous prévoyez que ces changements soient faits. à A.
BartoszKP
J'ai une situation où j'ai 3 commits que je veux rebaser ensemble et un commit au milieu qui n'est pas lié. C'est super agréable de pouvoir simplement déplacer ce commit plus tôt ou plus tard dans la ligne des commits.
unflores
13
En supposant que l'historique de validation est preA -- A -- B -- C, si vous souhaitez insérer une validation entre Aet B, les étapes sont les suivantes:
git rebase -i hash-of-preA
Git ouvrira votre éditeur. Le contenu peut aimer ceci:
Maintenant, votre historique de commit Git est preA -- A -- I -- B -- C
Si vous rencontrez un conflit, Git s'arrêtera à ce commit. Vous pouvez utiliser git diffpour localiser les marqueurs de conflit et les résoudre. Après avoir résolu tous les conflits, vous devez utiliser git add <filename>pour indiquer à Git que le conflit a été résolu, puis réexécutergit rebase --continue .
Si vous souhaitez annuler le rebase, utilisez git rebase --abort.
Voici une stratégie qui évite de faire un "edit hack" lors du rebase vu dans les autres réponses que j'ai lues.
En utilisant, git rebase -ivous obtenez une liste des validations depuis cette validation. Ajoutez simplement un "break" en haut du fichier, cela provoquera la rupture du rebase à ce stade.
Une fois lancé, git rebaseva maintenant s'arrêter au point de la "pause". Vous pouvez maintenant éditer vos fichiers et créer votre commit normalement. Vous pouvez ensuite continuer le rebase avec git rebase --continue. Cela peut provoquer des conflits que vous devrez résoudre. Si vous vous perdez, n'oubliez pas que vous pouvez toujours annuler l'utilisation de git rebase --abort.
Cette stratégie peut être généralisée pour insérer un commit n'importe où, il suffit de mettre le "break" à l'endroit où vous voulez insérer un commit.
Après avoir réécrit l'histoire, n'oubliez pas de le faire git push -f. Les avertissements habituels concernant d'autres personnes qui récupèrent votre branche s'appliquent.
Désolé, mais j'ai du mal à comprendre comment est ce "éviter le rebase". Vous êtes en cours d' exécution rebaseici. Ce n'est pas beaucoup de différence que vous créiez le commit pendant le rebase ou avant.
BartoszKP
Woops, je voulais dire éviter le "hack d'édition" pendant le rebase, je suppose que je l'ai mal formulé.
axerologementy
Droite. Ma réponse n'utilise pas non plus la fonction «modifier» du rebase. Pourtant, c'est encore une autre approche valable - merci! :-)
BartoszKP
C'est de loin la meilleure solution!
Theodore R. Smith il y a
6
Beaucoup de bonnes réponses ici déjà. Je voulais juste ajouter une solution "no rebase", en 4 étapes faciles.
Résumé
git checkout A
git commit -am "Message for commit D"
git cherry-pick A..C
git branch -f master HEAD
Explication
(Remarque: l'un des avantages de cette solution est que vous ne touchez pas votre branche avant l'étape finale, lorsque vous êtes sûr à 100% que vous êtes d'accord avec le résultat final, vous avez donc une étape de «pré-confirmation» très pratique permettant des tests AB .)
État initial (j'ai supposé masterle nom de votre succursale)
A -- B -- C <<< master <<< HEAD
1) Commencez par pointer HEAD au bon endroit
git checkout A
B -- C <<< master
/
A <<< detached HEAD
(Optionnellement ici, plutôt que de détacher HEAD, nous aurions pu créer une branche temporaire avec git checkout -b temp A, que nous aurions besoin de supprimer à la fin du processus. Les deux variantes fonctionnent, faites comme vous préférez car tout le reste reste le même)
2) Créez le nouveau commit D à insérer
# at this point, make the changes you wanted to insert between A and B, then
git commit -am "Message for commit D"
B -- C <<< master
/
A -- D <<< detached HEAD (or <<< temp <<< HEAD)
3) Ensuite, apportez des copies des derniers commits manquants B et C (serait la même ligne s'il y avait plus de commits)
git cherry-pick A..C
# (if any, resolve any potential conflicts between D and these last commits)
B -- C <<< master
/
A -- D -- B' -- C' <<< detached HEAD (or <<< temp <<< HEAD)
(test AB confortable ici si nécessaire)
Le moment est venu d'inspecter votre code, de tester tout ce qui doit être testé, et vous pouvez également comparer / comparer / inspecter ce que vous aviez et ce que vous obtiendriez après les opérations.
4) En fonction de vos tests entre Cet C', soit c'est OK, soit c'est KO.
(SOIT) 4-OK) Enfin, déplacez la référence demaster
git branch -f master HEAD
B -- C <<< (B and C are candidates for garbage collection)
/
A -- D -- B' -- C' <<< master
(OU) 4-KO) Laissez simplement masterinchangé
Si vous avez créé une branche temporaire, supprimez-la simplement avec git branch -d <name>, mais si vous avez opté pour la route HEAD détachée, aucune action n'est nécessaire à ce stade, les nouveaux commits seront éligibles pour le ramasse-miettes juste après que vous les reconnectiez HEADavec ungit checkout master
Dans ces deux cas (OK ou KO), à ce stade, il suffit de vérifier à masternouveau pour le rattacher HEAD.
Réponses:
C'est encore plus facile que dans la réponse d'OP.
git rebase -i <any earlier commit>
. Cela affiche une liste de commits dans votre éditeur de texte configuré.a1b2c3d
). Dans votre éditeur, pour cette ligne, changezpick
enedit
.a1b2c3d
) comme si elle venait d'être validée .git commit
( PAS de modification, contrairement à la plupart desedit
s). Cela crée un nouveau commit après celui que vous avez choisi.git rebase --continue
. Cela relit les commits successifs, laissant votre nouveau commit inséré au bon endroit.Sachez que cela réécrira l'histoire et brisera quiconque essaiera de tirer.
la source
A -- B -- C -- D
au lieu de désiréeA -- D -- B -- C
.D
pourrait être un commit n'importe où. Supposons que nous ayonsA - B - C
et que nous ayons un commitD
qui n'est même pas dans cette branche. Nous connaissons son SHA cependant, nous pouvons le fairegit rebase -i HEAD~3
. Maintenant, entre les lignesA
etB
pick
, nous insérons une nouvellepick
ligne qui ditpick SHA
, en donnant le hachage du désiréD
. Il n'est pas nécessaire que ce soit le hachage complet, mais simplement le hachage raccourci.git rebase -i
cerise choisit simplement les validations listées parpick
lignes dans le tampon; il n'est pas nécessaire qu'ils soient les originaux répertoriés pour vous.break
mot - clé dans l'éditeur sur sa propre ligne entre deux commits (ou sur la première ligne, pour insérer un commit avant votre commit spécifié).S'avère être assez simple, la réponse trouvée ici . Supposons que vous soyez sur une branche
branch
. Suivez ces étapes:créez une branche temporaire à partir du commit après avoir voulu insérer le nouveau commit (dans ce cas commit
A
):effectuez les changements et validez-les, en créant un commit, appelons-le
N
:(ou
git add
suivi degit commit
)rebase les commits que vous voulez avoir après le nouveau commit (dans ce cas commits
B
etC
) sur le nouveau commit:(vous devez peut-être utiliser
-p
pour conserver les fusions, s'il y en avait - grâce à un commentaire qui n'existe plus de ciekawy )supprimer la branche temporaire:
Après cela, l'historique se présente comme suit:
Il est bien sûr possible que certains conflits apparaissent lors du rebasage.
Dans le cas où votre branche n'est pas uniquement locale, cela introduira un historique de réécriture, ce qui pourrait entraîner de graves problèmes.
la source
git push --force
changer le dépôt distant.git rebase temp branch -Xtheirs
. Réponse utile pour l'injection dans un script!git rebase temp branch
, mais avantgit branch -d temp
, tout ce que vous avez à faire est de résoudre et de mettre en scène les conflits et les problèmes de fusiongit rebase --continue
, c'est-à-dire pas besoin de commettre quoi que ce soit, etc.Solution encore plus simple:
Créez votre nouveau commit à la fin, D. Maintenant vous avez:
Puis exécutez:
Git ouvrira votre éditeur et il ressemblera à ceci:
Déplacez simplement D vers le haut comme ceci, puis enregistrez et quittez
Maintenant, vous aurez:
la source
En supposant que l'historique de validation est
preA -- A -- B -- C
, si vous souhaitez insérer une validation entreA
etB
, les étapes sont les suivantes:git rebase -i hash-of-preA
Git ouvrira votre éditeur. Le contenu peut aimer ceci:
Remplacez le premier
pick
paredit
:Sauvegarder et quitter.
Modifiez votre code puis
git add . && git commit -m "I"
git rebase --continue
Maintenant, votre historique de commit Git est
preA -- A -- I -- B -- C
Si vous rencontrez un conflit, Git s'arrêtera à ce commit. Vous pouvez utiliser
git diff
pour localiser les marqueurs de conflit et les résoudre. Après avoir résolu tous les conflits, vous devez utilisergit add <filename>
pour indiquer à Git que le conflit a été résolu, puis réexécutergit rebase --continue
.Si vous souhaitez annuler le rebase, utilisez
git rebase --abort
.la source
Voici une stratégie qui évite de faire un "edit hack" lors du rebase vu dans les autres réponses que j'ai lues.
En utilisant,
git rebase -i
vous obtenez une liste des validations depuis cette validation. Ajoutez simplement un "break" en haut du fichier, cela provoquera la rupture du rebase à ce stade.Une fois lancé,
git rebase
va maintenant s'arrêter au point de la "pause". Vous pouvez maintenant éditer vos fichiers et créer votre commit normalement. Vous pouvez ensuite continuer le rebase avecgit rebase --continue
. Cela peut provoquer des conflits que vous devrez résoudre. Si vous vous perdez, n'oubliez pas que vous pouvez toujours annuler l'utilisation degit rebase --abort
.Cette stratégie peut être généralisée pour insérer un commit n'importe où, il suffit de mettre le "break" à l'endroit où vous voulez insérer un commit.
Après avoir réécrit l'histoire, n'oubliez pas de le faire
git push -f
. Les avertissements habituels concernant d'autres personnes qui récupèrent votre branche s'appliquent.la source
rebase
ici. Ce n'est pas beaucoup de différence que vous créiez le commit pendant le rebase ou avant.Beaucoup de bonnes réponses ici déjà. Je voulais juste ajouter une solution "no rebase", en 4 étapes faciles.
Résumé
Explication
(Remarque: l'un des avantages de cette solution est que vous ne touchez pas votre branche avant l'étape finale, lorsque vous êtes sûr à 100% que vous êtes d'accord avec le résultat final, vous avez donc une étape de «pré-confirmation» très pratique permettant des tests AB .)
État initial (j'ai supposé
master
le nom de votre succursale)1) Commencez par pointer HEAD au bon endroit
(Optionnellement ici, plutôt que de détacher HEAD, nous aurions pu créer une branche temporaire avec
git checkout -b temp A
, que nous aurions besoin de supprimer à la fin du processus. Les deux variantes fonctionnent, faites comme vous préférez car tout le reste reste le même)2) Créez le nouveau commit D à insérer
3) Ensuite, apportez des copies des derniers commits manquants B et C (serait la même ligne s'il y avait plus de commits)
(test AB confortable ici si nécessaire)
Le moment est venu d'inspecter votre code, de tester tout ce qui doit être testé, et vous pouvez également comparer / comparer / inspecter ce que vous aviez et ce que vous obtiendriez après les opérations.
4) En fonction de vos tests entre
C
etC'
, soit c'est OK, soit c'est KO.(SOIT) 4-OK) Enfin, déplacez la référence de
master
(OU) 4-KO) Laissez simplement
master
inchangéSi vous avez créé une branche temporaire, supprimez-la simplement avec
git branch -d <name>
, mais si vous avez opté pour la route HEAD détachée, aucune action n'est nécessaire à ce stade, les nouveaux commits seront éligibles pour le ramasse-miettes juste après que vous les reconnectiezHEAD
avec ungit checkout master
Dans ces deux cas (OK ou KO), à ce stade, il suffit de vérifier à
master
nouveau pour le rattacherHEAD
.la source