Reset или вернуть конкретный файл в конкретную ревизию с помощью Git?

Я внес некоторые изменения в файл, который был передан несколько раз как часть группы файлов, но теперь хочу reset/вернуть изменения на него обратно в предыдущую версию.

Я сделал git log вместе с git diff, чтобы найти нужный мне вариант, но просто не знаю, как вернуть файл в прежнее состояние в прошлом.

2975
задан Hates_ 19 окт. '08 в 2:34
источник поделиться

27 ответов

Предполагая, что хэш требуемого фиксации c5f567:

git checkout c5f567 -- file1/to/restore file2/to/restore

На главной странице git checkout представлена ​​дополнительная информация.

Если вы хотите вернуться к изменениям, сделанным как раз 1 commit перед c5f567, передайте хеш фиксации как c5f567~1:

git checkout c5f567~1 -- file1/to/restore file2/to/restore

Как побочная заметка, мне всегда было неудобно с этой командой, потому что она использовалась как для обычных вещей (изменение между ветвями), так и для необычных деструктивных вещей (отбрасывание изменений в рабочем каталоге).

4056
ответ дан Greg Hewgill 19 окт. '08 в 2:39
источник поделиться

Вы можете быстро просмотреть изменения, внесенные в файл, используя команду diff:

git diff <commit hash> <filename>

Затем, чтобы вернуть конкретный файл этому фиксатору, используйте команду reset:

git reset <commit hash> <filename>

Возможно, вам придется использовать опцию --hard, если у вас есть локальные модификации.

Хорошим документооборотом для управления путевыми точками является использование тегов для чистоты точек на вашей временной шкале. Я не могу понять ваше последнее предложение, но то, что вам может понадобиться, - это расхождение ветки с предыдущего момента времени. Для этого используйте удобную команду checkout:

git checkout <commit hash>
git checkout -b <new branch name>

Затем вы можете переустановить это против своей основной линии, когда будете готовы объединить эти изменения:

git checkout <my branch>
git rebase master
git checkout master
git merge <my branch>
465
ответ дан Chris Lloyd 17 дек. '08 в 9:59
источник поделиться

Вы можете использовать любую ссылку на фиксацию git, включая SHA-1, если это наиболее удобно. Дело в том, что команда выглядит так:

git checkout [commit-ref] -- [filename]

283
ответ дан foxxtrot 08 апр. '09 в 0:48
источник поделиться
git checkout -- foo

Это будет reset foo для HEAD. Вы также можете:

git checkout HEAD^ foo

для одной ревизии и т.д.

226
ответ дан Greg Hewgill 29 авг. '08 в 23:56
источник поделиться

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

git checkout HEAD file/to/restore
102
ответ дан CDR 14 янв. '12 в 9:15
источник поделиться

У меня была такая же проблема только сейчас, и я нашел этот ответ проще всего понять (commit-ref - значение SHA изменения в журнале, который вы хотите отправить назад):

git checkout [commit-ref] [filename]

Это ставит эту старую версию в ваш рабочий каталог, и оттуда вы можете ее зафиксировать, если хотите.

97
ответ дан bbrown 27 мая '09 в 20:52
источник поделиться

Если вы знаете, сколько коммитов вам нужно вернуться, вы можете использовать:

git checkout master~5 image.png

Предполагается, что вы находитесь в ветке master, а желаемая версия - 5.

84
ответ дан Ron DeVera 07 апр. '09 в 17:03
источник поделиться

Я думаю, что нашел... от http://www-cs-students.stanford.edu/~blynn/gitmagic/ch02.html

Иногда вы просто хотите вернуться и забыть обо всех изменениях за определенный момент, потому что все они неправы.

Начните с:

$ git log

который показывает вам список последних коммитов и их хэш SHA1.

Затем введите:

$ git reset --hard SHA1_HASH

чтобы восстановить состояние для данной фиксации и стереть все новые записи из записи навсегда.

72
ответ дан jdee 17 дек. '08 в 9:53
источник поделиться

Это сработало для меня:

git checkout <commit hash> file

Затем зафиксируйте изменение:

git commit -a
55
ответ дан v2k 26 авг. '11 в 1:12
источник поделиться

Вы должны быть осторожны, когда говорите "откат". Если вы использовали одну версию файла в commit $A, а затем сделали два изменения в двух отдельных коммитах $B и $C (так что вы видите, это третья итерация файла), и если вы скажете "Я хочу вернуться к первому", вы действительно это имеете в виду?

Если вы хотите избавиться от изменений как второй, так и третьей итерации, это очень просто:

$ git checkout $A file

а затем вы фиксируете результат. Команда запрашивает "Я хочу проверить файл из состояния, записанного фиксацией $A".

С другой стороны, то, что вы имели в виду, это избавиться от изменения второй итерации (то есть совершить $B), при сохранении того, что зафиксировал файл $C в файле, вы хотели бы вернуть $B

