Як я можу "скасувати повернення" поверненого Git?


485

З огляду на зміну, яку було здійснено за допомогою commit, а потім було повернено за допомогою revert, який найкращий спосіб скасувати це відновлення?

В ідеалі це слід зробити з новим зобов’язанням, щоб не переписувати історію.



@phuclv коментар щодо можливого дублікату, тут вказується. Один повинен бути позначений оригіналом, а один повинен бути позначений як дублікат
Джон

@JohnDemetriou жодне запитання щодо кращого набору відповідей не повинно залишатися відкритим. Час тут не релевантний. Як слід поводитися з повторюваними запитаннями?
phuclv

Я не казав про час. Мені просто трапилось коментувати одне з двох щодо цього питання
Джон Деметріу

Відповіді:


385

Якщо ви ще не натиснули цю зміну, git reset --hard HEAD^

В іншому випадку повернення ревертування ідеально добре.

Інший спосіб - це git checkout HEAD^^ -- .і тоді git add -A && git commit.


8
Зауважте, що якщо ви хочете скасувати відновлення без негайного застосування оригінальних змін до головної гілки, ви можете (1) відновити початкову гілку, якщо її видалити, (2) натиснути "повернути" на гілку відновлення, як зазначив Адам, потім ( 3) натисніть "редагувати" у заголовку отриманого PR та змініть цільову гілку на вихідну гілку замість головного. Тепер ваша оригінальна гілка може бути знову об’єднана, щоб здійснити раніше повернені зміни.
pauljm

1
Зверніть увагу, що це видалить усі зміни в робочому дереві та індексі. Використовуйте git скриньку, щоб зберегти зміни, які ви не хочете втратити.
zpon

3
Яка перевага методу оформлення замовлення та оплати? Схоже, що в загальному випадку git cherry-pickабо, як альтернатива git revert, це найбільш прямі способи повернення реверсу.
Роберт Джек Уілл

5
Я думаю, було б корисно показати, як це робити Otherwise, reverting the revert is perfectly fine., а потім також пояснити, що git checkout HEAD^^ -- .робиться.
Тодд

3
Добрий пане, не використовуй git add -A... якщо ви не хочете додати кожен файл до контролю версій, що, швидше за все, не є тим, що ви хочете.
Кайтайн

473

git cherry-pick <original commit sha>
Зробить копію оригіналу зобов’язання, по суті повторно застосувавши зобов’язання

Повернення відновлення зробить те ж саме, з повідомленням messier commit:
git revert <commit sha of the revert>

Будь-який із цих способів дозволить вам git pushне перезаписувати історію, оскільки це створює нове зобов’язання після відновлення.
Вводячи команду sha, вам зазвичай потрібні лише перші 5 або 6 символів:
git cherry-pick 6bfabc


60
Це легко найелегантніше та найповніше рішення питання про ОП. Набагато краще, ніж прийнята відповідь з її припущеннями про те, що команда повернення знаходиться в ГОЛАДІ дерева дерев. Оп також спеціально попросив рішення, яке не переписує історію, тому складне рішення, запропоноване у прийнятій відповіді, просто неправильне.
Тимо

6
@Timo Щоб уточнити, прийнята відповідь містить рішення, яке я використав ("повернення повернення"), і було опубліковане протягом години мого запитання - ясна на 3 роки раніше, ніж ця відповідь. Значить, галочка.
JimmidyJoo

6
@JimmidyJoo Я знаю, що мені було 3 роки пізніше, я просто хотів, щоб люди, які приїхали сюди з пошуку в Google, побачили кращу відповідь
Стефан

2
@Stephan Так, але знову ж таки, щоб уточнити - це краща відповідь, а не той, який я використовував для вирішення своєї проблеми. Я просто коментував, чому галочка там, де вона є. Запитання до всіх: чи передбачає Конвенція про те, що я повинен "підтримувати" свої попередні запитання та повторно призначати галочки, коли надходять нові відповіді?
JimmidyJoo

3
@JimmidyJoo Я не маю поняття про конвенцію про так. Але я, як шукач google, дійсно вважаю за краще перевірити відповідь. І вдячний би будь-яким зусиллям зберегти свої минулі питання.
Paiman Roointan

28

Повторне виконання так само, як і будь-яке інше в git. Це означає, що ви можете повернути його, як у:

git revert 648d7d808bc1bca6dbf72d93bf3da7c65a9bd746

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

