Отмена случайного поп-гита

186

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

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

NREN
источник
2
Вы не должны быть допущены git stash popбез совершения первого. Что вы сделали для этого?
Крис Джестер-Янг
Не уверен, чтобы быть честным (это было вчера). Слияние не произошло само по себе, потому что были конфликты. После этого я смог запустить шкатулку.
Нен
1
Я сделал это просто знаю, используя git версии 1.7.9.msysgit.0. У меня были неподготовленные файлы, и треск просто соединил все в себе.
PandaWood
Я смог запустить git stash popпосле постановки изменений (хотя я не фиксировал) с версией git
2.25.0.windows.1
Если вы проиндексировали свои изменения и потеряли их во время выполнения, stash pop/applyпрежде чем делать коммит, вы можете запустить git fsck --lost-found. Эта команда будет перебирать висячие большие двоичные объекты (фактические файлы для тех, кто не знаком с терминологией git), которые были организованы, но нигде не зафиксированы (поэтому висят), и помещать их в каталог .git / lost-found / , где вы можете git showих увидеть и увидеть если это файлы, которые вы ищете.
Артем Хеворян

Ответы:

69

Попробуйте использовать Как восстановить сброшенный тайник в Git? чтобы найти тайник, который вы нашли. Я думаю, что всегда есть два коммита для тайника, так как он сохраняет индекс и рабочую копию (поэтому часто индексный коммит будет пустым). Затем git showих, чтобы увидеть patch -Rразличия и использовать, чтобы отменить их.

Бен Джексон
источник
6
Вау, это сработало. Мне удалось найти коммиты с тайником git fsck --no-reflog | awk '/dangling commit/ {print $3}'(по ссылке), и я просто вручную нашел проблему из этого diff. Спасибо!
Нен
1
fsck выводит огромный список. Утомительно показывать каждый SHA1 там. Как ты делаешь это ?
meson10
5
@ meson10: К сожалению, тайники хранятся в рефлоге, что было бы очевидным способом (если бы они были настоящей веткой), чтобы взглянуть на историю всплывающих тайников. Также позвольте мне предположить, что запрос downvote + о помощи - не лучшая стратегия.
Бен Джексон
2
Мне потребовалось немного искажения, чтобы понять это правильно. Вот результат моей работы git diff -p ${STACH_SHA1}~1 ${STASH_SHA1} | patch -R -p1:; Я попытался с git showкак предложено, но его вывод не был хорош для патча; Кроме того, мне пришлось предоставить -p1возможность исправления для удаления элемента a/..and, b/..который git diffпомещается перед файлами, иначе он не будет разрешать пути из корня хранилища. ПРЕДЛОЖЕНИЕ: будьте осторожны и зафиксируйте беспорядок в отдельной ветке перед игрой с патчем.
basilikode
@BenJackson В вашем ответе «всегда» означает и то, stash popи другое, и stash pushсработает коммит, который сохранит изменения в индексе и рабочем каталоге, верно?
Артем Хеворхян
36

Из git stash --help

Recovering stashes that were cleared/dropped erroneously
   If you mistakenly drop or clear stashes, they cannot be recovered through the normal safety mechanisms. However, you can try the
   following incantation to get a list of stashes that are still in your repository, but not reachable any more:

       git fsck --unreachable |
       grep commit | cut -d\  -f3 |
       xargs git log --merges --no-walk --grep=WIP

Это помогло мне лучше, чем принятый ответ с тем же сценарием.

Качар
источник
13
Обратите внимание, что многие решения, связанные с поиском «WIP», основаны на стандартных сообщениях. Если вы дадите своим тайникам явные сообщения, они могут не содержать WIP.
Бен Джексон
Спасибо. Я добавил опцию --oneline в команду log, чтобы улучшить читаемость.
Басло
Это только поможет вам найти SHA тайника. Но если он интегрирован с комментарием @basilikode из принятого ответа (git diff SHA ~ 1 SHA | patch -R), он работает нормально. Я рекомендую сначала использовать путь --dry-run для проверки.
Jarek C
3

Если ваше объединение не было слишком сложным, другой вариант:

  1. Переместите все изменения, включая изменения слияния, в stash, используя «git stash»
  2. Запустите объединение снова и зафиксируйте ваши изменения (без изменений из удаленного хранилища).
  3. Запустите «git stash pop», который должен игнорировать все изменения из вашего предыдущего слияния, поскольку файлы теперь идентичны.

После этого у вас останутся только те изменения, которые вы оставили слишком рано.

Markus
источник