Я часто использую git stash
и git stash pop
для сохранения и восстановления изменений в моем рабочем дереве. Вчера у меня были некоторые изменения в моем рабочем дереве, которые я спрятал и вытолкнул, а затем я сделал больше изменений в своем рабочем дереве. Я хотел бы вернуться и просмотреть вчерашние сохраненные изменения, но, git stash pop
похоже, удаляет все ссылки на связанный коммит.
Я знаю, что если я использую, git stash
то .git / refs / stash содержит ссылку на коммит, использованный для создания тайника. И .git / logs / refs / stash содержит весь тайник. Но эти ссылки исчезли после git stash pop
. Я знаю, что коммит все еще находится в моем хранилище, но я не знаю, что это было.
Есть ли простой способ восстановить вчерашнюю ссылку на коммит?
Обратите внимание, что сегодня это не критично для меня, потому что у меня ежедневные резервные копии, и я могу вернуться к вчерашнему рабочему дереву, чтобы получить свои изменения. Я спрашиваю, потому что должен быть более легкий путь!
git stash pop
, вы можете сделать этоgit stash apply
вместо этого. Он делает то же самое, за исключением того, что не удаляет ссылку на примененный тайник.git stash
,git pull -r upstream
,git push -f origin
,git stash pop
, и поп сказал «фатальный: журнал для рефов / тайник пуст». Tried Я попробовал кучу этих ответов, ничего не получалось. Когда я посмотрел в .git / refs / stash , там был SHA. Может быть проблема с маркировкой сетевого диска Windows для автономной синхронизации? BОтветы:
После того, как вы узнаете хэш потерянного коммита, вы можете применить его как тайник:
Или вы можете создать для него отдельную ветку
После этого вы можете делать все, что хотите со всеми обычными инструментами. Когда вы закончите, просто взорвать ветку.
Нахождение хеша
Если вы только совал его , и терминал по - прежнему открыт, вы по- прежнему имеют значение хеш - функции выведенную
git stash pop
на экран (спасибо, Dolda).В противном случае вы можете найти его, используя это для Linux, Unix или Git Bash для Windows:
... или используя Powershell для Windows:
Это покажет вам все коммиты в подсказках вашего графа коммитов, на которые больше не ссылаются ни одна ветка или тэг - каждый потерянный коммит, включая каждый сохраненный вами коммит, будет где-то на этом графе.
Самый простой способ найти нужный stash-коммит - это, вероятно, передать этот список
gitk
:... или посмотрите ответ от emragins, если используете Powershell для Windows.
Это запустит браузер репозитория, который покажет вам каждый коммит в репозитории , независимо от того, доступен он или нет.
Вы можете заменить его
gitk
чем-то вроде,git log --graph --oneline --decorate
если предпочитаете хороший график на консоли, а не отдельное приложение с графическим интерфейсом.Чтобы обнаружить коммиты на stash, ищите сообщения коммитов этой формы:
WIP на somebranch : commithash Некоторое старое сообщение коммита
Примечание . Сообщение коммита будет только в этой форме (начиная с «WIP on»), если вы не предоставили сообщение, когда это сделали
git stash
.источник
%{ $_.Split(' ')[2]; }
должно делать эквивалент команды{print $3}
inawk
в PowerShell, но у меня нет системы Windows, чтобы проверить это, и вам все еще нужен эквивалент для этой/dangling commit/
части. В любом случае, просто бегитеgit fsck --no-reflog
и смотрите на результат. Вам нужны хэши из строк «dangling commit <commitID>».git stash save "<message>"
).git fsck --no-reflog | awk '/dangling commit/ {print $3}' | xargs -L 1 git --no-pager show -s --format="%ci %H" | sort
вероятно, последняя запись - это та, которую вы хотитеstash apply
.git stash apply {ref}
восстановил упавший заначку!git
так здорово, что это должно быть незаконно!Если вы не закрыли терминал, просто посмотрите на вывод,
git stash pop
и у вас будет идентификатор объекта уроненного тайника. Обычно это выглядит так:(Обратите внимание, что
git stash drop
также производит ту же строку.)Чтобы вернуть этот тайник, просто бегите
git branch tmp 2cae03e
, и вы получите его как ветвь. Чтобы преобразовать это в тайник, запустите:Наличие этого как ветви также позволяет вам свободно им манипулировать; например, чтобы выбрать его или объединить.
источник
git stash apply commitid
то ,git stash
чтобы получить новый тайник.git stash pop
, он также не сбрасывает тайник, так что обычно это не проблема.git stash pop
. Если вы хотите применить тайник, не опуская его, используйтеgit stash apply
вместо этого. Кроме того, если вы хотите применить изменения к нескольким веткам, вы также можете выбрать коммит.Просто хотел упомянуть это дополнение к принятому решению. Для меня это было не сразу очевидно, когда я впервые попробовал этот метод (возможно, так и должно было быть), но чтобы применить тайник из значения хеша, просто используйте «git stash apply»:
Когда я был новичком в git, мне это было непонятно, и я пробовал разные комбинации «git show», «git apply», «patch» и т. Д.
источник
Чтобы получить список тайников, которые все еще находятся в вашем хранилище, но больше недоступны:
Если вы дали название своему хранилищу, замените «WIP» в
-grep=WIP
конце команды частью вашего сообщения, например-grep=Tesselation
.Команда выглядит как «WIP», потому что сообщение о фиксации по умолчанию для тайника находится в форме
WIP on mybranch: [previous-commit-hash] Message of the previous commit.
источник
!
).Я только что создал команду, которая помогла мне найти потерянный коммит:
Это перечисляет все объекты в дереве .git / objects, находит те, которые имеют тип commit, затем показывает сводку каждого из них. С этого момента достаточно было просто просмотреть коммиты, чтобы найти подходящий «WIP на работе: 6a9bb2» («work» - это моя ветка, 619bb2 - недавний коммит).
Я заметил, что если бы я использовал «git stash apply» вместо «git stash pop», у меня не возникло бы этой проблемы, и если бы я использовал «git stash save message », тогда фиксация могла бы быть легче найти.
Обновление: с идеей Натана, это становится короче:
источник
git fsck --unreachable | grep commit
должен показать sha1, хотя список, который он возвращает, может быть довольно большим.git show <sha1>
покажет, если это коммит вы хотите.git cherry-pick -m 1 <sha1>
объединит фиксацию с текущей веткой.источник
Эквивалент Windows PowerShell с использованием gitk:
gitk --all $(git fsck --no-reflog | Select-String "(dangling commit )(.*)" | %{ $_.Line.Split(' ')[2] })
Вероятно, есть более эффективный способ сделать это в одной трубе, но это делает работу.
источник
Если вы хотите восстановить потерянный тайник, сначала нужно найти хэш потерянного тайника.
Как подсказал Аристотель Пагальцис,
git fsck
вам должен помочь.Лично я использую свой
log-all
псевдоним, который показывает мне каждый коммит (восстанавливаемые коммиты), чтобы иметь лучшее представление о ситуации:Вы можете выполнить еще более быстрый поиск, если ищете только сообщения «WIP on».
Как только вы узнаете свой sha1, вы просто измените свой список хранения stash, чтобы добавить старый stash:
Вы, вероятно, предпочтете иметь связанное сообщение, чтобы
-m
И вы даже захотите использовать это как псевдоним:
источник
-d\\
должно быть-d\
(или даже более ясно-d' '
)git update-ref -m "$(git log -1 --pretty=format:'%s' ed6721d)" refs/stash ed6721
Мне понравился подход Аристотеля, но мне не нравилось использовать GITK ... так как я привык использовать GIT из командной строки.
Вместо этого я взял оборванные коммиты и вывел код в файл DIFF для просмотра в редакторе кода.
Теперь вы можете загрузить полученный файл diff / txt (он находится в вашей домашней папке) в ваш текстовый редактор и увидеть фактический код и полученный SHA.
Тогда просто используйте
источник
Вы можете перечислить все недоступные коммиты, написав эту команду в терминале -
Проверить недостижимый хеш коммита -
Наконец примените, если вы найдете спрятанный предмет -
источник
Почему люди задают этот вопрос? Потому что они еще не знают или не понимают рефлог.
Большинство ответов на этот вопрос дают длинные команды с параметрами, которые почти никто не запомнит. Таким образом, люди приходят к этому вопросу, копируют и вставляют то, что им нужно, и забывают об этом почти сразу после этого.
Я бы посоветовал всем с этим вопросом просто проверить reflog (git reflog), не намного больше этого. Как только вы видите этот список всех коммитов, есть сотни способов узнать, какой коммит вы ищете, и выбрать его или создать из него ветку. В процессе вы узнаете о reflog и полезных опциях для различных основных команд git.
источник
В OSX с git v2.6.4 я просто случайно запустил git stash drop, а затем нашел его, выполнив следующие шаги
Если вы знаете имя тайника, используйте:
$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show | grep -B 6 -A 2 <name of the stash>
в противном случае вы найдете идентификатор из результата вручную с помощью:
$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show
Затем, когда вы найдете commit-id, просто нажмите git stash apply {commit-id}
Надеюсь, это поможет кому-то быстро
источник
Я хочу добавить к принятому решению еще один хороший способ пройти через все изменения, когда у вас либо нет доступного gitk, либо нет X для вывода.
Затем вы получаете все различия для тех хэшей, которые отображаются один за другим. Нажмите «q», чтобы перейти к следующему различию.
источник
Я не смог получить ни одного ответа для работы в Windows в простом командном окне (Windows 7 в моем случае).
awk
,grep
ИSelect-string
не были признаны в качестве команд. Поэтому я попробовал другой подход:git fsck --unreachable | findstr "commit"
start cmd /k git show
будет выглядеть примерно так:
start cmd /k git show 8506d235f935b92df65d58e7d75e9441220537a4 start cmd /k git show 44078733e1b36962571019126243782421fcd8ae start cmd /k git show ec09069ec893db4ec1901f94eefc8dc606b1dbf1 start cmd /k git show d00aab9198e8b81d052d90720165e48b287c302e
git stash apply (your hash)
возможно, не лучшее решение, но сработало для меня
источник
Принятый ответ Аристотеля покажет все достижимые коммиты, включая коммиты, не похожие на тайники. Чтобы отфильтровать шум:
Это будет включать только коммиты, которые имеют ровно 3 родительских коммита (которые будут иметь тайник), и чье сообщение включает «WIP on».
Имейте в виду, что если вы сохранили свой тайник с сообщением (например
git stash save "My newly created stash"
), это переопределит стандартное сообщение «WIP on ...».Вы можете отобразить дополнительную информацию о каждом коммите, например, отобразить сообщение о коммите или передать его
git stash show
:источник
Мой любимый это одна строка:
Это в основном та же идея, что и в этом ответе, но гораздо короче. Конечно, вы все равно можете добавить,
--graph
чтобы получить древовидный дисплей.Когда вы найдете коммит в списке, примените с
Для меня использование
--no-reflogs
действительно показало потерянную запись тайника, но--unreachable
(как найдено во многих других ответах) не сделало.Запустите его на git bash, когда вы находитесь под Windows.
Кредиты: Подробности вышеупомянутых команд взяты из https://gist.github.com/joseluisq/7f0f1402f05c45bac10814a9e38f81bf
источник
Восстановить его, выполнив следующие действия:
Определите удаленный хэш-код:
gitk --all $ (git fsck --no-reflog | awk '/ dangling commit / {print $ 3}')
Вишневый пикап:
git cherry-pick -m 1 $ stash_hash_code
Разрешить конфликты, если они есть, используя:
git mergetool
Кроме того, у вас могут возникнуть проблемы с сообщением фиксации, если вы используете gerrit. Пожалуйста, сохраните ваши изменения, прежде чем использовать следующие альтернативы:
источник
Что я пришел сюда в поисках, так это как вернуть тайник, независимо от того, что я проверил. В частности, я спрятал что-то, затем проверил более старую версию, затем выскочил, но тайник был недоступен в тот более ранний момент времени, поэтому тайник исчез; Я не мог просто сделать это,
git stash
чтобы вернуть его обратно в стек. Это сработало для меня:Оглядываясь назад, я использую
git stash apply
неgit stash pop
. У меня былbisect
небольшой патч, который я хотел применить на каждомbisect
шагу. Сейчас я делаю это:источник
stash apply
.