Из других ответов, приведенных здесь, я был немного озадачен тем, как git rebase -i
можно использовать удаление коммита, поэтому я надеюсь, что здесь можно записать мой тестовый пример (очень похожий на OP).
Вот bash
скрипт, который вы можете вставить, чтобы создать тестовое хранилище в /tmp
папке:
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"
На данный момент, у нас есть file.txt
с этим содержанием:
aaaa
bbbb
cccc
dddd
eeee
На этом этапе HEAD находится на 5-м коммите, HEAD ~ 1 будет 4-м - и HEAD ~ 4 будет 1-м коммитом (поэтому HEAD ~ 5 не будет существовать). Допустим, мы хотим удалить 3-й коммит - мы можем выполнить эту команду в myrepo_git
каталоге:
git rebase -i HEAD~4
( Обратите внимание, что в git rebase -i HEAD~5
результате получается «fatal: необходима одна ревизия; недопустимый верхний колонтитул ~ 5». ) Откроется текстовый редактор (см. Скриншот в ответе @Dennis ) со следующим содержимым:
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
# ...
Таким образом, мы получаем все коммиты, так как (но не включая ) наш запрошенный HEAD ~ 4. Удалить строку pick 448c212 3rd git commit
и сохранить файл; Вы получите этот ответ от 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
В этот момент откройте myrepo_git / folder/file.txt
в текстовом редакторе; вы увидите, что он был изменен:
aaaa
bbbb
<<<<<<< HEAD
=======
cccc
dddd
>>>>>>> b50213c... 4th git commit
По сути, git
видит, что когда HEAD получил 2-й коммит, было содержимое aaaa
+ bbbb
; и затем у него есть патч cccc
+, dddd
который он не знает, как добавить к существующему контенту.
Так что здесь git
не может решить за вас - это вы должны принять решение: удаляя 3-й коммит, вы либо сохраняете внесенные им изменения (здесь, строка cccc
) - либо нет. Если вы этого не сделаете, просто удалите лишние строки - в том числе cccc
- в folder/file.txt
текстовом редакторе, чтобы он выглядел так:
aaaa
bbbb
dddd
... а затем сохранить folder/file.txt
. Теперь вы можете выполнить следующие команды в myrepo_git
каталоге:
$ 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
Ах - так, чтобы отметить , что мы решили конфликт, мы должны , прежде чем делать :git add
folder/file.txt
git rebase --continue
$ git add folder/file.txt
$ git rebase --continue
Здесь снова открывается текстовый редактор, показывающий строку 4th git commit
- здесь у нас есть шанс изменить сообщение коммита (которое в этом случае могло бы быть существенно изменено на 4th (and removed 3rd) commit
или подобное). Допустим, вы не хотите - просто выйдите из текстового редактора без сохранения; как только вы это сделаете, вы получите:
$ git rebase --continue
[detached HEAD b8275fc] 4th git commit
1 file changed, 1 insertion(+)
Successfully rebased and updated refs/heads/master.
На данный момент, теперь у вас есть такая история (которую вы также можете проверить, скажем, с помощью gitk .
других инструментов), например, содержимого folder/file.txt
(с, по-видимому, неизменными временными метками оригинальных коммитов):
1st git commit | +aaaa
----------------------------------------------
2nd git commit | aaaa
| +bbbb
----------------------------------------------
4th git commit | aaaa
| bbbb
| +dddd
----------------------------------------------
5th git commit | aaaa
| bbbb
| dddd
| +eeee
И если ранее мы решили сохранить строку cccc
(содержимое 3-го git коммита, который мы удалили), мы бы имели:
1st git commit | +aaaa
----------------------------------------------
2nd git commit | aaaa
| +bbbb
----------------------------------------------
4th git commit | aaaa
| bbbb
| +cccc
| +dddd
----------------------------------------------
5th git commit | aaaa
| bbbb
| cccc
| dddd
| +eeee
Ну, это было то чтение, которое я надеялся найти, чтобы начать понимать, как git rebase
работает с точки зрения удаления коммитов / ревизий; так что надеюсь, что это может помочь и другим ...