D'après les autres réponses ici, j'étais un peu confus avec la façon dont git rebase -i
pourrait être utilisé pour supprimer un commit, donc j'espère que c'est OK de noter mon cas de test ici (très similaire à l'OP).
Voici un bash
script que vous pouvez coller pour créer un référentiel de test dans le /tmp
dossier:
set -x
rm -rf /tmp/myrepo*
cd /tmp
mkdir myrepo_git
cd myrepo_git
git init
git config user.name me
git config user.email me@myself.com
mkdir folder
echo aaaa >> folder/file.txt
git add folder/file.txt
git commit -m "1st git commit"
echo bbbb >> folder/file.txt
git add folder/file.txt
git commit -m "2nd git commit"
echo cccc >> folder/file.txt
git add folder/file.txt
git commit -m "3rd git commit"
echo dddd >> folder/file.txt
git add folder/file.txt
git commit -m "4th git commit"
echo eeee >> folder/file.txt
git add folder/file.txt
git commit -m "5th git commit"
À ce stade, nous avons un file.txt
avec ces contenus:
aaaa
bbbb
cccc
dddd
eeee
À ce stade, HEAD est au 5ème commit, HEAD ~ 1 serait le 4ème - et HEAD ~ 4 serait le 1er commit (donc HEAD ~ 5 n'existerait pas). Disons que nous voulons supprimer le 3e commit - nous pouvons émettre cette commande dans le myrepo_git
répertoire:
git rebase -i HEAD~4
( Notez que les git rebase -i HEAD~5
résultats avec "fatal: Besoin d'une seule révision; invalide en amont HEAD ~ 5". ) Un éditeur de texte (voir capture d'écran dans la réponse de @Dennis ) s'ouvrira avec ces contenus:
pick 5978582 2nd git commit
pick 448c212 3rd git commit
pick b50213c 4th git commit
pick a9c8fa1 5th git commit
# Rebase b916e7f..a9c8fa1 onto b916e7f
# ...
Nous obtenons donc tous les commits depuis (mais sans inclure ) notre HEAD demandé ~ 4. Supprimez la ligne pick 448c212 3rd git commit
et enregistrez le fichier; vous obtiendrez cette réponse de git rebase
:
error: could not apply b50213c... 4th git commit
When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To check out the original branch and stop rebasing run "git rebase --abort".
Could not apply b50213c... 4th git commit
À ce stade, ouvrez myrepo_git / folder/file.txt
dans un éditeur de texte; vous verrez qu'il a été modifié:
aaaa
bbbb
<<<<<<< HEAD
=======
cccc
dddd
>>>>>>> b50213c... 4th git commit
Fondamentalement, git
voit que lorsque HEAD est arrivé au 2e commit, il y avait du contenu de aaaa
+ bbbb
; puis il a un patch de cccc
+ ajouté dddd
qu'il ne sait pas comment ajouter au contenu existant.
Donc, ici, git
vous ne pouvez pas décider pour vous - c'est vous qui devez prendre une décision: en supprimant le 3e commit, soit vous gardez les changements introduits par lui (ici, la ligne cccc
) - soit vous ne le faites pas. Si vous ne le faites pas, supprimez simplement les lignes supplémentaires - y compris le cccc
- en folder/file.txt
utilisant un éditeur de texte, pour qu'il ressemble à ceci:
aaaa
bbbb
dddd
... puis enregistrez folder/file.txt
. Vous pouvez maintenant exécuter les commandes suivantes dans le myrepo_git
répertoire:
$ nano folder/file.txt # text editor - edit, save
$ git rebase --continue
folder/file.txt: needs merge
You must edit all merge conflicts and then
mark them as resolved using git add
Ah - donc pour marquer que nous avons résolu le conflit, nous devons git add
le folder/file.txt
, avant de faire git rebase --continue
:
$ git add folder/file.txt
$ git rebase --continue
Ici, un éditeur de texte s'ouvre à nouveau, montrant la ligne 4th git commit
- ici, nous avons une chance de changer le message de validation (qui dans ce cas pourrait être significativement changé en 4th (and removed 3rd) commit
ou similaire). Disons que vous ne voulez pas - alors quittez simplement l'éditeur de texte sans enregistrer; une fois que vous faites cela, vous obtiendrez:
$ git rebase --continue
[detached HEAD b8275fc] 4th git commit
1 file changed, 1 insertion(+)
Successfully rebased and updated refs/heads/master.
À ce stade, vous avez maintenant un historique comme celui-ci (que vous pouvez également inspecter avec disons gitk .
ou d'autres outils) du contenu de folder/file.txt
(avec, apparemment, des horodatages inchangés des commits originaux):
1st git commit | +aaaa
----------------------------------------------
2nd git commit | aaaa
| +bbbb
----------------------------------------------
4th git commit | aaaa
| bbbb
| +dddd
----------------------------------------------
5th git commit | aaaa
| bbbb
| dddd
| +eeee
Et si précédemment, nous avions décidé de conserver la ligne cccc
(le contenu du 3ème commit git que nous avions supprimé), nous aurions eu:
1st git commit | +aaaa
----------------------------------------------
2nd git commit | aaaa
| +bbbb
----------------------------------------------
4th git commit | aaaa
| bbbb
| +cccc
| +dddd
----------------------------------------------
5th git commit | aaaa
| bbbb
| cccc
| dddd
| +eeee
Eh bien, c'était le genre de lecture que j'espérais avoir trouvé, pour commencer à chercher comment git rebase
fonctionne en termes de suppression de commits / révisions; alors j'espère que ça pourrait aider les autres aussi ...