Скасування бази git


3178

Хто-небудь знає, як легко відмінити git rebase?

Єдиний спосіб, який спадає на думку, це перейти до цього вручну:

  • git checkout батьків прихильності до обох гілок
  • потім створіть звідти тимчасову гілку
  • вишні вибирайте всі вручну
  • замініть гілку, в якій я переобладнаний, створеною вручну гілкою

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

Однак мій підхід вважає мене як неоптимальний і схильний до помилок (скажімо, я щойно переосмислив 2 власні гілки).

Будь-які ідеї?

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


6
ТАКОЖ зауважте, що під час ребазування ви можете виключати коміти або зменшувати їх; ці зміни не підлягають поверненню без вказівника на вихідні вузли або просіювання через рефлог, тому вишні не працюватимуть.
ANeves

Відповіді:


4337

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

git reflog

і відновити поточну гілку до неї (із звичайними застереженнями щодо того, щоб бути абсолютно впевненим перед тим, як повторно налаштувати --hardпараметр).

Припустимо, старий фіксатор був HEAD@{5}у журналі ref:

git reset --hard HEAD@{5}

У Windows вам може знадобитися цитувати посилання:

git reset --hard "HEAD@{5}"

Ви можете перевірити історію старого голови кандидата, просто виконавши git log HEAD@{5}( Windows git log "HEAD@{5}" :).

Якщо ви не відключили кожну відгалуження гілки, ви повинні мати можливість просто зробити git reflog branchname@{1}так, як база даних від'єднує головку гілки перед повторним приєднанням до кінцевої заголовка. Я б ще раз перевірив це, хоча, як це нещодавно не підтвердив.

За замовчуванням всі відхилення активуються для неочищених сховищ:

[core]
    logAllRefUpdates = true

114
Git reflog є приголомшливим, просто пам’ятайте, що ви можете отримати краще форматований вихід git log -g(підказка від progit.org/book Скотта Чакона ).
karmi

60
@Zach: git rebase --abort( -iне має сенсу --abort) - це відмова від ребази, яка не була завершена - або через те, що виникли конфлікти, або через те, що вона була інтерактивною або обома; справа не в тому, щоб скасувати вдалу базу даних, про яку йдеться. Ви б або використовували, rebase --abortабо reset --hardзалежно від того, в якій ситуації ви опинилися. Вам не потрібно робити обох.
CB Bailey

311
На всякий випадок, зробіть резервну копію першого: git tag BACKUP. Ви можете повернутися до нього, якщо щось піде не так:git reset --hard BACKUP
kolypto

6
Якщо ви зробили багато завдань, HEAD @ {#}, який ви шукаєте, матиме перевагу на commit:відміну від rebase:. Звучить очевидно, але це мене трохи заплутало.
Warpling

4
Приєднання до партії після випадкового перезавантаження: D. Чи не вдалося б git reset --hard ORIG_HEADзробити трюк також відразу після випадкового перезавантаження?
quaylar

1485

Власне, база даних зберігає вашу вихідну точку, ORIG_HEADтому це, як правило, так просто, як:

git reset --hard ORIG_HEAD

Однак reset, rebaseі mergeвсе , крім вихідного HEADпокажчика в ORIG_HEADтак, якщо ви зробили будь - якого з цих команд з Rebase ви намагаєтеся скасувати , то ви повинні будете використовувати reflog.


34
У випадку, якщо ORIG_HEADце більше не корисно, ви також можете використовувати branchName@{n}синтаксис, де nзнаходиться n-те попереднє положення вказівника гілки. Так, наприклад, якщо ви перезавантажите featureAвідділення на свою masterгілку, але вам не подобається результат git reset --hard featureA@{1}перезавантаження , ви можете просто зробити, щоб скинути гілку туди, куди вона була раніше, ніж ви зробили ребазу. Докладніше про синтаксис гілки @ {n} можна прочитати в офіційних документах Git для редагування .

15
Це найпростіше. Слідкуйте за цим, git rebase --abortхоча.
Seph

1
@DaBlick для мене це спрацювало чудово після цілком успішної бази даних без конфліктів git 2.17.0.
dvlsg

4
І дозвольте мені доповнити: git reset --hard ORIG_HEADможна використовувати кілька разів, щоб повертатися знову і знову. Скажіть, якщо A --- rebase до --- B --- rebase до --- C, зараз я перебуваю в C, я можу повернутися до A, використовуючи два разиgit reset --hard ORIG_HEAD
CalvinChe

5
@Seph Чи можете ви пояснити, чому ви пропонуєте наступні дії git rebase --abort?
UpTheCreek

386

Відповідь Чарльза працює, але ви можете зробити це:

git rebase --abort

прибирати після reset.

В іншому випадку ви можете отримати повідомлення " Interactive rebase already started".


4
Це видалило частину "| ЗВ'ЯЗКУ" у моєму підказці. +1
Wouter Thielen

62
У цьому не було питання. Питання задає питання, як скасувати готову базу даних.
Arunav Sanyal

2
Повинен бути коментар до відповіді Чарльза, тому що він не відповідає на запитання про його
Мермель

Гм, я не повинен був цього робити.
Віктор

1
Єдиний, хто працював на мене!
Олександр Пікард

90

Перезавантаження гілки на об'єкт, що звисає, виконувати старий наконечник - це, звичайно, найкраще рішення, оскільки воно відновлює попередній стан, не витрачаючи жодних зусиль. Але якщо ви втратили ці комісії (f.ex. тому, що тим часом ви зібрали сміття зі свого сховища або це свіжий клон), ви завжди можете знову відновити гілку. Ключ до цього - --ontoперемикач.

Скажімо, у вас була тематично названа галузь теми topic, яку ви розгалужували, masterколи вістрям masterбуло 0deadbeefвиконано. У якийсь момент, перебуваючи на topicгілці, ти це зробив git rebase master. Тепер ви хочете скасувати це. Ось як:

git rebase --onto 0deadbeef master topic

Це займе всі комітети, на topicяких не ввімкнено, masterі повторити їх поверх 0deadbeef.

З цим --ontoви можете переставити свою історію в майже будь-яку форму .

Весело. :-)


