Сброс или возврат определенного файла к определенной ревизии с помощью Git? - PullRequest
3989 голосов
/ 19 октября 2008

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

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

Ответы [ 31 ]

36 голосов
/ 30 августа 2008

Забавно, но git checkout foo не будет работать, если рабочая копия находится в каталоге с именем foo; однако и «git 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
32 голосов
/ 24 февраля 2009

Вот как 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 Checkout git rebase master

... проверить ветку изменений, которые вы хотите применить к ветке 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. Без этого шага коммит ребаз не добавляется в master. Окончательный результат:

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

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

git branch -d <my branch>
22 голосов
/ 04 апреля 2017

Первая головка сброса для целевого файла

git reset HEAD path_to_file

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

git checkout -- path_to_file
21 голосов
/ 01 мая 2015

git-aliases, awk и shell-функции на помощь!

git prevision <N> <filename>

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

git prevision -1 x/y/z.c

Как работает git prevision?

Добавьте следующее к вашему 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 для идентификатора фиксации для указанного файла.

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

20 голосов
/ 19 октября 2008

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

<a href="http://www.gnome.org/~newren/eg/documentation/revert.html" rel="noreferrer">eg revert</a> <b>foo/bar foo/baz</b>

20 голосов
/ 11 января 2014

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

git checkout HEAD^1 path/to/file

или

git checkout HEAD~1 path/to/file

Затем просто подготовьте и зафиксируйте «новую» версию.

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

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

18 голосов
/ 31 августа 2008

Обратите внимание, однако, что 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 редакция перед этим.

15 голосов
/ 08 января 2016

Множество предложений здесь, большинство из них по линии git checkout $revision -- $file. Пара неясных альтернатив:

git show $revision:$file > $file

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

git show $revision:$file

или

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

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

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

git archive $revision $file | tar -x0 > $file
11 голосов
/ 25 февраля 2014

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

git checkout eb917a1 YourFileName

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

git reset HEAD YourFileName
git checkout YourFileName

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

11 голосов
/ 23 марта 2017

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

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

Теперь скажите, что я что-то испортил в файле file.txt и хочу вернуться к предыдущему коммиту 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.

не требуется.
...