Як видалити вибрані записи журналу комісій із сховища Git, зберігаючи їх зміни?


241

Я хотів би видалити вибрані записи журналу фіксування з лінійного дерева фіксації, щоб записи не відображалися в журналі фіксації.

Моє дерево фіксації виглядає приблизно так:

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

Чи можливо це? якщо так, то як?

Це досить новий проект, тому зараз немає галузей, отже, немає і об'єднань.


@ xk0der: "здійснює" - це правильний термін. rebaseможе видалити старі / створити нові коміти. Я не знаю, що означає "робити записи журналу".
jfs

@JFSebastian Я не бачу проблеми з "журналом фіксації" - Журнал усіх комітетів. І я хотів видалити кілька записів із журналу - зберігаючи фактичні зміни (коміти).
xk0der

@ xk0der: git- файли можуть бути адресовані вмістом, тобто, якщо ви щось змінили в коміті, наприклад, повідомлення журналу; ви створюєте новий комітет. Ви можете прочитати вчинення git без git і переконатися в цьому самі .
jfs

@JFSebastian - Дякую за посилання - я це знаю - Але чи справді ця технічність змінює проблему, з якою я стикався, і як я її вирішував? Я думаю, що не. Врешті-решт: я хотів видалити "повідомлення журналу фіксації" - не знімаючи "зміни змін". Будь ласка, перечитайте моє запитання - особливо другий абзац. Щоб додати більше, git logпоказує "журнал фіксації" git-scm.com/docs/git-log . І я хотів позбутися двох записів із цього журналу - не зміни.
xk0der

Відповіді:


273

git-rebase (1) робить саме це.

$ git rebase -i HEAD~5

git awsome-ness [git rebase - інтерактив] містить приклад.

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

Якщо ви загубилися, введіть:

$ git rebase --abort  

Дякуємо за швидку відповідь. Тож я повинен перевірити A і зробити ребауз, щось подібне git rebase -i D [A]?
xk0der


3
Як ми можемо це зробити на віддалених репостах?
Eray

6
@Eray: лише push -fваші зміни. Не робіть цього, якщо ви не працюєте один.
jfs

2
@ ripper234: Я виправив посилання на git-rebaseінструкцію з посібника та зворотну машину для публікації в блозі.
jfs

75
# 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

Це теж працює і допомогло мені зрозуміти, що таке м'яке скидання. Зрозуміло, відповідь "верхній" є правильною і коротшою, але дякую і за цю відповідь.
cgp

41

Ось спосіб видалити певний ідентифікатор фіксації, знаючи лише ідентифікатор фіксації, який ви хочете видалити.

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

Зауважте, що це фактично видаляє зміни, внесені комітом.


7
Додаткова HEAD у цій команді призведе до того, що ребауз закінчиться "відокремленою HEAD", що небажано. Його слід опустити.
Морозний

3
Це скасовує зміни, внесені моїми ідентифікаторами комісій, ОП хоче зберегти зміни, просто розчавити коміти.
CB Bailey

1
-1 тому, що він не робить того, про що попросив ОП (скоріше знищує те, що він явно хотів зберегти).
Еміль Стірке

1
Хоча це не робить те, про що просив ОП, це було саме те, що мені потрібно, тому +1 для корисної відповіді.
Едвінс

20

Щоб розширити відповідь Дж. Ф. Себастьяна:

Ви можете використовувати 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

Ви можете неінтерактивно видалити B і C у своєму прикладі за допомогою:

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

або символічно,

git rebase --onto A C HEAD

Зауважте, що зміни B і C не будуть в D; вони будуть пішли .


Дивіться тут для отримання додаткової інформації: sethrobertson.github.io/GitFixUm/fixup.html#remove_deep
Макс

3

Ще один спосіб,

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

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


2

Я вважаю цей процес набагато безпечнішим і простішим для розуміння, створивши іншу гілку з 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>

якщо ви це зробите, ви також втратите комісію Е, чи не так? Як я зрозумів, ви видаляєте майстер і перейменовуєте переробку як головну (вважаючи, що потік ABCDE є головним відділенням).
Ренан Бандейра

1

Щойно зібрали відповіді всіх людей: (m new to git plz use it only for reference)

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)

Тоді екран буде виглядати приблизно так:

виберіть 0c2236d Додано новий рядок.

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

#

Команди:

p, забрати = використовувати накласти

r, reword = використовувати присвоєння, але відредагуйте повідомлення про фіксацію

e, редагувати = використовувати команду, але зупинятись на внесенні змін

s, сквош = використовувати фіксацію, але увімкнути попередній коміт

f, fixup = як "сквош", але відмовтеся від журналу цього журналу

x, exec = запустити команду (решта рядка) за допомогою оболонки

d, drop = видалити фіксацію

#

Ці рядки можна переупорядкувати; вони виконуються зверху вниз.

#

Якщо ви видалите тут рядок, ЩО ЗВ'ЯЗКОВО БУДЕ ВЗАЄМО

#

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

#

Зауважте, що порожні комітети коментуються ~ ~

~
~
~
~
~
~
~
~
~

Тут змініть перший рядок відповідно до ваших потреб (використовуючи перераховані вище команди, тобто "drop" для видалення фіксації тощо). Після завершення редагування натисніть ": x", щоб зберегти та вийти з редактора (це лише для редактора vim)

І потім

git push

Якщо проблема виявляється, вам потрібно насильно натиснути зміни на віддалений (ЇЇ ДУЖЕ КРИТИЧНО: не натискайте, якщо ви працюєте в команді)

git push -f походження


-1

Для цього можна використовувати git 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.


2
ОП хоче поєднувати B, C, D, не змінюючи їх зміни.
jfs

3
Я думаю, ти мав на увазі reset --hard, а не rebase --hard(чого не існує)
Маурісіо Шеффер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.