@deftonee

Как вернуть потерянные в git stash clear файлы?

На стенде, где развёрнут git, была выполнена комбинация комманд:
git add .
git stash
git stash clear
В результате удалились все файлы, которых не было в репозитории. Даже те, которые были добавлены пользователями в процессе использования стенда.
Для поиска потерянных файлов были выполнена комманда:
git fsck --unreachable
Среди полученных результатов было найдено дерево (tree), которое содержало ту папку, где искомые файлы были. При дальнейшем путешествии по дереву файлы были найдены.
Как теперь вернуть эти файлы, если они не были включены ни в один коммит?
  • Вопрос задан
  • 3181 просмотр
Решения вопроса 1
@deftonee Автор вопроса
Для решения был написан скрипт на python.
# -*- encoding: utf-8 -*-
import git
import re
from os import path, mkdir
from subprocess import Popen, PIPE


def find_that_hash(source_hashes, aim):
# выделить из списка "source_hashes" те записи, в информации о которых есть вхождение строки aim
    found_hashes = []
    for tmp_hash in source_hashes:
        infa = repo.git.cat_file('-p', tmp_hash)
        if infa.find(aim) != -1:
            found_hashes.append(tmp_hash)
    return found_hashes


def find_hash_in_info(source_hash, aim):
# выделить из информации о хэше source_hash строки, в которых есть вхождение строки aim и разбить эти строки на слова
    found_hashes = []
    for info_string in repo.git.cat_file('-p', source_hash).split('\n'):
        if info_string.find(aim) == -1:
            continue
        else:
            tmp1 = re.split('[\t]+', info_string)
            tmp2 = re.split('[ ]+', tmp1[0])
            tmp2.append(tmp1[1])
            found_hashes.append(tmp2)
    return found_hashes

#===========================================================================

project_path = '/home/user/project/'
secure_files_path = project_path + 'media/secure-files/'

repo = git.Repo(project_path)
unreachable = repo.git.fsck('--unreachable')
lost_found = repo.git.fsck('--lost-found')

strings = [s for s in unreachable.split('\n')] + [s for s in lost_found.split('\n')]

tree_hashes = [s.split()[2] for s in filter(lambda x: ' tree ' in x, strings)]
commit_hashes = [s.split()[2] for s in filter(lambda x: ' commit ' in x, strings)]

our_docs_hashes = find_that_hash(tree_hashes, 'secure-files')
if not our_docs_hashes:
    print 'Hash of "secure-files" dir not found'
else:

    if not path.exists(secure_files_path):
        mkdir(secure_files_path)
    for our_docs_hash in our_docs_hashes:
        secure_dir_hash_info = find_hash_in_info(our_docs_hash, 'secure-files')[0]
        for sub_dir_info in find_hash_in_info(secure_dir_hash_info[2], 'tree'):
            current_path = secure_files_path + sub_dir_info[3] + '/'
            if not path.exists(current_path):
                mkdir(current_path)
            for file_info in find_hash_in_info(sub_dir_info[2], 'blob'):
                
                rubbish = "printf '%b\n'"
                fn, _ = Popen("%s '%s'" % (rubbish, file_info[3]), shell=True, stdout=PIPE).communicate()
                file_name = '%s%s' % (current_path, fn[1:len(fn)-2])
                if not path.exists(file_name) and fn[1:len(fn)-2] != '':
                    f = open(file_name, 'w')
                    f.write(repo.git.show(file_info[2]))
                    f.close()
                    print 'Restored: %s' % (file_name)
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Мануал по git stash рекомендует искать не дерево, а merge-коммит со словом WIP в заголовке, и потом просто вычекивать его.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы