Git вернуть удаленный файл и сохранить историю файлов
Предположим, у меня есть файл a.txt
, Однажды я удалил его, зафиксировал и подтолкнул.
На следующий день я хотел отменить последний коммит, вернув a.txt
, Я пытался с помощью git revert
, но когда я сделал git blame
, все строки показывают хеш возврата. Оригинальная история вины потеряна.
Можно ли восстановить файл и сохранить историю файлов, т. Е. Как если бы файл не был удален ранее? Обратите внимание, что я не должен изменять историю, поскольку коммит был нажат.
Спасибо!
3 ответа
Вы МОЖЕТЕ сделать это! Вот как:
- Начните новую ветку с коммита, предшествующего удалению, которое вы хотите отменить.
- Объединить оскорбительные изменения с
git merge <sha> -s ours
, - Если фиксация имела изменения помимо удаления, которое вы хотите сохранить:
- Применить изменения к вашей рабочей копии с
git diff <sha>^..<sha> | git apply
, - Откажитесь от удалений (доступно много методов;
git checkout -p
может хорошо работать для вас).
- Применить изменения к вашей рабочей копии с
- Слейте эту ветку обратно в основную ветку (например, 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
,