Мені потрібно спливати та видаляти “середній” коміт у моїй головній гілці. Як я можу це зробити?


94

Наприклад, у такій головній гілці мені потрібно смітити лише коміт af5c7bf16e6f04321f966b4231371b21475bc4da, який є другим завдяки попередньому перебазуванню:

commit 60b413512e616997c8b929012cf9ca56bf5c9113
Author: Luca G. Soave <luca.soave@gmail.com>
Date:   Tue Apr 12 23:50:15 2011 +0200

    add generic config/initializers/omniauth.example.rb

commit af5c7bf16e6f04321f966b4231371b21475bc4da
Author: Luca G. Soave <luca.soave@gmail.com>
Date:   Fri Apr 22 00:15:50 2011 +0200

    show github user info if logged

commit e6523efada4d75084e81971c4dc2aec621d45530
Author: Luca G. Soave <luca.soave@gmail.com>
Date:   Fri Apr 22 17:20:48 2011 +0200

    add multiple .container at blueprint layout

commit 414ceffc40ea4ac36ca68e6dd0a9ee97e73dee22
Author: Luca G. Soave <luca.soave@gmail.com>
Date:   Thu Apr 21 19:55:57 2011 +0200

    add %h1 Fantastic Logo + .right for 'Sign in with Github'

Мені потрібно погодувати

  • перший коміт 60b413512e616997c8b929012cf9ca56bf5c9113,
  • третій коміт e6523efada4d75084e81971c4dc2aec621d45530 та
  • останнє комітування 414ceffc40ea4ac36ca68e6dd0a9ee97e73dee22

"викидання" лише Другого коміту af5c7bf16e6f04321f966b4231371b21475bc4da

Як я можу це зробити? Заздалегідь дякую, Лука

Відповіді:


98

Перебазувати або відновити - це варіанти. Rebase фактично видалить коміт з історії, так що буде виглядати так, ніби другий коміт ніколи не існував. Це буде проблемою, якщо ви відсунули головну гілку на будь-які інші репозиторії. Якщо ви спробуєте натиснути після перебазування даних у цьому випадку, git видасть вам помилку відхилення без швидкого перемотування вперед .

Повернути - це правильне рішення, коли гілка була надана спільно з іншими репозиторіями. git revert af5c7bf16зробить новий коміт, який просто скасовує зміни, внесені af5c7bf16. Таким чином історія не переписується, ви ведете чіткий запис про помилку, а інші репозиторії приймуть натиск.

Ось хороший спосіб стерти: git rebase -i <commit>^ це приведе вас до коміту безпосередньо перед тим, який ви хочете видалити. Інтерактивний редактор покаже вам список усіх комітів назад до цього моменту. Ви можете вибрати, стиснути тощо. У цьому випадку видаліть рядок коміту, який ви хочете стерти, і збережіть файл. Rebase закінчить свою роботу.


2
Якщо я оберу Rebase, який правильний коміт перебазувати? Мені потрібно кинути лише секунду ...
Лука Г. Соаве

@ BBJ3 Див. Відповідь mipadi.
Prajwal Dhatwalia

32

Якщо перебазування є варіантом, ви можете перебазувати і просто скинути його:

$ git rebase -i 414ceffc^

Якщо перебазувати не можна, ви можете просто скасувати його:

$ git revert af5c7bf16

якщо я отримав для "git rebase 414ceffc", який є старшим четвертим комітом, хіба я втрачу також третій e6523 і перший 60b41?
Luca G. Soave

3
@Luca G. Soave: Ви "втрачаєте" коміт, лише якщо спеціально наказали git rebaseйого відмовитись (запустивши rebaseв інтерактивному режимі та видаливши його запис).
mipadi

Дякую, mipadi, я віддаю свій голос JCotton по суті за широке пояснення, навіть якщо ви двоє сказали те саме ... ще раз спасибі.
Luca G. Soave

29

Незважаючи на всі заслуги оригінальних відповідей, отриманих тут, я не зовсім знайшов їх, щоб задовільно відповісти на питання. Якщо ви потрапили в ситуацію, коли вам потрібно видалити коміт або колекцію комітів із середини історії, я пропоную ось що:

  • Створіть нову гілку з голови тієї, що містить усі коміти, і перейдіть до неї.
  • Поверніть нову гілку назад до точки, з якої ви хочете запустити нову базу.
  • Потім, (ось ключовий момент) вишня вибирає наступні коміти, які ви насправді хочете застосувати після цього, з початкової гілки до нової та пропускаєте коміти, які ви більше не хочете (тобто ті, які ви видаляєте).
  • За бажанням перейменуйте вихідну гілку на щось, що вказує на її старий код, а потім перейменуйте нову гілку на те, що називалася оригінальною.
  • Нарешті, натисніть зміни на віддаленому репо (якщо використовується). Ймовірно, вам доведеться застосувати «примусовий поштовх». Якщо у ваших співавторів виникають проблеми з витяганням версій, їм буде найпростіше просто клонувати репо знову з віддаленого джерела. Так чи інакше, ви, швидше за все, захочете поговорити з ними, якщо все одно вириваєте коміти з середини вашої історії!

Ось інформація про збір вишні: що означає комітування збору вишні за допомогою git?

Ось деякі з цього з Tortoise Git (як я щойно зробив). Безумовно, простіше використовувати утиліту gui для таких видів операцій! Вишневий пиріг за допомогою TortoiseGit


6
Це мала бути головна відповідь!
MadOgre

Хороший спосіб використовувати вишневий пікінг, це рішення навіть краще, коли ви хочете "пропустити" більше одного коміту.
Джонні Віллер,

Насправді не звертаючись до вихідного питання. Хоча запропоноване рішення працює, воно набагато більш трудомістке / незручне, і IMO не приносить ніякої користі. Якщо гілка вже була висунута (і використовується в дикій природі), стратегія повернення - це, мабуть, відповідь. Якщо ні, інтерактивне перебазування та усунення порушуючого коміту - ось що я б використав. Якщо його натиснули, але ми знаємо, що ним ніхто не користується, ви все одно можете піти за допомогою перебазування з подальшим силовим натисканням.
raduw
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.