$ git revert $B

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

51
ответ дан gitster 11 янв. '09 в 11:13
источник поделиться

Интересно, 'git checkout foo' не будет работать, если рабочая копия находится в каталоге с именем foo; однако, как "w20 > checkout HEAD foo" и "git checkout./foo" будет:

$ pwd
/Users/aaron/Documents/work/foo
$ git checkout foo
D   foo
Already on "foo"
$ git checkout ./foo
$ git checkout HEAD foo
34
ответ дан Aaron Maenpaa 30 авг. '08 в 0:26
источник поделиться

Здесь rebase работает:

git checkout <my branch>
git rebase master
git checkout master
git merge <my branch>

Предположим, что у вас есть

---o----o----o----o  master
    \---A----B       <my branch>

Первые две команды... совершить    git выписка   git мастер переустановки

... проверьте ветвь изменений, которые вы хотите применить к ветки master. Команда rebase берет коммиты из <my branch> (которые не найдены в master) и повторно применяет их к заголовку master. Другими словами, родительский элемент первого коммита в <my branch> больше не является предыдущим фиксатором в истории master, а текущим заголовком master. Две команды такие же, как:

git rebase master <my branch>

Возможно, было бы легче запомнить эту команду, так как ветки "base" и "modify" явно.

. Конечный результат:

---o----o----o----o   master
                   \----A'----B'  <my branch>

Последние две команды...

git checkout master
git merge <my branch>

... выполните быстрое слияние для применения всех изменений <my branch> на master. Без этого шага фиксация rebase не добавляется к master. Конечный результат:

---o----o----o----o----A'----B'  master, <my branch>

master и <my branch> обе ссылки B'. Кроме того, с этой точки можно безопасно удалить ссылку <my branch>.

git branch -d <my branch>
29
ответ дан cmcginty 24 февр. '09 в 12:43
источник поделиться

Мне нужно подключить EasyGit здесь, который является оберткой, чтобы сделать git более доступным для новичков, не запутывая опытных пользователей. Одна из вещей, которые она делает, - дает больше значений git revert. В этом случае вы просто скажете:

eg revert foo/bar foo/baz

18
ответ дан Aristotle Pagaltzis 19 окт. '08 в 3:16
источник поделиться

git -алиасы, awk и функции оболочки для спасения!

git prevision <N> <filename>

где <N> - это количество исправлений файла для отката для файла <filename>.
Например, чтобы проверить немедленную предыдущую ревизию одного файла x/y/z.c, запустите

git prevision -1 x/y/z.c

Как работает git предикция?

Добавьте в свой gitconfig

следующее:
[alias]
        prevision = "!f() { git checkout `git log --oneline $2 |  awk -v commit="$1" 'FNR == -commit+1 {print $1}'` $2;} ;f"

Команда в основном

  • выполняет git log в указанном файле и
  • выбирает соответствующий идентификатор фиксации в истории файла и
  • выполняет git checkout идентификатор commit для указанного файла.

По существу, все, что можно было бы сделать вручную в этой ситуации,
завернутый в один красивый, эффективный git -alias - git-prevision

17
ответ дан TheCodeArtist 01 мая '15 в 4:46
источник поделиться

Обратите внимание, что git checkout ./foo и git checkout HEAD ./foo не точно одно и то же; пример:

$ echo A > foo
$ git add foo
$ git commit -m 'A' foo
Created commit a1f085f: A
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 foo
$ echo B >> foo
$ git add foo
$ echo C >> foo
$ cat foo
A
B
C
$ git checkout ./foo
$ cat foo
A
B
$ git checkout HEAD ./foo
$ cat foo
A

(Второй add обрабатывает файл в индексе, но он не получает совершено.)

git checkout ./foo означает возврат пути ./foo к индексу ; добавление HEAD инструктирует Git вернуть этот путь в индекс к его HEAD до этого.

16
ответ дан Damien Diederen 31 авг. '08 в 14:54
источник поделиться

В случае, если вы хотите вернуть файл в предыдущую фиксацию (и файл, который вы хотите вернуть уже зафиксирован), вы можете использовать

git checkout HEAD^1 path/to/file

или

git checkout HEAD~1 path/to/file

Затем просто выполните этап и зафиксируйте "новую" версию.

Вооружившись знаниями о том, что в случае слияния commit может иметь двух родителей, вы должны знать, что HEAD ^ 1 является первым родителем, а HEAD ~ 1 является вторым родителем.

Либо будет работать, если в дереве есть только один родитель.

13
ответ дан ModernIncantations 11 янв. '14 в 3:29
источник поделиться

Чтобы перейти к предыдущей версии файла фиксации, получите номер фиксации, скажем, eb917a1 то

git checkout eb917a1 YourFileName

Если вам просто нужно вернуться к последней зарегистрированной версии

