Подтвердить что ты не робот

Отменить Git Rebase

Я выполнил git rebase master на моей ветке и не понимал, что это не то, что я хотел, пока я не подтолкнул его к пульту. Это только я и еще один человек, работающий над проектом, поэтому я знаю, что они не вытащили последние изменения.

Чтение других вопросов в StackOverflow, он сказал, чтобы использовать git reflog, а затем git reset --hard [email protected]{n} до перезагрузки. Я сделал это, чтобы перейти к фиксации, которую я создал до перезагрузки, но он не восстановил вещи до того, как это было раньше.

Я пропустил шаг? Есть ли способ заставить другого человека подтолкнуть его репо, чтобы восстановить то, как они были?

Спасибо

4b9b3361

Ответ 1

Как Макото уже отметил, вам, вероятно, не стоит беспокоиться о том, чтобы отменить эту rebase: возможно, это то, что вы хотели. Тем не менее, не стесняйтесь читать, как отменить его.


Используйте reflog для ветки, так как ее будет легче читать. (HEAD reflog имеет одинаковую информацию, но в нем много чего больше, поэтому сложнее найти то, что вы ищете.)

Например, если бы я просто пересобил mybranch, я бы увидел:

$ git reflog mybranch
nnnnnnn [email protected]{0}: rebase finished: refs/heads/mybranch onto biguglysha1
ooooooo [email protected]{1}: commit: some sort of commit message
...

Таким образом, имя [email protected]{1} является синонимом (на данный момент) с ooooooo, старым сокращенным SHA-1. Каждый раз, когда вы что-то делаете с веткой (например, git reset), число внутри части @{...} будет меняться, а SHA-1 всегда навсегда, поэтому немного лучше использовать SHA-1 (полный или сокращенный ) для вырезания и вставки.

Если вы тогда:

$ git checkout mybranch # if needed

и

$ git reset --hard ooooooo  # or [email protected]{1}

у вас должен быть оригинал. Это связано с тем, что rebase просто копирует коммиты, а затем перемещает метку. После rebase, но до reset, граф фиксации выглядит примерно так: где A через C "ваши" совершает:

          A - B - C              <-- (only in reflog now)
        /
... - o - o - o - A' - B' - C'   <-- mybranch (after rebase)

и git reset просто 1 стирает текущую метку ветвления и вставляет ее в поставляемый SHA-1 (при необходимости сначала превращая имя reflog в SHA-1, если необходимо). Следовательно, после reset:

          A - B - C              <-- mybranch, plus older reflog
        /
... - o - o - o - A' - B' - C'   <-- (only in reflog now)

Обратите внимание, что теперь post- reset копии, сделанные с помощью перезаписи, являются "заброшенными", которые находятся только в записях reflog. Оригиналы, которые были оставлены, теперь снова заявлены в mybranch.

Способ думать об этом состоит в том, чтобы нарисовать граф фиксации (с новыми коммитами, указывающими назад на их родительские коммиты), затем нарисуйте метки ветки с длинными стрелками, указывающими на граф фиксации. График никогда не изменяет 2 кроме как добавлять новые коммиты, у которых есть новые и разные большие уродливые SHA-1 (именно поэтому я использую буквы типа A B и C вместо этого и привязать к таким добавкам, как A' для копий). SHA-1 гарантированно являются уникальными 3 и являются постоянными, но метки с длинными стрелками все время стираются и перенаправляются. (Если вы делаете это на доске, вы обычно должны использовать черный для графика фиксации и цвет или несколько цветов для ярлыков.)


1 Ну, git reset делает больше, чем просто переместить метку, если вы не добавите несколько флагов командной строки. По умолчанию он перемещает метку и сбрасывает индекс; с --hard, он перемещает метку и сбрасывает индекс и очищает ваше дерево работы. С помощью --soft он просто перемещает метку, оставляя индекс и рабочее дерево. Когда git является тем, чем он является, есть еще несколько флагов, которые еще больше закручивают смысл, но это большие три: --soft, ничего как --mixed и --hard.

2 Если git только добавленные вещи, ваше репо со временем станет огромным. Таким образом, в конечном итоге "недостижимые" комментируют: те, у кого нет ярлыков, и даже какие-либо остатки записей reflog, указывающие на них, и которые не указываются какой-либо фиксацией, которая имеет метку, или какие-либо другие ссылки, в конечном итоге эти недостижимые коммиты (и любые другие недостижимые объекты) удаляются, когда git запускает git gc для вас автоматически. Вы можете заставить их быть удаленными раньше, но редко есть веская причина беспокоиться.

3 Git сам зависит от гарантии. Это математически возможно, но крайне маловероятно, для любых двух разных объектов, которые заканчиваются одним и тем же SHA-1. Если это произойдет, git ломается. 4 Если распределение достаточно хорошее, вероятность равна 1 из 2 160 что действительно крошечно. Это хорошо, так как "Парадоксальный день рождения" очень быстро увеличивает вероятность, но поскольку он начал настолько крошечным, он остается крошечным, и на практике он никогда не было проблемой.

4 По дизайну "поломка" заключается в том, что git просто перестает добавлять объекты, так что все так далеко все еще хорошо. Затем вам нужно перейти к любой новой системе, предназначенной для обработки репозиториев с миллиардами объектов, "следующего поколения" git или любого другого.

Ответ 2

У меня есть хорошие новости и плохие новости для вас.

Хорошей новостью является то, что вы находитесь в состоянии, которое вы выражаете, что хотите! Последняя фиксация на master действительно находится сейчас в вашей ветке, и все хорошо с юниверсом.

Плохая новость заключается в том, что теперь, с вашей операцией переадресации, вы эффективно переместили свою ветку на кончик мастера; то есть ваша ветка развития теперь находится в том же состоянии, как если бы вы просто разветвлялись от кончика мастера.

Но это [считается] хорошим: при условии, что у вас не было конфликтов слияния, вы не потеряли никаких данных в этом процессе, и у вас также нет бесполезной фиксации слияния на вашем ветвь.

Книга отлично справляется с объяснением того, что такое rebase, поэтому я не буду повторять ее. Из описаний, которые вы описываете, вы не должны были потерять работу.


Если вы хотите воссоздать свою первоначальную историю до принудительного нажатия, то кто-то с незатянутой историей может принудительно направить свою ветку в удаленный репозиторий. Это приведет к тому, что состояние вашего репо будет тем, что было на их поле в момент их нажатия.

Ответ 3

Если вы берете хеш фиксации из reflog (также хвост записи в обычном журнале git), вы можете получить reset --hard COMMIT, а затем git push -f origin master, который обычно плохая вещь. Я бы рекомендовал проверить всю историю в отдельной, чистой директории, прежде чем делать силовой толчок.