Nach den anderen Antworten hier war ich etwas verwirrt darüber, wie git rebase -i
verwendet werden, um einen Commit zu entfernen. Ich hoffe, es ist in Ordnung, wenn ich hier meinen Testfall aufschreibe (der dem des OP sehr ähnlich ist).
Hier ist ein bash
Skript, das Sie einfügen können, um ein Test-Repository in der /tmp
Ordner:
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"
An diesem Punkt haben wir eine file.txt
mit diesen Inhalten:
aaaa
bbbb
cccc
dddd
eeee
Zu diesem Zeitpunkt ist HEAD beim 5. Commit, HEAD~1 wäre der 4. und HEAD~4 wäre der 1. Commit (HEAD~5 würde also nicht existieren). Sagen wir, wir wollen den 3. Commit entfernen - wir können diesen Befehl in der myrepo_git
Verzeichnis:
git rebase -i HEAD~4
( Beachten Sie, dass git rebase -i HEAD~5
ergibt "fatal: Benötigte eine einzelne Revision; ungültiger Upstream HEAD~5". ) Ein Texteditor (siehe Screenshot in @Dennis' Antwort ) wird mit diesem Inhalt geöffnet:
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
# ...
Wir erhalten also alle Übertragungen seit (aber ohne ) unser gewünschtes HEAD~4. Löschen Sie die Zeile pick 448c212 3rd git commit
und speichern Sie die Datei; Sie erhalten dann folgende Antwort von 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
Öffnen Sie an dieser Stelle myrepo_git/ folder/file.txt
in einem Texteditor; Sie werden sehen, dass sie geändert wurde:
aaaa
bbbb
<<<<<<< HEAD
=======
cccc
dddd
>>>>>>> b50213c... 4th git commit
Im Grunde genommen, git
sieht, dass, als HEAD zur 2. Übergabe kam, es Inhalt von aaaa
+ bbbb
; und dann hat es einen Fleck mit zusätzlichen cccc
+ dddd
die es nicht an den vorhandenen Inhalt anhängen kann.
Also hier git
kann nicht für Sie entscheiden - es ist Sie der eine Entscheidung treffen muss: Wenn Sie die 3. Übergabe entfernen, behalten Sie entweder die durch sie eingeführten Änderungen (hier die Zeile cccc
) - oder eben nicht. Wenn nicht, entfernen Sie einfach die zusätzlichen Zeilen - einschließlich der cccc
- in folder/file.txt
mit einem Texteditor, so dass es wie folgt aussieht:
aaaa
bbbb
dddd
... und dann speichern folder/file.txt
. Jetzt können Sie die folgenden Befehle in myrepo_git
Verzeichnis:
$ 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 - um also zu markieren, dass wir den Konflikt gelöst haben, müssen wir muss git add
die folder/file.txt
, bevor sie git rebase --continue
:
$ git add folder/file.txt
$ git rebase --continue
Hier öffnet sich wieder ein Texteditor und zeigt die Zeile 4th git commit
- hier haben wir die Möglichkeit, die Commit-Nachricht zu ändern (die in diesem Fall sinnvollerweise in 4th (and removed 3rd) commit
oder ähnlich). Angenommen, Sie wollen das nicht - dann beenden Sie einfach den Texteditor, ohne zu speichern; sobald Sie das tun, erhalten Sie:
$ git rebase --continue
[detached HEAD b8275fc] 4th git commit
1 file changed, 1 insertion(+)
Successfully rebased and updated refs/heads/master.
An diesem Punkt haben Sie nun einen Verlauf wie diesen (den Sie auch mit z.B. gitk .
oder andere Tools) der Inhalte von folder/file.txt
(mit offenbar unveränderten Zeitstempeln der ursprünglichen Übertragungen):
1st git commit | +aaaa
----------------------------------------------
2nd git commit | aaaa
| +bbbb
----------------------------------------------
4th git commit | aaaa
| bbbb
| +dddd
----------------------------------------------
5th git commit | aaaa
| bbbb
| dddd
| +eeee
Und wenn wir vorher beschlossen haben, die Linie beizubehalten cccc
(der Inhalt des 3. Git-Commits, den wir entfernt haben), hätten wir das:
1st git commit | +aaaa
----------------------------------------------
2nd git commit | aaaa
| +bbbb
----------------------------------------------
4th git commit | aaaa
| bbbb
| +cccc
| +dddd
----------------------------------------------
5th git commit | aaaa
| bbbb
| cccc
| dddd
| +eeee
Nun, das war die Art von Lektüre, die ich zu finden gehofft hatte, um zu verstehen, wie git rebase
funktioniert in Bezug auf das Löschen von Commits/Revisionen; ich hoffe, es hilft auch anderen...