3
Я думаю, що це найкращий варіант через свою гнучкість. Я розгалужував b1 off master, потім перекидав b1 на нову гілку b2, потім хотів повернути b1, щоб він знову був заснований на master. Я просто люблю git - спасибі!
ripper234

2
Тут найкращий варіант! Це зберегло всі зміни, які я маю на моїй поточній гілці, та видалила всі небажані!
Алісія Тан

Я б сказав, що за допомогою комбінації --ontoі -iви можете переставити історію в будь-яку форму. Використовуйте gitk (або gitx на mac), щоб побачити форми, які ви робите :-).
rjmunro

69

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

Тоді відновити так само просто git reset --hard BACKUP.


2
Я теж це роблю. Також корисно збирати різні BACKUP..HEAD, щоб переконатися, що ви змінили те, що хотіли.
Пол Кість

5
Раніше я це робив, але оскільки мені стало зручніше з рефлогом, я більше не відчуваю це необхідним. Рефлоґація по суті робить це від вашого імені кожного разу, коли ви міняєте HEAD.
Піт Ходжсон

4
Ну, я віддаю перевагу значущим іменам, адже пошук потрібного елемента в рефлозі іноді зовсім не цікавий.
Алекс Гонтахер

12
Вам фактично навіть не потрібно робити резервну гілку, ви можете просто використовувати branchName@{n}синтаксис, ось nп’яте попереднє положення вказівника гілки. Так, наприклад, якщо ви перезавантажите featureAвідділення на свою masterгілку, але вам не подобається результат git reset --hard featureA@{1}перезавантаження , ви можете просто зробити, щоб скинути гілку туди, куди вона була раніше, ніж ви зробили ребазу. Докладніше про branch@{n}синтаксис можна прочитати в офіційних документах Git для редагування .

2
Насправді, вам навіть не потрібно використовувати синтаксис, зазначений вище, згідно з відповіддю Пат Ноца , оригінал HEADгілки тимчасово зберігається в ORIG_HEAD. Але техніка використання мітки резервного відділення також працює, це лише кілька кроків.

68

У випадку, якщо ви відсунули свою філію у віддалений сховище (зазвичай це походження), а потім ви виконали успішне ребазування (без злиття) ( git rebase --abortдає "Без перезавантаження не працює "), ви можете легко скинути гілку за допомогою команди:

git reset - жорстке походження / {відділенняName}

Приклад:

$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is ahead of 'origin/{branchName}' by 135 commits.
  (use "git push" to publish your local commits)

nothing to commit, working directory clean

$ ~/work/projects/{ProjectName} $ git reset --hard origin/{branchName}
HEAD is now at 6df5719 "Commit message".

$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is up-to-date with 'origin/{branchName}.

nothing to commit, working directory clean

Це правильна відповідь для мене. Перезагрузка та фіксація перед повторною передачею мали той самий ідентифікатор фіксації, і повернення до HEAD {1} просто не відновить відновлення!
Білл Коціас

23

Використання reflog не працювало для мене.

Те, що працювало для мене, було схожим на описане тут . Відкрийте файл у .git / logs / refs з назвою гілки, яка була повторно базована, і знайдіть рядок, що містить "завершене оновлення", як-от:

5fce6b51 88552c8f Kris Leech <me@example.com> 1329744625 +0000  rebase finished: refs/heads/integrate onto 9e460878

Оформити другу комісію, вказану на рядку.

git checkout 88552c8f

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

git log
git checkout -b lost_changes


3
Whoa - із цього посилання: "Є один застереження: я втратив історію філії, але в цьому випадку це насправді не мало значення. Я просто радий, що знайшов свої зміни". ?
ruffin

16

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


11

Після рішення @Allan та @Zearin, я хотів би просто зробити коментар, але мені не вистачає репутації, тому я використав таку команду:

