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

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

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

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

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

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

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

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

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

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

Ответ 1

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

$ git rebase -i HEAD~5

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

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

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

$ git rebase --abort  

Ответ 2

# 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

Ответ 3

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

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

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

Ответ 4

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

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

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

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

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

Ответ 5

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

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

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

git rebase --onto A C HEAD

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

Ответ 6

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

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

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

Ответ 7

Я считаю этот процесс более безопасным и понятным, создавая еще одну ветку из SHA1 of 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>

Ответ 8

Просто собрал ответы всех людей: (m new to 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 Добавлена ​​новая строка.

Rebase 2a1cd65..0c2236d на 2a1cd65 (команда 1)

#

Команды

p, pick = use commit

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

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

s, squash = использовать commit, но meld в предыдущий commit

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

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

d, drop = удалить commit

#

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

#

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

#

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

#

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

~
~
~
~
~
~
~
~
~

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

И затем

git нажмите

Если его проблема с отображением, вам необходимо принудительно надавить изменения на удаленный (ITS VERY CRITICAL: не нажимайте push, если вы работаете в команде)

git push -f origin

Ответ 9

Вы можете использовать git cherry-pick для этого. "cherry-pick" теперь применит фиксацию на ветку.

то do

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.