Найти и извлечь файл из Git stash
Возможно, я слишком часто использую git stash, но это то, что я обычно делаю, когда хочу отбросить мои эксперименты в проекте.
Вопрос 1:
- Как я могу найти имя файла во всех моих текущих записях?
Вопрос 2:
Ответы
Ответ 1
Немного более важно отметить, что refs/stash
является reflog псевдо-ветки (ref):
git rev-list --walk-reflogs stash # (long option)
git rev-list -g stash # (short option)
Итак, вы можете найти файл:
for sha in $(git rev-list -g stash);
do
git ls-tree -r $sha:;
done |
grep "$SOMEFILENAME" |
sort --unique
(Уникальный вид - удалить дубликаты одной и той же версии в разных записях).
например:.
$ for sha in $(git rev-list -g stash); do git ls-tree -r $sha:; done | grep numeric.js | sort -u
100644 blob f1c9a61910ae1bbd562615444a45688b93e9d808 LSPO.Web/DaVinci/JScript/numeric.js
Итак, вы можете запустить визуальный diff, например,
kompare numeric.js <(git cat-file -p f1c9a61910ae1bbd562615444a45688b93e9d808)
Конечно, если у вас уже была догадка, в которой reflog содержал другой файл, это было бы намного проще:
git diff [email protected]{3} -- numeric.js
Ответ 2
Ответ от @sehe дает отличный ответ для Вопроса 2.
Я пришел на эту страницу, чтобы найти лучший ответ на вопрос 1, чем то, что я сейчас использую. В настоящее время я использую оболочку script stashshowall.sh
, а затем я выводит результат.
Разница в моем ответе заключается в том, что, в то время как другие ответы здесь говорят вам, был ли изменен файл, который вы ищете, они не сообщают вам, какой штамп находится в файле, если вы хотите apply
занести.
Мой ответ - чистое использование "фарфоровых" команд git, но оно работает для меня.
#!/bin/sh
# stashshowall.sh
for stash in `git stash list | sed 's/\(\w*\)\:.*/\1/'`
do
echo
echo "$stash"
git stash show $stash
done
Итак, чтобы ответить на вопрос 1, я запустил
> stashshowall.sh | grep "stash\|some-file"
который дает мне
[email protected]{0}
[email protected]{1}
.../some-dir/some-file | 16 ++--
[email protected]{2}
[email protected]{3}
[email protected]{4}
.../some-dir/some-file | 2 ++--
[email protected]{5}
Таким образом, я знаю, что мне нужно apply
или смотреть дальше на stash{1}
или stash{4}
Ответ 3
TL;DR
grep stash для имени файла:
git reflog stash -- '*fileglob*'
git log -g stash -- '*fileglob*'
grep stash для контента:
git stash list -G<regex>
Поиск записи для имени файла
Из git help stash:
Последний созданный тэг хранится в refs/stash
; более старые stashes найдены в reflog этой ссылки и могут быть названы с использованием обычного синтаксиса reflog (например, [email protected]{0}
...)
Из git help reflog:
git reflog show
является псевдонимом для git log -g --abbrev-commit --pretty=oneline
Из git журнал справки:
-g
- ходить reflogs
Вместо того, чтобы следовать цепочке родословной фиксации, пройдите записи рефлога от самых последних до более старых.
git синопсис журнала:
git log [<options>] [<revision range>] [[\--] <path>...]
Из git спецификации ревизий:
<refname>
, например. мастер, руководители/мастер, refs/heads/master
Символическое имя ссылки....
При двусмысленности a <refname>
устраняется неоднозначно, принимая первое совпадение в следующих правилах:
-
Если $GIT_DIR/<refname>
существует, это то, что вы имеете в виду (обычно это полезно только для HEAD
, FETCH_HEAD
, ORIG_HEAD
, MERGE_HEAD
и CHERRY_PICK_HEAD
);
-
в противном случае refs/<refname>
, если он существует;
Теперь у нас есть все вместе:
git reflog stash -- '*fileglob*'
git log -g stash -- '*fileglob*'
Итак, мы stash
будем решать refs/stash
, а -g
приведет к прохождению всей ветки, а `- 'fileglob будет соответствовать любым путям в этой фиксации.
Поисковый штамп для контента
git help stash:
... Команда принимает параметры, применимые к команде журнала git, чтобы контролировать, что показано и как. См. git-log.
Из git журнал справки:
-G <regex>
Ищите различия, в тексте патча которых добавлены/удалены строки, соответствующие <regex>
.
Итак, простая команда:
git stash list -G<regex>
Другие команды pickaxe также должны работать.
Ответ 4
Я использую это для поиска файла среди штампов
git stash list | cut -d ":" -f 1 | xargs -L1 git diff --stat | grep <filename>
Вы можете создать новую ветку, содержащую stash (git checkout -b <new_branch> <stash>
), а затем скопировать файл туда и обратно, чтобы слить его обратно.
Вы можете использовать git difftool
, чтобы получить визуальное представление об отличии.
РЕДАКТИРОВАТЬ: Чтобы получить фиксацию кошелька вместе с именем файла, вы можете использовать эту оболочку script:
for i in $(git stash list | cut -d ":" -f 1 | xargs -L1 git show | grep commit |
cut -d" " -f 2)
do
if git show $i --oneline --stat | grep ht.h
then
echo $i
fi
done
Он распечатает фиксацию под именем файла.