2017-01-03 2 views
1

Я занимался большой интерактивной перестановкой, где редактировал что-то вроде 8 коммитов. Это делается с помощью git commit --amend. Моя проблема в том, что однажды я получил конфликт слияния, которого я не заметил, поэтому я продолжал наивно изменять и git rebase --continue -ing. По-видимому, теперь я внес поправки в несколько коммитов в один, и около 4 моих коммитов исчезли после завершения rebase. Изменения были внесены в другие коммиты.Вместо того, чтобы разрешать конфликт в интерактивной перестановке, я скорее изменил. Могу ли я отменить?

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

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

Git дерево пример:

Перед перебазироваться: A-B-C-D-E-F

После перебазирования: A-B-C-F (C теперь имеет изменения от D и Е исправленные)

+0

Я не знаю, как разгадать комманду 'C' на несколько оригинальных произведений. Я лично переделаю rebase. –

+0

2017 здесь я прихожу – Automatico

+0

Возможно, у кого-то еще есть серебряная пуля для вас. Из того, что я могу сказать, просто делать это было бы меньшим злом. –

ответ

3

Да, вы можете.

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

Я предполагаю, что содержимое F в вашем примере - это именно то, что вы хотите, чтобы ваш конечный результат был, вы просто пропустили D и E совершает.

Что вы можете сделать это:

git checkout C    # "git status" should be empty right now 
git checkout F . 
git reset . 
git add only-changes-from-D ; git commit -m D 
git add only-changes-from-E ; git commit -m E 
git add -A ; git commit -m F 

git checkout F . ; git reset . делает это так, что ваш рабочий каталог содержит F, но ваша голова еще указал на C, и ничто не в индексе. git status теперь покажет вам полную разницу между C и F.

Теперь вы берете свой любимый инструмент добавления/фиксации (мне нравится git gui) и выбирайте каждое изменение, которое принадлежало D изначально, и сообщайте. Повторите для E. После этого доступны только изменения от F; вы можете добавлять и фиксировать их за один раз. Конечно, если есть больше между E и F, вам придется промыть и повторить.

Это имеет то преимущество, что на самом деле вам ничего не нужно менять. Конечным результатом будет именно F, но при необходимости вы получите несколько промежуточных коммитов.

2

После перезагрузки/изменения фиксации первоначальная фиксация все еще здесь. Хотя, если он не доступен через ветку, он не отображается в git log.

Думаю, с помощью git reflog вы можете делать то, что хотите.

git reflog //identify the hash of the commits you want, look for your commit --amend that you want to undo git checkout B git cherry-pick hash-of-commit-C-as-resolved-during-rebase-but-before-amending git cherry-pick hash-of-commit-C-after-amending-with-D git cherry-pick hash-of-commit-C-after-amending-with-E git cherry-pick F

3

Каждый коммит, что вы сделали, изменены или нет, до сих пор «там», и они все находят, в состоянии через reflogs.Это связано с тем, что не Фактически изменение что-нибудь, он просто делает новый обязуется, что «откидывает старую сторону в стороне».

Подтверждает, что вы не марку (т.е., если есть конфликтогенная состояние в индексе, так что git commit отказался сделать коммит) были, конечно же, не сохраняются.

Используйте git reflog (или git reflog HEAD), чтобы найти каждый сделанный фиксаж. Возможно, вы захотите сохранить свои исходные идентификаторы хэшей в файле для вырезания и вставки, так как простые способы их названия [email protected]{3} и т. Д. Являются относительными и будут меняться. (То есть, каждый раз, когда вы регулируете HEAD, что было [email protected]{3}[email protected]{4} теперь, [email protected]{5}, вскоре [email protected]{7}, и в конце концов [email protected]{198}, augh! :-))

Вы также можете получить оригинальную цепочку обратно сразу (если у вас нет выполните любые другие команды), используя имя ORIG_HEAD. То есть, что происходит, когда вы запускаете git rebase -i, а затем выполняете все свои изменения, исправления и т. Д. И, наконец, заканчиваете, то, что git rebase сохраняет исходный ответвление под именем ORIG_HEAD. Вы можете создать новую точку ветвления или имя тега в том, что оригинальный коммит, а затем использовать name, name~1, name~2, и так далее, чтобы вернуться к первоначальной (предварительной Rebase) обязуется:

git tag oops ORIG_HEAD 

Теперь oops является commit F, oops~1 is E, и так далее.

Вы можете: git show любой фиксатор, git checkout <commit-id> -- <path>, чтобы извлечь из него файл, git cherry-pick <commit-id>, чтобы применить это сообщение как дельта к вашей текущей позиции и так далее.

Смежные вопросы