Восстанавливаем файлы, удаленные в прошлых коммитах в Git


Сегодня передо мной встала довольно простая, но интересная задача: восстановить несколько файлов в репозитории Git, которые были удалены некоторое время назад в разных коммитах. Задача простая, потому что решение легко найти в соотвествующих ответах на Stack Overflow. Мне лишь осталось слегка адаптировать приведенные примеры команд для своих нужд.

Я не помнил точные названия файлов и уж тем более не знал хэши коммитов, в которых производилось удаление. Поэтому воспользовался сниппетом от пользователя Robert Munteanu, чтобы вывести историю удаленных файлов:

git log --diff-filter=D --summary

Отыскав необходимые файлы и коммиты, можно было бы воспользоваться простым git checkout для восстановления, но список был весьма велик, так что пришлось набросать небольшой скрипт на Bash.

#!/bin/bash

set -o nounset 
set -o errexit

declare -a files=(
    "source/posts/2012-11-11-twitter/Untitled.png"
    "source/posts/2013-06-08-wb/unnamed.png"
    "source/posts/2012-10-13-lift/IMG_0020.png"
);

counter=0
while [ $counter -lt ${#files[@]} ]; do
    file=${files[$counter]}
    commit=$(git rev-list -n 1 HEAD -- "$file") 
    echo Restoring file: $file from commit: $commit
    git checkout $commit^ "$file" 
    let counter+=1
done

В скрипте я объявляю массив с нужными мне файлами (в примере я сократил список). Далее в цикле проходимся по этому списку, при помощи команды git rev-list -n 1 HEAD -- "$file" находим коммит, в котором последний раз использовался этот файл и при помощи git checkout $commit^ "$file" восстанавливаем его из предыдущего коммита (для этого используется символ ^).