У нашій команді у нас є правило використовувати повернення до повернення комітетів, які були здійснені в головній галузі, насамперед, щоб зберегти історію в чистоті, щоб ви могли бачити, який виклик скасовує, що:

      7963f4b2a9d   Revert "Revert "OD-9033 parallel reporting configuration"
      "This reverts commit a0e5e86d3b66cf206ae98a9c989f649eeba7965f.
                    ...
     a0e5e86d3b6    Revert "OD-9055 paralel reporting configuration"
     This reverts commit 648d7d808bc1bca6dbf72d93bf3da7c65a9bd746.
                ...
     Merge pull request parallel_reporting_dbs to master* commit 
    '648d7d808bc1bca6dbf72d93bf3da7c65a9bd746'

Таким чином, ви можете простежити історію і розібратися з цілою історією, і навіть ті, хто не знає спадщини, могли б розробити це для себе. Тоді як, якщо ви збираєте вишні або обновлюєте речі, ця цінна інформація втрачається (якщо ви не включите її до коментаря).

Очевидно, якщо комісія повертається та повертається не раз, то це стає досить безладним.


14

Повернення відновлення виконає трюк

Наприклад,

Якщо abcdefваша фіксація і ghijklце зобов'язання, яке ви мали, коли ви скасували комісію abcdef, виконайте:

git revert ghijkl

Це відновить відновлення


4

Мені це виглядає дурно. Але я опинився в тій же ситуації, і я повернувся за скасовані зобов'язання. Я зробив кількість ревертів, тому мені довелося робити повернення для кожного "повернення".

Тепер моя історія подій трохи дивно виглядає.

дивна історія

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


4
Ви можете бути зацікавлені в відповідях на інший моє запитання: stackoverflow.com/questions/10415565 / ...
JimmidyJoo

2
Ви можете уникати автоматичної фіксації та вибирати повідомлення про фіксацію, використовуючи прапор --no-commit при поверненні назад, а потім виконувати відповідне повідомлення
David Barda

Також ви можете вказати кілька ідентифікаторів комісій при використанні відновлення git (я думаю, вони повинні бути в потрібному порядку).
Алекс Габі

Чи можу я це зробити на робочому столі github?
Гійом Ф.

4

Ось як я це зробив:
якщо гілка my_branchnameбула включена в об'єднання, яке було повернене. І я хотів скасувати ревертування my_branchname:

Я спочатку роблю git checkout -b my_new_branchnameз my_branchname.
Тоді я роблю, git reset --soft $COMMIT_HASHде $COMMIT_HASHє хеш на виконання прямого зобов’язання перед першим фіксуванням my_branchname(див. git log)
Потім я роблю нове зобов’язання. git commit -m "Add back reverted changes"
Потім я натискаю нову гілку. git push origin new_branchname
Потім я робив запит на нову гілку.


Шлях, коли є занадто багато "вишеньки", щоб зробити. Я не розумію, чому ця відповідь має так мало відгуків
Fundhor

2

Або ви могли б git checkout -b <new-branch>і git cherry-pick <commit>раніше, щоб перейти до та git rebaseвідмовитись revert. надіслати запит на тягу, як і раніше.


1

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

З огляду на наступну вихідну ситуацію

 P---o---o---M---x---x---W---x
  \         /
   A---B---C----------------D---E   <-- fixed-up topic branch

(W - ваше первісне відновлення злиття M; D і E - це виправлення до вашої початково розбитої гілки функції / комісії)

Тепер ви можете просто повторити переходи від A до E, щоб жоден з них не «належав» до поверненого злиття:

$ git checkout E
$ git rebase --no-ff P

Нова копія вашої філії тепер може бути masterзнову об’єднана :

   A'---B'---C'------------D'---E'  <-- recreated topic branch
  /
 P---o---o---M---x---x---W---x
  \         /
   A---B---C----------------D---E

Гарна ідея та спасибі за посилання на doc. Ми, як правило, базуємося з master перед об'єднанням назад, але git потім, схоже, визнає, що A ', B', C 'такі ж, як і раніше, і в мене зараз D, E після W ( пастбін ). Пропозиції щодо вирішення цього питання?
Крістофер Баккейорд

0

Щоб повернути нестандартні та поетапні зміни, які були повернені після здійснення комісії:

git reset HEAD@{1}

Щоб відновити всі нестандартні видалення:

git ls-files -d | xargs git checkout --
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.