Поиск и восстановление удаленного файла в репозитории Git
скажем, я в репозитории Git. Я удаляю файл и фиксирую это изменение. Я продолжаю работать и делаю еще несколько обязательств. Затем я обнаружил, что мне нужно восстановить этот файл.
Я знаю, что могу проверить файл с помощью git checkout HEAD^ foo.bar
, но я действительно не знаю, когда этот файл был удален.
- каков был бы самый быстрый способ найти фиксацию, которая удалила данное имя файла?
- каков был бы самый простой способ вернуть этот файл в мою работу копия?
Я надеюсь, что мне не придется вручную просматривать мои журналы, проверять весь проект для данного SHA, а затем вручную копировать этот файл в мою исходную проверку проекта.
19 ответов
найти последнюю фиксацию, которая повлияла на данный путь. Поскольку файл не находится в фиксации HEAD, эта фиксация должна была удалить его.
git rev-list -n 1 HEAD -- <file_path>
затем проверьте версию на фиксации раньше, используя курсор (^
) символов:
git checkout <deleting_commit>^ -- <file_path>
или в одной команде, если $file
это файл, о котором идет речь.
git checkout $(git rev-list -n 1 HEAD -- "$file")^ -- "$file"
если вы используете zsh и опция EXTENDED_GLOB включена, символ курсора не будет работать. Вы можете использовать ~1
вместо.
git checkout $(git rev-list -n 1 HEAD -- "$file")~1 -- "$file"
- использовать
git log --diff-filter=D --summary
чтобы получить все коммиты, которые удалили файлы и файлы удалены; - использовать
git checkout $commit~1 filename
для восстановления удаленного файла.
здесь $commit
значение фиксации вы нашли на шаге 1, например,e4cf499627
чтобы восстановить все удаленные файлы в папку, введите следующую команду.
git ls-files -d | xargs git checkout --
Я пришел к этому вопросу, чтобы восстановить файл, который я только что удалил, но я еще не совершил изменения. На всякий случай, если вы окажетесь в такой ситуации, все, что вам нужно сделать, это следующее:
git checkout HEAD -- path/to/file.ext
если вы сумасшедший, используйте git-bisect
. Вот что нужно сделать:
git bisect start
git bisect bad
git bisect good <some commit where you know the file existed>
теперь пришло время запустить автоматический тест. Команда оболочки '[ -e foo.bar ]'
вернет 0, если , и 1 в противном случае. Команда "выполнить" команды git-bisect
будет использовать двоичный поиск, чтобы автоматически найти первую фиксацию, где тест терпит неудачу. Он начинается на полпути через заданный диапазон (от хорошего до плохого) и разрезает его пополам на основе результата указанного теста.
git bisect run '[ -e foo.bar ]'
теперь вы находитесь в фиксации, которая удалила его. Отсюда вы можете вернуться в будущее и использовать git-revert
чтобы отменить изменение,
git bisect reset
git revert <the offending commit>
или вы можете вернуться на одну фиксацию и вручную проверить повреждение:
git checkout HEAD^
cp foo.bar /tmp
git bisect reset
cp /tmp/foo.bar .
мой новый любимый псевдоним, основанный на bonyiii ' s ответ (upvoted), и мой собственный ответ о "передайте аргумент команде псевдонима Git":
git config alias.restore '!f() { git checkout $(git rev-list -n 1 HEAD -- )~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- )~1 | grep '^D' | cut -f 2); }; f'
Я потерял файл, удаленный по ошибке несколько коммитов назад?
Быстро:
git restore my_deleted_file
кризис миновал.
Роберт Дэйли предлагает в комментариях следующие псевдонимы:
restore-file = !git checkout $(git rev-list -n 1 HEAD -- "")^ -- ""
и jegan добавляет в комментариях:
для установки псевдонима из командной строки я использовал следующую команду:
git config --global alias.restore "\!git checkout $(git rev-list -n 1 HEAD -- \"$1\")^ -- \"$1\""
Если вы знаете имя файла, это простой способ с помощью основных команд:
перечислите все коммиты для этого файла.
git log -- path/to/file
последняя фиксация (самая верхняя) - это та, которая удалила файл. Таким образом, вам нужно восстановить Второй до последнего фиксации.
git checkout {second to last commit} -- path/to/file
чтобы восстановить удаленный и введенный файл:
git reset HEAD some/path
git checkout -- some/path
Он был протестирован на Git версии 1.7.5.4.
Если вы только внесли изменения и удалили файл, но не зафиксировали его, и теперь вы расстались с вашими изменениями
git checkout -- .
но удаленные файлы не возвращаются, вы просто выполняете следующую команду:
git checkout <file_path>
и presto, ваш файл вернулся.
у меня есть данное решение.
-
получить идентификатор коммита, где файл был удален, используя один из способов ниже.
-
git log --grep=*word*
git log -Sword
git log | grep --context=5 *word*
-
git log --stat | grep --context=5 *word*
# рекомендуется, если вы вряд ли вспомните что-нибудь
-
вы должны получить что-то вроде:
commit bfe68bd117e1091c96d2976c99b3bcc8310bebe7 Автор: Александр Орлов Дата: Чт 12 Мая 23: 44: 27 2011 +0200
replaced deprecated GWT class - gwtI18nKeySync.sh, an outdated (?, replaced by a Maven goal) I18n generation script
совершить 3ea4e3af253ac6fd1691ff6bb89c964f54802302 Автор: Александр Орлов Дата: Чт 12 Мая 22:10: 22 2011 +0200
3. Теперь, используя идентификатор фиксации bfe68bd117e1091c96d2976c99b3bcc8310bebe7 do:
git checkout bfe68bd117e1091c96d2976c99b3bcc8310bebe7^1 yourDeletedFile.java
поскольку идентификатор фиксации ссылается на фиксацию, где файл уже был удален, вам нужно ссылаться фиксация перед bfe68b что можно сделать путем добавления ^1
. Это означает: дайте мне совершить перед bfe68b.
во многих случаях может быть полезно использовать coreutils (grep, sed, etc.) совместно с Git. Я уже знаю эти инструменты довольно хорошо,но Git меньше. Если бы я хотел выполнить поиск удаленного файла, я бы сделал следующее:
git log --raw | grep -B 30 $'D\t.*deleted_file.c'
когда я нахожу ревизию/фиксацию:
git checkout <rev>^ -- path/to/refound/deleted_file.c
Как уже сказали до меня.
теперь файл будет восстановлен до состояния, в котором он был до удаления. Не забудьте повторно посвятить его работе дерево, если хочешь, чтобы оно было рядом.
git undelete path/to/file.ext
-
положите это в свой
.bash_profile
(или другой соответствующий файл, который загружается при открытии командной оболочки):git config --global alias.undelete '!sh -c "git checkout $(git rev-list -n 1 HEAD -- )^ -- " -'
-
затем использовать:
git undelete path/to/file.ext
этот псевдоним сначала проверяет, чтобы найти последнюю фиксацию, где этот файл существовал, а затем делает проверку git этого пути файла из этого последнего фиксации, где этот файл существовал. источник
поэтому мне пришлось восстановить кучу удаленных файлов из определенной фиксации, и я справился с ней двумя командами:
git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git checkout <rev>^ --
git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git reset HEAD
(обратите внимание на пробел в конце каждой команды.)
файлы были добавлены .файл gitignore, а затем очищен с помощью git rm, мне нужно было восстановить файлы, но затем распаковать их. У меня были сотни файлов для восстановления, ввод вручную для каждого файла, как и в других примерах, будет слишком медленным.
user@bsd:~/work/git$ rm slides.tex
user@bsd:~/work/git$ git pull
Already up-to-date.
user@bsd:~/work/git$ ls slides.tex
ls: slides.tex: No such file or directory
восстановить удаленный файл:
user@bsd:~/work/git$ git checkout
D .slides.tex.swp
D slides.tex
user@bsd:~/work/git$ git checkout slides.tex
user@bsd:~/work/git$ ls slides.tex
slides.tex
у меня был тот же вопрос. Сам того не зная, я создал болтается commit.
список свесив совершает
git fsck --lost-found
проверить каждый болтающийся фиксации
git reset --hard <commit id>
мои файлы снова появились, когда я перешел к болтающейся фиксации.
git status
по причине:
“HEAD detached from <commit id where it detached>”
в нашем случае мы случайно удалили файлы в фиксации, а некоторые фиксации позже мы поняли нашу ошибку и хотели вернуть все файлы, которые были удалены, но не те, которые были изменены.
основываясь на превосходном ответе Чарльза Бейли, вот мой один лайнер:
git co $(git rev-list -n 1 HEAD -- <file_path>)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- <file_path>)~1 head | grep '^D' | cut -f 2)
Если вы знаете фиксацию, которая удалила файл(ы), выполните эту команду, где <SHA1_deletion>
- это фиксация, которая удалила файл:
git diff --diff-filter=D --name-only <SHA1_deletion>~1 <SHA1_deletion> | xargs git checkout <SHA1_deletion>~1 --
в части перед каналом перечислены все файлы, которые были удалены в фиксации; все они извлекаются из предыдущей фиксации для их восстановления.