2014-01-22 2 views
0

История моих фиксаций выглядит следующим образом:Как найти номера филиалов при возврате слияния?

A - B - C - D - E 
    \ /
     X - Y 

Филиал ABCDE является master, филиал XY некоторые другие отрасли (например test), и D является слияние фиксации. HEAD сейчас на E. Мне нужно вернуть мой рабочий каталог в состояние A в предположении не с использованием git reset --hard <SHA1(A)>, только git revert. Насколько я знаю, в таком случае это может быть сделано двумя способами:

Первый способ:

git revert --no-commit <SHA1(E)> 
git revert -m 1 --no-commit <SHA1(D)> 
git revert --no-commit <SHA1(C)> 
git revert --no-commit <SHA1(B)> 
git commit -m "Reverted to state A" 

Второй способ:

git revert --no-commit <SHA1(E)> 
git revert -m 2 --no-commit <SHA1(D)> 
git revert --no-commit <SHA1(Y)> 
git revert --no-commit <SHA1(X)> 
git revert --no-commit <SHA1(B)> 
git commit -m "Reverted to state A" 

камнем преткновения является git revert -m. В этом примере я предполагаю, что 1 позволяет продолжить цепочку ревертов по ветке master и 2 - вдоль ветки test.

Вопрос в следующем: как я действительно знаю, какое число означает, какая ветка?

+0

Почему вы не просто «git checkout A'? Если вам нужно переключить ветку на точку A, 'git checkout A; git branch -D NAME; git branch NAME; git checkout NAME'. Вы все равно можете проверить любой из ABCDEX или Y. – Andy

+0

Фактически я работаю с удаленным репо, и в этом случае мне разрешено только возврат и отсутствие сброса и выписки. – user3026384

+1

Я бы создал патч между A и HEAD и применил его в обратном порядке с помощью 'patch -R'. – Kaz

ответ

0

Вы можете проверить слияние совершить, чтобы увидеть, кто это родители:

git show <SHA1(D)> 

Родители будут перечислены в том порядке, в котором вы можете обратиться к ним. Эта информация также печатается на выходе git log. Используйте это, чтобы вывести, какие фиксации имеют значение, когда вы делаете git revert -m.

Редактировать: кажется, что вы работаете с публичным репо и ищете способ изменить опубликованную ветку, что существенно отличается от изменения состояния рабочей копии. У Git есть способ вернуться, не вычисляя каждого родителя слияния на этом пути. Просто делать это все сразу:

git revert <SHA1(B)>.. 

Update: Я просматривал некоторые старые вещи, и понял, что это ответ, который я дал это полностью неправильно. Если вы выше, вы не получите состояния А, но вместо этого получить Франкенштейн вы не хотите:

A - C' - D' - E' 
\ /
    X - Y 

что^является эквивалентом того, что вы получите, что не на всех что ты хочешь. Существует лишь один способ сделать это и сохранить свою историю полностью:

git revert HEAD    # reverts E, labeled as E' below 
git revert -m 1 <SHA1(D)> # reverts D, labeled as D' below 
git revert HEAD    # reverts C, labeled as C' below 
git revert HEAD    # reverts B, labeled as B' below 

Это оставит вам историю вида:

A - B - C - D - E - E' - D'{C} - C' - B' 
    \ /
     X - Y 

Этот метод поможет вам, что вы хотите и сохранить каждый бит истории. Методы @Kaz и @ torek более эффективны и менее подробны, и если вы не хотите повторно вводить X и Y, тогда я рекомендую одно из этих решений; тем не менее, они потенциально сложнее повторно ввести X и Y в вашу основную ветку, если это вас беспокоит.Возврат каждой части позволяет повторно ввести X и Y без перезаписи/C & P еще раз, что является привлекательным вариантом, если X и Y были значительными изменениями или если вы навязчивы в том, чтобы сохранить самую точную историю (я, как правило, сюда).

Чтобы вновь X и Y, вы должны сделать это:

git revert D' 

Это, вероятно, создают конфликтов слияния, особенно если вы также не возвращаются B' и C', но это может быть лучше, чем повторно делать X и Y от руки. Linux Torvalds написал a very thorough explanation of this scenario, который может вам помочь.

+0

Запуск новой ветви не вернет *, что * ветвь в точку A. Каждому придется переключиться на новую ветку. Вероятно, он тоже не хочет перезагружаться, потому что это непереходное изменение. – Kaz

+0

Ах. Он не указал ничего о публичном репо в своем вопросе, что довольно важно. –

+0

Он указал, что сброс на A является неприемлемым. Если эти изменения не публикуются ни для какого другого репо, нет причин, по которым это решение неприемлемо. – Kaz

1

Я бы не ломать себе голову над мерзавца слишком много в этом случае и просто сделать:

git diff <sha(A)> HEAD | git apply -R 
git commit -a -m "undoing everything since A" 

Конечно, рассмотреть все, прежде чем совершить. Кроме того, после фиксации проверьте: каковы различия между A и HEAD сейчас? Не идеально, ничего:

git diff <sha(A)> HEAD 
+0

Не знаете, почему это было опущено ... – Andy

+0

@ Энди Зависть; жажда мести; неуклюжая мазания на крошечном экране смартфона; Недостаточность контрольной суммы TCP/IP ...:) – Kaz

+0

@Kaz Я просто попытался вас выгнать, но у меня недостаточно репутации :( – user3026384

2

Другой метод просто выплескивать работы дерева, а затем вставить произведение дерево-как-она-была-на-за направления A:

# assumes you're in the top level 
$ git rm -rf . 
$ git checkout sha-or-other-specifier-for-A -- . 
$ git commit -m 'revert to state A' 

Идея вот что git rm -rf полностью опустошает дерево работы и индекс/промежуточную область, а затем git checkout <rev> -- . полностью заново заполняет дерево работы и индексирует/организует, но получает деревья и файлы из указанной версии, а не из последней версии.

После того, как эти два выполнены, новый фиксатор записывает те же деревья и файлы, что и в commit A.

+0

Очень хорошо, мне это нравится. – Kaz

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