git reset HEAD YourFileName
git checkout YourFileName

Это приведет вас к последнему зафиксированному состоянию файла

8
ответ дан shah1988 25 февр. '14 в 17:01
источник поделиться

git checkout ref | commitHash - filePath

например.

git checkout HEAD~5 -- foo.bar
or 
git checkout 048ee28 -- foo.bar
7
ответ дан Amos Folarin 26 сент. '13 в 20:04
источник поделиться

Используйте git log для получения хеш-ключа для конкретной версии, а затем используйте git checkout <hashkey>

Примечание. Не забудьте ввести хэш перед последним. Последний хэш указывает текущую позицию (HEAD) и ничего не меняет.

5
ответ дан mustafakyr 05 дек. '11 в 23:09
источник поделиться

Для меня ни один ответ не казался действительно ясным, и поэтому я хотел бы добавить мой, который кажется супер простым.

У меня есть commit abc1, и после него я сделал несколько (или одну модификацию) файла file.txt.

Теперь скажите, что я что-то испортил в файле file.txt, и я хочу вернуться к предыдущему commit abc1.

1. git checkout file.txt: это приведет к удалению локальных изменений, если они вам не нужны.

2. git checkout abc1 file.txt: это приведет ваш файл к вашей желаемой версии

3. git commit -m "Restored file.txt to version abc1": это приведет к вашей реверсии.

  1. git push: это приведет все в удаленный репозиторий

Между шагами 2 и 3, конечно, вы можете сделать git status, чтобы понять, что происходит. Обычно вы должны видеть, что file.txt уже добавлен, и поэтому нет необходимости в git add.

5
ответ дан kalmanIsAGameChanger 23 марта '17 в 0:33
источник поделиться

Здесь много предложений, в основном по git checkout $revision -- $file. Несколько неясных альтернатив:

git show $revision:$file > $file

Кроме того, я часто использую это, чтобы временно увидеть определенную версию:

git show $revision:$file | less

или

git show $revision:$file | vim -R -

(OBS: $file должно быть префикс с ./, если это относительный путь для работы git show $revision:$file)

И еще более странно:

git archive $revision $file | tar -x0 > $file
4
ответ дан Peter V. Mørch 08 янв. '16 в 1:19
источник поделиться

Первая Reset Голова для целевого файла

git reset HEAD path_to_file

Вторая проверка этого файла

git checkout -- path_to_file
4
ответ дан gulshan maurya 04 апр. '17 в 13:25
источник поделиться

Очевидно, кому-то нужно написать понятную книгу на git или git, чтобы ее лучше объяснить в документации. Столкнувшись с этой же проблемой, я догадался, что

cd <working copy>
git revert master

отменяет последнее совершение, которое, как представляется, делает.

Ян

4
ответ дан Ian Davis 16 дек. '11 в 6:03
источник поделиться
git revert <hash>

Вернет заданную фиксацию. Похоже, вы думаете, что git revert влияет только на последнее совершение.

Это не решит вашу проблему, если вы хотите отменить изменение в определенном файле и что commit изменился больше, чем этот файл.

2
ответ дан Otto 17 дек. '08 в 21:56
источник поделиться

Многие ответы здесь требуют использовать git reset ... <file> или git checkout ... <file>, но при этом вы потеряете все изменения в <file>, совершенные после коммита, который вы хотите вернуть.

Если вы хотите отменить изменения только от одного фиксации только в одном файле, как это сделал бы git revert, но только для одного файла (или, скажем, подмножества файлов фиксации), я предлагаю использовать как git diff, так и git apply как это (с <sha>= хеш коммита, который вы хотите вернуть):

git diff <sha>^ <sha> path/to/file.ext | git apply -R

В принципе, он сначала сгенерирует патч, соответствующий изменениям, которые вы хотите вернуть, а затем отмените применение патча, чтобы отбросить эти изменения.

Конечно, он не работает, если ревертированные строки были изменены любым фиксацией между <sha1> и HEAD (конфликтом).

1
ответ дан Vince 07 дек. '16 в 17:43
источник поделиться

Если вы используете Git Extensions и хотите вернуться к родительскому фиксации для файла, вы можете выбрать фиксацию, содержащую изменения, которые хотите вернуть, затем выбрать вкладку "Diff" в деталях щелкните правой кнопкой мыши файл, который вы хотите вернуть, затем Reset файл на "....", затем "A" (родительский)

0
ответ дан Chris Halcrow 26 сент. '17 в 4:48
источник поделиться

Вот мой путь.

a) В Android Studio откройте файл.

b) git → Показать историю, найти предыдущую фиксацию, к которой я хочу вернуться. Получите commit_id (т.е. Commit hash).

c) git checkout commit_id file_path

-1
ответ дан Francis Bacon 13 марта '17 в 11:10
источник поделиться

Другие вопросы по меткам