Замість того щоб робити git rebase -i --abort (зверніть увагу на -i ) я повинен був просто зробити git rebase --abort( без -i ).

Використання обох -iі --abortодночасно змушує Git показати мені список використання / варіантів.

Отже, мій попередній та поточний статус філії з цим рішенням:

matbhz@myPc /my/project/environment (branch-123|REBASE-i)
$ git rebase --abort

matbhz@myPc /my/project/environment (branch-123)
$

11

Якщо ви успішно відмовились від віддаленого відділення і не можете, git rebase --abortви все одно можете зробити кілька хитрощів, щоб зберегти свою роботу і не маєте вимушених натискань. Припустимо, ваша поточна галузь, яка була перезавантажена помилково, називається your-branchі відстежуєorigin/your-branch

  • git branch -m your-branch-rebased # перейменувати поточну гілку
  • git checkout origin/your-branch # замовлення до останнього стану, за яким відомо, що походить
  • git checkout -b your-branch
  • перевірити git log your-branch-rebased, порівняти git log your-branchта визначити комітети, яких немаєyour-branch
  • git cherry-pick COMMIT_HASH для кожного вчинення в your-branch-rebased
  • натисніть на зміни. Зауважте, що два локальні відділення пов’язані з remote/your-branchвами, і вам слід лише натиснутиyour-branch

4

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

git rebase -i HEAD~31

Інтерактивна база даних за останні 31 комітет (не зашкодить, якщо ви виберете занадто багато).

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


3

Для новачків / тих, хто занадто боїться зробити жорсткий перезавантаження, ви можете взяти на себе зобов’язання з рефлогу, а потім зберегти його як нову гілку.

git reflog

Знайдіть комісію безпосередньо перед тим, як розпочати випуск. Вам може знадобитися прокрутити далі вниз, щоб знайти його (натисніть Enter або PageDown). Зверніть увагу на номер HEAD та замініть 57:

git checkout HEAD@{57}

Перегляньте відділення / зобов’язання, якщо це добре виглядає, створіть нову гілку за допомогою цієї HEAD:

git checkout -b new_branch_name

2

Якщо ви знаходитесь у відділенні, ви можете використовувати:

git reset --hard @{1}

Існує не лише довідковий журнал для HEAD (отриманий git reflog), також є рефлоги для кожної гілки (отримані користувачем git reflog <branch>). Тож, якщо ви перебуваєте в masterтакому режимі, ви git reflog masterпобачите всі зміни до цієї гілки. Ви можете звернутися до того , що зміни з боку master@{1}, master@{2}і т.д.

git rebase зазвичай змінюється HEAD кілька разів, але поточна гілка буде оновлена ​​лише один раз.

@{1}це просто ярлик для поточної гілки , тож це дорівнює, master@{1}якщо ви перебуваєте в master.

git reset --hard ORIG_HEADне працюватиме, якщо ви використовувались git resetпід час інтерактивної роботи rebase.


1

Що я зазвичай роблю git reset #commit_hash

до останнього зобов’язання, де я думаю, що база даних не мала ефекту.

тоді git pull

Тепер ваша філія повинна відповідати точно так само, як і майстри, а переоформлені комісії не повинні знаходитись у ній.

Тепер ви можете просто вибрати вишні на цій гілці.


1

Я спробував усі пропозиції зі скиданням та відхиленням без успіху. Відновлення місцевої історії IntelliJ вирішило проблему втрачених файлів


Дякую! Ніколи раніше не використовував краєзнавчу історію, але це виявилося для мене найпростішим варіантом відновити якийсь випадково перезавантажений код. Дуже приємна, але дещо прихована особливість.
Magnus W

0

git reset - жорстке походження / {відділенняName}

- це правильне рішення для скидання всіх локальних змін, здійснених шляхом перезавантаження.


1
якщо ви важко скинетесь, origin/branchви можете втратити зміни між HEAD і цією точкою. Ви не хочете, щоб це взагалі.
bluesmonk

Це саме те, що я хотів у своїй справі. Тож наголос.
Mandar Vaze

-4

Якщо ви щось зіпсуєте в рамках git rebase, наприклад git rebase --abort, поки у вас є непослані файли, вони втратяться і git reflogне допоможуть. Це сталося зі мною, і вам тут потрібно буде подумати поза межами. Якщо вам пощастило, як я, і використовуєте IntelliJ Webstorm, ви можете right-click->local historyі можете повернутись до попереднього стану свого файлу / папок незалежно від помилок, які ви зробили з версією програмного забезпечення. Завжди добре проводити чергову несправність.


5
git rebase --abortаборти активного перебазування, що не скасувати в перебазування. Також використовувати одночасно два VCS - це погана ідея. Це приємна особливість програмного забезпечення Jetbrains, але ви не повинні використовувати обидва. Краще просто вивчити Git, особливо, відповідаючи на запитання щодо переповнення стека, які стосуються Git.
dudewad
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.