Как удалить выбранные записи в журнале коммитов из репозитория Git, сохранив их изменения? - PullRequest
235 голосов
/ 30 января 2009

Я хотел бы удалить выбранные записи журнала фиксации из линейного дерева фиксации, чтобы записи не отображались в журнале фиксации.

Мое дерево коммитов выглядит примерно так:

R--A--B--C--D--E--HEAD

Я хотел бы удалить записи B и C, чтобы они не отображались в журнале фиксации, но изменения от A до D должны быть сохранены. Может быть, введя один коммит, чтобы B и C стали BC, а дерево выглядит так.

R--A--BC--D--E--HEAD

Или, в идеале, сразу после A приходит D. D 'представляет изменения от A к B, B к C и C к D.

R--A--D'--E--HEAD

Возможно ли это? если да, то как?

Это довольно новый проект, поэтому у него нет веток на данный момент, поэтому также нет слияний.

Ответы [ 9 ]

267 голосов
/ 30 января 2009

git-rebase (1) делает именно это.

$ git rebase -i HEAD~5

git awsome-ness [git rebase --interactive] содержит пример.

  1. Не использовать git-rebase для публичных (удаленных) коммитов.
  2. Убедитесь, что ваш рабочий каталог чист (commit или stash ваши текущие изменения).
  3. Запустите приведенную выше команду. Он запускает ваш $EDITOR.
  4. Заменить pick перед C и D на squash. Он объединит C и D в B. Если вы хотите удалить коммит, просто удалите его строку.

Если вы потерялись, введите:

$ git rebase --abort  
72 голосов
/ 30 января 2009
# detach head and move to D commit
git checkout <SHA1-for-D>

# move HEAD to A, but leave the index and working tree as for D
git reset --soft <SHA1-for-A>

# Redo the D commit re-using the commit message, but now on top of A
git commit -C <SHA1-for-D>

# Re-apply everything from the old D onwards onto this new place 
git rebase --onto HEAD <SHA1-for-D> master
39 голосов
/ 14 сентября 2010

Вот способ удалить конкретный идентификатор фиксации, зная только идентификатор фиксации, который вы хотели бы удалить.

git rebase --onto commit-id^ commit-id

Обратите внимание, что это фактически удаляет изменение, внесенное коммитом.

19 голосов
/ 27 марта 2010

Подробнее о ответе Ф. Ф. Себастьяна:

Вы можете использовать git-rebase, чтобы легко вносить любые изменения в историю коммитов.

После запуска git rebase --interactive в вашем $ EDITOR вы получите следующее:

pick 366eca1 This has a huge file
pick d975b30 delete foo
pick 121802a delete bar
# Rebase 57d0b28..121802a onto 57d0b28
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit

Вы можете перемещать строки, чтобы изменить порядок коммитов, и удалять строки, чтобы удалить этот коммит. Или вы можете добавить команду для объединения (сжатия) двух коммитов в один коммит (предыдущий коммит - вышеупомянутый коммит), редактировать коммиты (что было изменено) или перефразировать сообщения коммитов.

Я думаю, что выбор просто означает, что вы хотите оставить этот коммит один.

(Пример из здесь )

14 голосов
/ 09 мая 2009

Вы можете неинтерактивно удалить B и C в вашем примере с помощью:

git rebase --onto HEAD~5 HEAD~3 HEAD

или символически

git rebase --onto A C HEAD

Обратите внимание, что изменения в B и C не будут в D; они будут ушли .

3 голосов
/ 17 апреля 2015

Еще один способ,

git rebase -i ad0389efc1a79b1f9c4dd6061dca6edc1d5bb78a (C's hash)
and
git push origin master  -f

выберите хеш, который вы хотите использовать в качестве базы, и приведенная выше команда должна сделать его интерактивным, чтобы вы могли сжать все сообщения top (вам нужно оставить самое старое)

2 голосов
/ 18 апреля 2013

Я считаю, что этот процесс гораздо безопаснее и проще для понимания, создав другую ветку из SHA1 в A и выбрав нужные изменения, чтобы я мог убедиться, что я удовлетворен тем, как выглядит эта новая ветка. После этого легко удалить старую ветку и переименовать новую.

git checkout <SHA1 of A>
git log #verify looks good
git checkout -b rework
git cherry-pick <SHA1 of D>
....
git log #verify looks good
git branch -D <oldbranch>
git branch -m rework <oldbranch>
0 голосов
/ 05 октября 2017

Просто собрал ответы всех людей: (я новичок в git plz, использую его только для справки)

git rebase для удаления любых коммитов

git log

-first check from which commit you want to rebase

git rebase -i HEAD ~ 1

-Here i want to rebase on the second last commit- commit count starts from '1')
-this will open the command line editor (called vim editor i guess)

Тогда экран будет выглядеть примерно так:

pick 0c2236d Добавлена ​​новая строка.

Перебазировать 2a1cd65..0c2236d на 2a1cd65 (1 команда)

#

Команда:

p, pick = использовать commit

r, reword = использовать фиксацию, но редактировать сообщение фиксации

e, edit = использовать коммит, но остановиться для внесения изменений

s, squash = использовать коммит, но слиться с предыдущим коммитом

f, fixup = как "squash", но отбросить сообщение журнала этого коммита

x, exec = команда запуска (остаток строки) с использованием оболочки

d, drop = удалить коммит

#

Эти строки можно переупорядочить; они выполняются сверху вниз.

#

Если вы удалите строку, ЭТО КОММИТ БУДЕТ ПОТЕРЯН.

#

Однако, если вы удалите все, ребаз будет прерван.

#

Обратите внимание, что пустые коммиты закомментированы ~ ~

~
~
~
~
~
~
~
~
~

Здесь измените первую строку в соответствии с вашими потребностями (используя команды, перечисленные выше, то есть «drop» для удаления коммита и т. Д.) После завершения редактирования нажмите «: x» для сохранения и выхода из редактора (только для редактора vim)

А потом

git push

Если проблема с отображением проблемы, вам нужно принудительно отправить изменения на удаленный компьютер (ЕГО ОЧЕНЬ КРИТИЧЕСКИ: не нажимайте принудительно, если вы работаете в команде)

git push -f origin

0 голосов
/ 03 февраля 2009

Для этого вы можете использовать git cherry-pick. 'cherry-pick' применит коммит на ветку, на которой вы сейчас находитесь.

тогда делай

git rebase --hard <SHA1 of A>

, затем примените коммиты D и E.

git cherry-pick <SHA1 of D>
git cherry-pick <SHA1 of E>

Это пропустит коммит B и C. Сказав, что может быть невозможно применить коммит D к ветви без B, так что YMMV.

...