Как удалить выбранные записи журнала фиксации из репозитория Git, сохранив их изменения?

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

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

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

Это возможно? если да, то как?

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


person xk0der    schedule 30.01.2009    source источник
comment
@ xk0der: здесь правильный термин "коммиты". rebase может удалять старые / создавать новые коммиты. Я не знаю, что означают записи журнала фиксации.   -  person jfs    schedule 11.08.2012
comment
@ J.F.Sebastian Я не вижу проблемы с журналом фиксации - журнал всех фиксаций. И я хотел удалить несколько записей из журнала, сохранив при этом фактические изменения (коммиты).   -  person xk0der    schedule 12.08.2012
comment
@ xk0der: коммиты git адресуются по содержимому, т. е. если вы измените что-нибудь в коммите, например, его сообщение журнала; вы создаете новую фиксацию. Вы можете прочитать коммит git без git и убедиться в этом.   -  person jfs    schedule 12.08.2012
comment
@ J.F.Sebastian - Спасибо за ссылки - я это знаю - Но действительно ли эта техническая сторона меняет проблему, с которой я столкнулся, и то, как я ее формулирую? Думаю, нет. В конце: я хотел удалить сообщения журнала фиксации - без удаления изменений фиксации - пожалуйста, перечитайте мой вопрос - особенно второй абзац. Чтобы добавить больше, git log показывает журнал фиксации git-scm.com/docs/git-log. И я хотел избавиться от двух записей из этого журнала, а не от изменений.   -  person xk0der    schedule 12.08.2012


Ответы (9)


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  
person jfs    schedule 30.01.2009
comment
Спасибо за быстрый ответ. Так что я проверяю A и делаю перебаз, что-то вроде git rebase -i D [A]? - person xk0der; 30.01.2009
comment
Как это сделать в удаленных репозиториях? - person Eray; 18.11.2011
comment
@Eray: просто push -f свои изменения. Не делайте этого, если вы работаете не один. - person jfs; 18.11.2011
comment
@ J.F.Sebastian, спасибо, в этом есть смысл. Если мы небольшая команда, можем ли мы остановить мир: все нажимают, перебазируют, все удаляют локально и клонируют? Это сработает? - person nalply; 06.12.2011
comment
Обновлена ​​ссылка на использование машины обратного пути. - person ripper234; 31.12.2011
comment
@ ripper234: Я исправил ссылки на руководство git-rebase точки и машину возврата для сообщения в блоге. - person jfs; 28.02.2012
comment
‹Funfact› git rebase -i HEAD ~ 5, за которым следует: q (из vim), приводит к удалению --no-ff Слияние из ... коммитов. ‹/Funfact› - person billrichards; 04.04.2014
comment
@~5 - это ярлык для HEAD~5 - person Filip Bartuzi; 26.08.2015
comment
@ J.F.Sebastian Я искренне хочу удалить фиксацию и все ее данные / изменения, но когда я удаляю строку фиксации, которую хочу удалить, и выхожу из редактора $ EDITOR с :wq все, что я получаю, это сообщение с надписью could not execute editor. И когда я проверяю git log, коммит, который я хотел удалить, все еще там. Что означает эта ошибка? - person Maggie S.; 05.03.2016
comment
@MaggieB .: эти вопросы: как удалить строку в моем $ EDITOR, как сохранить изменения на диск, как выйти из редактора, как указать другой редактор, с которым вы более знакомы, следует задавать отдельно. Ответы зависят от вашего $EDITOR (не забудьте указать, что это такое). См. Как задать вопрос - person jfs; 05.03.2016
comment
Просто чтобы повторить то, что сказал @jfs, и добавить еще немного контекста, выполнение rebase перепишет журнал shas! Это важно отметить, потому что, если вы уже нажали, вам нужно принудительно перезаписать журнал восходящего потока. Проблема здесь, как уже упоминалось, кто-либо другой, работающий с этой веткой, теперь не может нажимать, так как происхождение изменилось. git push --force-with-lease - это одна вещь, на которую следует обратить внимание, но в целом НЕ НАЖИМАЙТЕ НАЖИМАЙТЕ, ЕСЛИ ВЫ НЕ РАБОТАЕТЕ ОДИН! - person seeafish; 05.06.2018

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

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

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

person rado    schedule 13.09.2010
comment
Дополнительный HEAD в этой команде приведет к тому, что перебазирование завершится с «отсоединенной HEAD», что нежелательно. Его следует опустить. - person Frosty; 27.05.2011
comment
Это отменяет изменения, внесенные моим идентификатором фиксации, OP хочет сохранить изменения, просто подавите коммиты. - person CB Bailey; 24.09.2011
comment
-1, потому что он не выполняет то, что попросил OP (скорее, он уничтожает то, что он явно хотел сохранить). - person Emil Styrke; 28.03.2013
comment
Хотя он не выполняет то, что просил OP, это было именно то, что мне нужно, так что +1 за полезный ответ. - person Edvins; 30.07.2019

Чтобы расширить ответ Дж.Ф. Себастьяна:

Вы можете использовать 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

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

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

(Пример взят здесь)

person Community    schedule 27.03.2010

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

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

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

git rebase --onto A C HEAD

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

person Head    schedule 09.05.2009
comment
Дополнительную информацию см. Здесь: sethrobertson.github.io/GitFixUm/fixup.html#remove_deep < / а> - person Max; 28.04.2017

Я считаю, что этот процесс намного безопаснее и проще для понимания, создав еще одну ветку из 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>
person Eric Woodruff    schedule 17.04.2013
comment
если вы сделаете это, вы потеряете и коммит E, не так ли? Как я понял, вы удаляете мастер и переименовываете переработку как мастер (учитывая, что поток ABCDE является основной веткой). - person Renan Bandeira; 14.09.2016

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

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

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

person resultsway    schedule 17.04.2015

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

git rebase, чтобы удалить любые коммиты

git журнал

-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 = использовать фиксацию

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

e, edit = использовать фиксацию, но не вносить поправки

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

f, fixup = как "squash", но удалить сообщение журнала этой фиксации

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

d, drop = удалить фиксацию

#

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

#

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

#

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

#

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

~
~
~
~
~
~
~
~
~

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

А потом

git push

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

git push -f origin

person Shrinath Kopare    schedule 05.10.2017

Для этого вы можете использовать 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.

person Rory    schedule 02.02.2009
comment
OP хочет объединить коммиты B, C, D, а не удалять их изменения. - person jfs; 04.09.2009
comment
Я думаю, вы имели в виду reset --hard, а не rebase --hard (которого не существует) - person Mauricio Scheffer; 10.02.2012

person    schedule
comment
Это тоже работает и помогло мне понять, что такое мягкий сброс. Конечно, верхний ответ тоже правильный и короче, но спасибо и за этот ответ. - person cgp; 26.04.2012