Скасувати модифікації робочої копії одного файлу в Git?


1632

Після останньої фіксації я змінив купу файлів у своїй робочій копії, але хочу скасувати зміни в одному з цих файлів, як і повернути їх до того ж стану, що і остання фіксація.

Однак я хочу лише скасувати зміни робочої копії лише одного файлу, нічого іншого.

Як це зробити?

Відповіді:


2212

Можна використовувати

git checkout -- file

Ви можете зробити це без --(як це запропонував nimrodm), але якщо ім'я файлу має вигляд гілки чи тегу (або іншого ідентифікатора редакції), воно може заплутатися, тому --найкраще використовувати.

Ви також можете перевірити певну версію файлу:

git checkout v1.2.3 -- file         # tag v1.2.3
git checkout stable -- file         # stable branch
git checkout origin/master -- file  # upstream master
git checkout HEAD -- file           # the version from the most recent commit
git checkout HEAD^ -- file          # the version before the most recent commit

34
яка різниця між ГОЛОВОЮ ТА ГОЛОВОЮ ^?
hasen

62
HEAD - це найновіша фіксація на поточній гілці, а HEAD ^ - це фіксація перед цією гілкою. У описуваній ситуації ви можете використовувати git checkout HEAD - ім'я файлу.
Павло

16
Коротше кажучи, "git checkout sha-reference - ім'я файлу", де sha-посилання - це посилання на sha комітету, в будь-якій формі (гілка, тег, батьківщина тощо)
Lakshman Prasad

29
ПРИМІТКА. Якщо файл уже встановлено, спершу його потрібно скинути. git reset HEAD <filename> ; git checkout -- <filename>
Оліє

14
@gwho Так, ви можете зробити HEAD^^за 2 коміти з останніх або HEAD^^^за 3 комісії назад. Ви також можете використовувати HEAD~2або HEAD~3, що стає зручнішим, якщо ви хочете повернути більше комісій назад, тоді як HEAD^2означає "другий з батьків цього комітету"; через об'єднання об'єднань комісія може мати більше одного попереднього прихильності, тому з HEAD^числом вибирає, хто з цих батьків, тоді як з HEAD~номером завжди вибирає першого з батьків, але це число здійснює назад. Дивіться git help rev-parseдокладнішу інформацію.
Брайан Кемпбелл

139

Просто використовуйте

git checkout filename

Це замінить ім'я файлу останньою версією з поточної гілки.

УВАГА: ваші зміни будуть відкинуті - резервна копія не зберігається.


22
@duckx - це роз'єднати імена гілок з іменами файлів. якщо ви говорите, git checkout xі x трапляється як назва гілки, а також ім'я файлу, я не впевнений, що таке поведінка за замовчуванням, але я думаю, що git припустить, що ви хочете перейти на гілку x. Під час використання --ви говорите, що наступне - це назви файлів.
hasen

1
ic дякую за очищення цього. всі припускають, що ви знаєте, що означає - коли вони показують вам приклади. і це не те, що ви також можете легко гугл.
Патоші パ ト シ

1
Схоже, відповідь була відредагована, щоб видалити --її. Хоча все-таки правильно, як зазначає @hasen, якщо між іменем файлу та іменами гілок є неоднозначність, то тут у вас може виникнути дуже небажана поведінка!
BrainSlugs83

2
Мені подобається, як є, без --приємного та легкого. Коли ви називаєте гілки, використовуючи назви файлів, десь має бути погано задуматися ...
Марко Фаустінеллі

133
git checkout <commit> <filename>

Я використовував це сьогодні, тому що зрозумів, що мій фавікон був перезаписаний кілька фільмів тому, коли я зробив реплікацію до drupal 6.10, тому мені довелося повернути його. Ось що я зробив:

git checkout 088ecd favicon.ico

1
Як мені отримати фіксацію (раніше видаленого файлу), окрім прокрутки викидання тонн виводу "git log --stat"?
Олексій

4
ІМО складно через командний рядок важко сканувати через журнал gits і знайти потрібний файл. Набагато простіше за допомогою програми GUI, наприклад sourcetreeapp.com
neoneye

6
git log --oneline <filename>дасть вам більш компактний журнал і включить лише зміни до конкретного файлу
rjmunro

1
Ви також можете скористатисяgit reflog <filename>
ygesher

70

Якщо ваш файл уже є поетапним (трапляється, коли ви робите додавання git і т. Д. Після редагування файлу), щоб скасувати зміни.

Використовуйте

git reset HEAD <file>

Тоді

git checkout <file>

Якщо ви вже не ставили, просто використовуйте

git checkout <file>

2
Це було корисніше, ніж прийняте ха-ха. Неважко забути, які зміни було проведено, а що не, тому перезавантаження допомогло. Хоча я і раніше спробував "git reset --hard", це не зробило те, що зробив "git reset HEAD". Цікаво, чому?
Арман Біматов

20

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

git checkout branchname^ filename

