Возврат одного файла к предыдущей версии в git [дубликат]


этот вопрос уже есть ответ здесь:

  • Сброс или возврат определенного файла к определенной ревизии с помощью Git? 29 ответов

есть ли способ пройти через различные коммиты на файл. Скажем, я изменил файл 5 раз, и я хочу вернуться к изменению 2, после того, как я уже совершил и нажал на репозиторий.

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

может кто-нибудь прояснить это, пожалуйста?

6 462

6 ответов:

давайте начнем с качественного описания того, что мы хотим сделать (многое из этого сказано в ответе Бена Штрауба). Мы сделали некоторое количество коммитов, пять из которых изменил данный файл, и мы хотим вернуться к одной из предыдущих версий. Прежде всего, git не сохраняет номера версий для отдельных файлов. Он просто отслеживает контент - фиксация по существу является моментальным снимком рабочего дерева вместе с некоторыми метаданными (например, сообщением о фиксации). Итак, мы должны знать, какой коммит имеет версия файла, который мы хотим. Как только мы это узнаем, нам нужно будет сделать новую фиксацию, возвращающую файл в это состояние. (Мы не можем просто возиться с историей, потому что мы уже подтолкнули этот контент, и редактирование истории портит всех остальных.)

Итак, давайте начнем с поиска правильного фиксации. Вы можете посмотреть коммиты, которые внесли изменения в данный файл(ы) очень легко:

git log path/to/file

если ваши сообщения о фиксации недостаточно хороши, и вам нужно посмотреть, что было сделано для файла в каждой фиксации используйте :

git log -p path/to/file

или, если вы предпочитаете графический вид gitk

gitk path/to/file

вы также можете сделать это, как только вы запустили gitk через меню Вид; один из вариантов представления-это список путей для включения.

в любом случае, вы сможете найти в SHA1 (хэш) фиксации с версией файла, который вы хотите. Теперь, все что вам нужно сделать это:

# get the version of the file from the given commit
git checkout <commit> path/to/file
# and commit this modification
git commit

(сначала считывается команда checkout файл в индекс, а затем копирует его в дерево работ, поэтому нет необходимости использовать git add чтобы добавить его в индекс при подготовке к фиксации.)

если ваш файл не может иметь простой истории (например, переименования и копии), смотрите отличный комментарий VonC. git можно направить на более тщательный поиск таких вещей, за счет скорости. Если вы уверены, что история проста, вам не нужно беспокоиться.

Git очень гибкий. Вам не нужно сотни филиалов, чтобы сделать то, что вы просите. Если вы хотите вернуть состояние полностью назад к 2-му изменению (и это действительно изменение, которое уже было зафиксировано и нажато), используйте git revert. Что-то вроде:

git revert a4r9593432 

где a4r9593432-начальные символы хэша фиксации, которую вы хотите отменить.

если фиксация содержит изменения во многих файлах, но вы просто хотите вернуться просто один из файлов, вы можете использовать git reset (2 или 3 Форма):

git reset a4r9593432 -- path/to/file.txt
# the reverted state is added to the staging area, ready for commit
git diff --cached path/to/file.txt        # view the changes
git commit
git checkout HEAD path/to/file.txt        # make the working tree match HEAD           

но это довольно сложно, и сброс git опасен. Используйте git checkout <hash> <file path> вместо этого, как предполагает Jefromi.

если вы просто хотите посмотреть, как выглядел файл в commit x, вы можете использовать git show:

git show a4r9593432:path/to/file.txt

для всех команд есть много способов ссылаться на фиксацию, отличную от хэша фиксации (см. Именования Коммитов в Руководство Пользователя Git).

скажем, ваши 5 коммитов A,B,C,D,E--A - первый и E последние. Вы хотите вернуться .txt как это было после совершения A. Вам не нужно изучать или запоминать различные версии или параметры команд git-reset и git-checkout. Беги:

git show A:file.txt >file.txt

# If you want to commit the older version:
git add file.txt
git commit

команда git-show показывает содержимое или информацию о, любой объект в репозитории Git. Когда дается ссылка на фиксацию, например A (или мастер^ или голова~5 или ...), за которым следует двоеточие, а затем имя файла, он покажет содержимое этого файла, как это было после этого фиксации. Тогда это просто вопрос перенаправления вывода в файл.

вы можете взять разницу, которая отменяет изменения, которые вы хотите, и зафиксировать это.

например, если вы хотите отменить изменения в диапазоне from..to выполните следующее

git diff to..from > foo.diff  # get a reverse diff
patch < foo.diff
git commit -a -m "Undid changes from..to".

извлечено отсюда: http://git.661346.n2.nabble.com/Revert-a-single-commit-in-a-single-file-td6064050.html

 git revert <commit> 
 git reset 
 git add <path> 
 git commit ... 
 git reset --hard # making sure you didn't have uncommited changes earlier 

Он работал очень хорошо для меня.

Git не думает в терминах версий файлов. Версия в git-это снимок всего дерева.

Я не знаю, есть ли один лайнер, который вернет один файл в содержимое 5 коммитов назад, но решение lo-fi должно работать: checkout master~5, скопируйте файл в другое место, оформить заказ master, скопируйте файл обратно, а затем зафиксируйте.