1
votes

Supprimer le premier commit poussé d'une branche

J'ai le scénario que je voudrais annuler le premier commit sur ma branche. Une solution simple serait de créer une nouvelle branche, puis de déplacer tous les commits sauf les premiers de ma première branche vers la nouvelle et de supprimer l'ancienne branche.

J'imagine que cela peut être fait d'une manière plus agréable en pliant simplement le base de ma branche. Une telle chose est possible ? J'essaye de le dessiner:

actuel:

master a - b ---------------------
skip        \ revertB              \
branch1                             \ - c - d

voulu: p >

master   a - b 
branch1       \ - c - d 

possible ?:

master   a - b 
branch1       \ revertB - c - d

Je n'ai pas besoin du commit revertB. Comment puis-je y parvenir ou est-ce une mauvaise pratique? Merci d'avance :)

git

3 commentaires

De quoi voulez-vous vous débarrasser? juste le "revertB" apparaissant dans les journaux, ou aussi les modifications qu'il a apportées?


tous les changements, en gros, je veux juste qu'ils soient supprimés


rebase est LA façon de le faire.


3 Réponses :


1
votes

"possible?"

Définitivement.

Une manière parmi d'autres d'y parvenir:

# create your "skip" branch
git checkout -b skip <commitHash of "revertB">

# repair branch1 by resetting to master then recreating commits c and d
git checkout -B branch1 master
git cherry-pick c d


2 commentaires

Cela fait manuellement ce que git rebase fait pour vous automatiquement, car `git rebase under the cover effectue des sélections pour les commits que vous conservez.


Oui. Mais faire les choses anatomiquement ici n'est ni plus lourd ni plus complexe. Et cela donne une idée claire de ce qui doit être fait. Les deux méthodes appartiennent ici, je suis heureux que nous nous soyons associés pour les présenter.



2
votes

git rebase - sur b c branch1

Cela prend tous les commits sur branch1 à partir de c et les rebase en b .

Pensez-y comme couper une branche sur un arbre et greffer à nouveau --onto une autre partie de l'arbre ( b ).

Git rebase est puissant. Apprenez à l'utiliser! Surtout en mode interactif ( git rebase -i ). Pour un exemple de sa puissance, et pour avoir une idée du fonctionnement de git rebase , consultez la section the todo file explique de https://stackoverflow.com/a/61411955/8910547


9 commentaires

Je pense que c'est exactement ce que je veux. Je viens de vérifier un exemple, ne serait-ce pas git rebase --onto b revertb ? Ou est-ce que j'interprète mal git rebase --onto à partir d'ici: stackoverflow.com/questions/29914052/...


Oui, vous interprétez mal. Croyez-moi. Si vous voulez jouer en toute sécurité, créez une nouvelle branche sur d et rebasez-la comme un essai (en utilisant ma commande ci-dessus mais la nouvelle référence brach au lieu de d).


Très bien, vous êtes le pro ici: D J'essaie juste de le comprendre. Je lis que le mode à trois paramètres fonctionne comme ceci: git rebase --onto donc cela signifierait que je dois le faire comme ceci: git rebase --onto b revertb d n'est-ce pas? : D désolé mon cerveau est à la traîne rn


Pas assez. Pas . C'est assez simple si vous laissez tomber ce que vous avez dans la tête et intériorisez l'analogie «couper une branche» que j'ai donnée dans ma réponse. Vous prenez une branche coupée définie par ses points de début et de fin ( c d ) et greffage ONTO b .


Concernant "Si vous voulez jouer la sécurité", il y a toujours le git reflog pour annuler toutes les modifications que vous avez faites tant que vous ne les avez pas poussées


Oui, tous vos anciens engagements restent un certain temps (des semaines ou des mois). Vous les voyez toujours avec git log --graph --oneline --reflog --all . Vous pouvez toujours rejoindre et ramener la tête vers un commit qu'il a pointé vers le passé.


Ma faute. PARDON. Je n'arrêtais pas de penser que d était le nom de votre succursale. Je vais mettre à jour ma réponse maintenant! Pardon. Et vous n'avez pas à vous soucier de ce que vous n'avez pas encore fait ... branch1 n'est pas affecté, et vous venez de créer des commits orphelins rebasés qui n'ont pas d'importance et qui le seront gc'd automatiquement à l'avenir.


@Inigo Merci de m'avoir aidé à traverser. À la fin, j'ai pu le faire via le maître rebase -i. Mais je suppose que votre commande modifiée l'aurait corrigé pour moi aussi. Vous m'avez beaucoup aidé à comprendre au moins un peu `` rebase '': D


@ scholl123 heureux que cela ait fonctionné pour vous. Supprimons tous les deux nos commentaires ci-dessus qui ne sont plus pertinents compte tenu de ma réponse mise à jour. Le long fil de discussion est déroutant pour les futurs lecteurs et l'objectif de SO est des questions et réponses qui ont une valeur pour les futurs lecteurs.



1
votes

Si vous n'avez encore rien envoyé, vous pouvez modifier votre historique de de plusieurs façons a >. Si vous avez poussé votre état, vous devez tenir compte de l'impact qu'il aura!

Vous causerez des problèmes à tous les collaborateurs qui ont créé des commits au-dessus de branch1 mais ne les ont pas encore poussés. Si personne d'autre que vous n'a jamais utilisé branch1 , ça devrait aller.

Je trouve la manière la plus intuitive d'utiliser

git add myfile
git rebase --continue
Cela ouvre un fichier texte comme celui-ci. Changez le commit dont vous souhaitez vous débarrasser en drop comme je l'ai fait ci-dessous. Puis enregistrez le fichier et quittez.
<<<<<<< HEAD
b
=======
c
>>>>>>> 2657446... c

Comme j'ai toujours modifié la même ligne dans mon dépôt de test pour cette réponse, j'ai eu un conflit de fusion. Dans le commit b, j'ai écrit b . Dans le commit c, j'ai écrit c . Dans commit revertB, j'ai écrit revertB.

drop 1a432d7 revertB
pick 2657446 c
pick 8d15847 d

# Rebase 1219262..8d15847 onto 1219262 (3 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

Vous devrez corriger vos conflits de fusion si vous en rencontrez. Dans mon cas, j'ai remplacé le contenu du fichier par c .

Continuez le rebase après avoir préparé le fichier corrigé:

git checkout branch1
git rebase -i master

Vous avez la possibilité de modifier le message de validation de commit c. Une fois que vous l'avez confirmé, revertB est parti de branch1.


5 commentaires

Cela semble assez sympa, pouvez-vous expliquer ce que fait le master dans git rebase -i master ?


@ scholl123 Sans fouiller le manuel pour revérifier: Vous dites à git de rebaser votre branche actuelle "sur" une autre. C'est à dire. tout commit avant celui où branch1 dérivé du master n'est pas pris en compte.


Merci @Inigo! Votre réponse était la première et est plus propre. Je viens d'ajouter le mien car le rebase interactif permet de ne pas se soucier des détails des drapeaux et de souligner que c'est une mauvaise idée si la branche est utilisée par d'autres collaborateurs


J'ADORE en fait le mode interactif ♥ ️ ♥ ️ ♥ ️. Si l'OP voulait sauter plus de commits, réorganiser, squash, etc., vous répondez que c'est la voie à suivre!


J'ai fini par utiliser votre méthode, grâce à vous et @Inigo! Vous avez beaucoup aidé