Це дозволить перевірити файл таким, яким він був до останнього фіксації. Якщо ви хочете піти ще кілька разів назад, використовуйте branchname~nпозначення.


Це не призведе до видалення змін з комітету, воно просто застосує diff до версії на HEAD.
FernandoEscher

2
Незважаючи на те, що справжній плакат просто хотів відновити модифікації робочої копії (я думаю), а не повернути зміни з останнього комітету. Питання оригінального плаката було трохи незрозумілим, тому я можу зрозуміти плутанину.

можливо, не використання ОП, але я шукав, як переписати свою гілку з головною копією - це працює дуже добре при замініbranchname^
Алекс

15

Я закінчив через git bash:

(use "git checkout -- <file>..." to discard changes in working directory)

  1. Стан Git. [Отже, ми побачили, що один файл був модифікований.]
  2. git checkout - index.html [я змінив файл index.html:
  3. статус git [тепер ці зміни видалено]

введіть тут опис зображення


8

Я завжди плутаюсь із цим, тому ось тестовий випадок нагадування; скажімо, у нас є цей bashсценарій для тестування git:

set -x
rm -rf test
mkdir test
cd test
git init
git config user.name test
git config user.email test@test.com
echo 1 > a.txt
echo 1 > b.txt
git add *
git commit -m "initial commit"
echo 2 >> b.txt
git add b.txt
git commit -m "second commit"
echo 3 >> b.txt

На даний момент зміна не ставиться в кеш-пам'яті, так git status:

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   b.txt

no changes added to commit (use "git add" and/or "git commit -a")

Якщо з цього моменту ми це зробимо git checkout, результат такий:

$ git checkout HEAD -- b.txt
$ git status
On branch master
nothing to commit, working directory clean

Якщо замість цього ми це зробимо git reset, результат:

$ git reset HEAD -- b.txt
Unstaged changes after reset:
M   b.txt
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   b.txt

no changes added to commit (use "git add" and/or "git commit -a")

Отже, у цьому випадку - якщо зміни не є поетапними, git resetце не має значення, тоді git checkoutяк зміни перезаписуються.


Тепер скажімо, що остання зміна вищезазначеного сценарію є поетапною / кешованою, тобто ми також зробили git add b.txtв кінці.

У цьому випадку git statusна даний момент є:

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   b.txt

Якщо з цього моменту ми це зробимо git checkout, результат такий:

$ git checkout HEAD -- b.txt
$ git status
On branch master
nothing to commit, working directory clean

Якщо замість цього ми це зробимо git reset, результат:

$ git reset HEAD -- b.txt
Unstaged changes after reset:
M   b.txt
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   b.txt

no changes added to commit (use "git add" and/or "git commit -a")

Отже, у такому випадку - якщо зміни будуть поетапними, git resetвони в основному вносять поетапні зміни в нестандартні зміни - при git checkoutцьому зміни будуть повністю замінені.


7

Ця відповідь призначена для команди, необхідної для скасування локальних змін, які знаходяться в декількох конкретних файлах в одній або декількох папках (або каталогах). Це відповідь конкретно стосується питання, коли користувач має більше одного файлу, але користувач не хоче скасувати всі локальні зміни:

якщо у вас є один або кілька файлів, ви можете застосувати одну і ту ж команду ( git checkout -- file) до кожного з цих файлів, перерахувавши кожне їх розташування, розділене пробілом, як у:

git checkout -- name1/name2/fileOne.ext nameA/subFolder/fileTwo.ext

майте на увазі пробіл вище name1 / name2 / fileOne.ext nameA / subFolder / fileTwo.ext

Для декількох файлів в одній папці:

Якщо вам потрібно скасувати зміни для всіх файлів у певному каталозі, скористайтеся git checkout таким чином:

git checkout -- name1/name2/*

Зірочка у наведеному вище полягає в хитрість скасування всіх файлів у цьому місці під ім'ям1 / ім'я2.

Так само, наступне може скасувати зміни у всіх файлах для кількох папок:

git checkout -- name1/name2/* nameA/subFolder/*

знову пам’ятайте пробіл між name1 / name2 / * nameA / subFolder / * у зазначеному вище.

Примітка: name1, name2, nameA, subFolder - усі ці приклади прикладних папок вказують на папку або пакет, де можуть знаходитися файли, про які йдеться.


5

Я відновлюю свої файли за допомогою ідентифікатора SHA, що я роблю git checkout <sha hash id> <file name>



2

Якщо ви ще не надіслали або іншим чином не поділилися своїми зобов'язаннями:

git diff --stat HEAD^...HEAD | \
fgrep filename_snippet_to_revert | cut -d' ' -f2 | xargs git checkout HEAD^ --
git commit -a --amend

0

Якщо це вже зроблено, ви можете відновити зміну для файлу та знову зробити, а потім скасувати нову комісію з останньою.


1
Додавання конкретних команд для використання допоможе оригінальному плакату та майбутнім відвідувачам.
Адріан

0

Я не знаю чому, але коли я намагаюся ввести свій код, він з'являється як зображення.

введіть тут опис зображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.