Git вернуть удаленный файл и сохранить историю файлов

Предположим, у меня есть файл a.txt, Однажды я удалил его, зафиксировал и подтолкнул.

На следующий день я хотел отменить последний коммит, вернув a.txt, Я пытался с помощью git revert, но когда я сделал git blame, все строки показывают хеш возврата. Оригинальная история вины потеряна.

Можно ли восстановить файл и сохранить историю файлов, т. Е. Как если бы файл не был удален ранее? Обратите внимание, что я не должен изменять историю, поскольку коммит был нажат.

Спасибо!

3 ответа

Вы МОЖЕТЕ сделать это! Вот как:

  1. Начните новую ветку с коммита, предшествующего удалению, которое вы хотите отменить.
  2. Объединить оскорбительные изменения с git merge <sha> -s ours,
  3. Если фиксация имела изменения помимо удаления, которое вы хотите сохранить:
    1. Применить изменения к вашей рабочей копии с git diff <sha>^..<sha> | git apply,
    2. Откажитесь от удалений (доступно много методов; git checkout -p может хорошо работать для вас).
  4. Слейте эту ветку обратно в основную ветку (например, master).

Это создает историю с двумя ветвями; тот, в котором файл был удален, и тот, в котором он никогда не был удален. В результате, git может отслеживать историю файлов, не прибегая к такой героике, как -C -C -C, (На самом деле, даже с -C -C -Cфайл не "восстанавливается", потому что git видит, что новый файл был создан как копия ранее существующего файла. С помощью этой техники вы повторно вводите тот же файл в хранилище.)

Запусти мерзавца с -C опция указана трижды:

git blame -C -C -C

Это вызывает git blame искать контент, скопированный из файлов в предыдущих коммитах.

Из документации для git blame:

-C|<num>|

В дополнение к -M обнаруживать строки, перемещенные или скопированные из других файлов, которые были изменены в том же коммите. Это полезно, когда вы реорганизуете свою программу и перемещаете код между файлами. Когда этот параметр указан дважды, команда дополнительно ищет копии из других файлов в коммите, который создает файл. Когда эта опция задана три раза, команда дополнительно ищет копии из других файлов в любом коммите.

<num> является необязательным, но это нижняя граница количества буквенно-цифровых символов, которую Git должен определить как перемещение / копирование между файлами, чтобы связать эти строки с родительским коммитом. И значение по умолчанию - 40. Если их несколько -C варианты даны, <num> аргумент последнего -C вступит в силу.

Вы можете сделать это с помощью git reset вместо git revert, git reset удаляет новый коммит и извлекает предыдущий коммит. Это не рекомендуется, если вы уже подтолкнули вверх по течению.

NAME
       git-reset - Reset current HEAD to the specified state

SYNOPSIS
       git reset [-q] [<tree-ish>] [--] <paths>...
       git reset (--patch | -p) [<tree-ish>] [--] [<paths>...]
       git reset [--soft | --mixed | --hard | --merge | --keep] [-q] [<commit>]

DESCRIPTION
       In the first and second form, copy entries from <tree-ish> to the index. In the third form, set the
       current branch head (HEAD) to <commit>, optionally modifying index and working tree to match. The
       <tree-ish>/<commit> defaults to HEAD in all forms.

Так как вы уже нажали:

  • Если у вас нет активных соавторов, которые вытащили этот день, используйте git reset и заставить толчок git push -f,
Другие вопросы по тегам