Вернуть один из коммитов в сдавленный коммит? - PullRequest
0 голосов
/ 04 сентября 2018

У меня есть запрос на получение с 250 files changed, только 5 ~ 10 из которых я изменил.

Это сквош из 4 коммитов, и один из них - revert из merge с другой ветвью, и этот содержит ~ 240 files changed.

Это выглядит так

<some commits I made after this>
<squashed commit of:

minor change

working on abcd..

Revert "Merge branch 'settlement-statement' into rents-proration"

This reverts commit 0e44eae, reversing
changes made to a39e7fd.

some more change>

Я хочу только вернуться

Revert "Merge branch 'settlement-statement' into rents-proration"

This reverts commit 0e44eae, reversing
changes made to a39e7fd.

Я думал, что слияние ветки settlement-statement с моей веткой исправит это, но это не так.

Как я могу это исправить, не просматривая все файлы в files changed и не выбирая мои изменения?

Ответы [ 2 ]

0 голосов
/ 04 сентября 2018

Обновление - я написал оригинальный ответ в два этапа, и это немного сбивает с толку. Информация остается прежней, но я ее немного чищу ...


В зависимости от того, как вы squash редактировали коммиты, у вас есть одна из двух очень похожих ситуаций. Грубо говоря:

1) Если вы раздавились от одной ветви к другой (например, git merge --aquash), у вас есть график, подобный

x -- AB!MCD -- E <--(branch_for_pr)

A -- B -- !M -- C -- D <--(work_branch)

, где !M отменил некоторое предыдущее слияние, а AB!MCD - это "сквош" из A, B, !M, C и D.

2) Если вы раздавили коммиты «на месте» на ветке, например, git rebase -i, график больше похож на

x -- AB!MCD -- E <--(branch_for_pr)

A -- B -- !M -- C -- D <--(branch_for_pr@{2})

Здесь branch_for_pr@{2} - запись reflog. Инструменты не отображают записи reflog так же явно, как текущие ссылки, поэтому может показаться, что A .. D «пропали», но (по крайней мере, в локальном клоне, где произошел сквош), они, надеюсь, не вернутся. т. (Это правда, что срок действия записей reflog истекает - по умолчанию примерно через 3 месяца или когда вы явно их истекаете. По истечении срока действия записи reflog gc может удалить старые коммиты, если за это время вы что-то не сделали что делает их "доступными". Кроме того, reflogs не делятся на push или fetch.)

Вы можете найти запись reflog с помощью команды, подобной

git reflog branch_for_pr

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

В остальной части этой записи предполагается, что фактическая ветвь указывает на D. Итак ... как поступить?

Самое простое, что нужно сделать - вернуть !M на branch_for_pr. Это может показаться нелогичным, но вы можете изменить практически все; это не должно быть предком HEAD. Поэтому вам нужно выражение, которое разрешается в !M - это может быть его идентификатор фиксации или в этом примере что-то вроде work_branch~2.

git checkout branch_for_pr
git revert work_branch~2

Несколько точек фона, которые следует знать здесь:

Фиксация - это просто снимок проекта с небольшим количеством метаданных. Метаданные включают в себя «родительский» список, который помещает снимок относительно других снимков в истории. Многие команды git работают с патчем коммита - то есть разницей между коммитом и его родителем (или одним из его родителей, в случае слияний). Метаданные коммита не включают какие-либо особые отношения для «коммит, возвращенный этим коммитом», или «коммит (и), заключенный в этот коммит»; эта информация по существу потеряна.

Как подразумевается выше, «возврат» - это просто краткий способ собрать коммит, который определенным образом относится к его родителю, управляемый отношениями другого коммита с его родителем. git не увековечивает, что этот конкретный коммит был сгенерирован путем возврата другого коммита (намного меньше, чем тот, который был другим коммитом).

Аналогично, "сквош" - это просто сокращенный способ указания группы изменений, которые вы хотите применить к HEAD для создания нового коммита. Полученный коммит не «знает», что это сквош.

Так что эти вещи могут изменить ваш взгляд на то, что вы пытаетесь сделать, и повлиять на то, как вы подходите к этому вопросу. И все же более неотложная проблема для предлагаемого решения «повторного слияния» заключается в том, что git немного странно относится к возвратам слияний. После того, как вы отменили слияние, его не так просто восстановить. Вы должны либо заново сгенерировать ветку из новых коммитов (чтобы сделать возможным повторное слияние), либо просто отменить возврат - это то, что я рекомендую сделать выше, прямо в вашей последней ветке.

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

0 голосов
/ 04 сентября 2018

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

К счастью, Git требуется несколько недель, чтобы что-то выбросить. Твоя несокрушимая ветвь, вероятно, все еще там. Надеемся, что ваш репозиторий выглядит следующим образом.

A - B - C - D [master]
            |\
            | E [feature]
            \
             F - G - H - I

feature это ваша ветвь. F - G - H - I - ваши исходные несокрушимые коммиты. E равно F - G - H - I все сжато вместе. Мы хотим вернуть feature на I.

I не имеет ссылки на ветку или тег. Мы можем найти его с помощью reflog. Это история всех случаев, когда HEAD сдвигался. Каждая проверка, ребаз и сброс. Вы ищете что-то вроде этого.

c6a7e90 (HEAD -> master) HEAD@{0}: rebase -i (finish): returning to refs/heads/master
c6a7e90 (HEAD -> master) HEAD@{1}: rebase -i (squash): second
40c7031 HEAD@{2}: rebase -i (squash): # This is a combination of 2 commits.
4c79819 HEAD@{3}: rebase -i (start): checkout HEAD^^^
7fd34b9 HEAD@{4}: rebase -i (finish): returning to refs/heads/master
7fd34b9 HEAD@{5}: rebase -i (start): checkout master

7fd34b9 - это I, идентификатор коммита вашей ветви до того, как вы раздавили. c6a7e90 - E, коммит после того, как вы раздавили. Затем вы можете git reset --hard 7fd34b9 положить feature назад, прежде чем вы раздавите.

Более подробную информацию можно найти в Git Book о Обслуживание и восстановление данных и Сброс демистификации .


Вот почему нельзя раздавливать целые ветви функций. Важные детали теряются как для истории, так и для рецензентов. Почему вы изменили эту строку? Это может быть одна из 4 причин, смешанных вместе. ОТО, вы можете получить "раздавленный" вид на несокрушимую ветвь. Github предоставит один для вашего PR, или вы можете сделать git diff master. Но вы не можете пойти другим путем, вы не можете получить непревзойденные изменения из раздавленной ветви. Жизненно важная информация потеряна.

Сквош должен быть зарезервирован для устранения неинтересных изменений, таких как исправления опечаток и «Я хочу сделать это изменение три фиксации назад по-другому».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...