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
HEAD와 HEAD ^의 차이점은 무엇입니까?
hasen mar

62
HEAD는 현재 브랜치에서 가장 최근 커밋이고 HEAD ^는 현재 브랜치에서 커밋보다 먼저 커밋됩니다. 설명하는 상황에서는 git checkout HEAD-filename을 사용할 수 있습니다.
Paul

16
간단히 말해 "git checkout sha-reference-filename"에서 sha-reference는 모든 형태 (분기, 태그, 부모 등)의 커밋 sha에 대한 참조입니다.
Lakshman Prasad

29
참고 : 파일이 이미 준비된 경우 먼저 재설정해야합니다. git reset HEAD <filename> ; git checkout -- <filename>
Olie

14
@gwho 예, HEAD^^가장 최근의 커밋 2 개 또는 HEAD^^^다시 커밋 3 개 를 수행 할 수 있습니다 . 또는을 사용할 수도 있습니다 HEAD~2. HEAD~3더 많은 커밋을 되돌리려면 HEAD^2"이 커밋의 두 번째 부모" 를 의미합니다. 병합 커밋으로 인해 커밋에 둘 이상의 이전 커밋이 HEAD^있을 수 있으므로 숫자를 사용하면 해당 부모 중 하나를 선택하고 숫자를 사용 HEAD~하면 항상 첫 번째 부모를 선택하지만 해당 커밋 수는 다시 선택합니다. 자세한 내용 git help rev-parse은 참조하십시오.
Brian Campbell

139

그냥 사용

git checkout filename

이것은 파일 이름을 현재 브랜치의 최신 버전으로 바꿉니다.

경고 : 변경 사항이 삭제되며 백업이 유지되지 않습니다.


22
@duckx 그것은 파일 이름에서 분기 이름을 명확하게하는 것입니다. 당신이 말하는 경우 git checkout xx는 분기 이름뿐만 아니라 파일 이름이 될 일이, 내가하지 않도록 기본 동작이 무엇이야하지만 난 자식이 당신이 지점 X로 전환한다고 가정 것이라 생각합니다. 당신이 사용할 때 --뒤에 오는 것은 파일 이름입니다.
hasen

1
그것을 정리해 주셔서 감사합니다. 모든 사람들은 단지 당신이 예를 보여줄 때의 의미를 알고 있다고 가정합니다. 구글도 쉽게 할 수있는 것이 아닙니다.
Patoshi パ ト シ

1
답변을 수정하여 답변을 삭제 한 --것 같습니다. @hasen이 지적한 것처럼 여전히 정확하지만 파일 이름과 지점 이름 사이에 모호성이있는 경우 여기에서 원하지 않는 동작이 발생할 수 있습니다!
BrainSlugs83

2
나는 그것이 --좋고 좋고 쉬운 방법을 좋아합니다 . 파일 이름을 사용하여 분기 이름을 지정할 때는 어딘가에 나쁜 생각이 있어야합니다.
Marco Faustinelli

133
git checkout <commit> <filename>

드루팔 6.10으로 업그레이드했을 때 파비콘이 몇 커밋 전에 덮어 쓰여졌 기 때문에 오늘 이것을 사용했습니다. 그래서 다시 가져와야했습니다. 여기 내가 한 일이 있습니다.

git checkout 088ecd favicon.ico

1
스크롤 톤에서 "git log --stat"출력을 제외하고 (이전에 삭제 된 파일의) 커밋을 얻는 방법은 무엇입니까?
Alex

4
IMO 명령 줄을 통해 gits 로그를 스캔하고 올바른 파일을 찾는 것은 어렵습니다. sourcetreeapp.com
neoneye

6
git log --oneline <filename>더 작은 로그를 제공하고 특정 파일에 대한 변경 사항 만 포함합니다
rjmunro

1
또는 다음을 사용할 수 있습니다git reflog <filename>
ygesher

70

파일이 이미 준비된 경우 (파일을 편집 한 후 git add 등을 수행하면 발생할 수 있음) 변경 내용을 준비 해제합니다.

사용하다

git reset HEAD <file>

그때

git checkout <file>

아직 준비되지 않은 경우

git checkout <file>

2
이것은 허용 된 하하보다 도움이되었습니다. 어떤 변화가 준비되었고 아직 이루어지지 않은 것을 잊어 버리기 쉬우므로 재설정이 도움이되었습니다. 전에도 "git reset --hard"를 시도했지만 "git reset HEAD"의 기능은 수행하지 않았습니다. 왜 궁금해?
Arman Bimatov

20

하나의 파일에 대한 이전 커밋의 변경 사항을 취소하려면 다음을 시도하십시오.

git checkout branchname^ filename

마지막 커밋 이전의 파일을 체크 아웃합니다. 커밋을 몇 번 더 되돌리려면 branchname~n표기법을 사용하십시오 .


커밋에서 변경 사항을 제거하지 않고 HEAD의 버전에 diff를 적용합니다.
FernandoEscher

2
사실이지만 원래 포스터는 마지막 커밋의 변경 사항을 되 돌리지 않고 작업 복사본 수정본을 되돌리고 싶었습니다. 원래 포스터의 질문은 약간 불분명하여 혼란을 이해할 수 있습니다.

아마도 OP의 사용은 아니지만 마스터의 사본으로 분기를 덮어 쓰는 방법을 찾고있었습니다. 교체 할 때 꽤 잘 작동합니다.branchname^
Alex

15

git bash를 통해 완료했습니다.

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

  1. 힘내 상태. [그래서 우리는 하나의 파일 뭉치가 수정 된 것을 보았습니다.]
  2. git checkout-index.html [i index.html 파일에서 변경되었습니다 :
  3. 자식 상태 [이 변경 사항이 제거되었습니다]

여기에 이미지 설명을 입력하십시오


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 resetgit 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/*

위의 별표는 name1 / name2 아래의 해당 위치에서 모든 파일을 실행 취소하는 트릭을 수행합니다.

마찬가지로 다음과 같이 여러 폴더의 모든 파일에서 변경 사항을 취소 할 수 있습니다.

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

위의 name1 / name2 / * nameA / subFolder / * 사이의 공백을 다시 염두에 두십시오.

참고 : name1, name2, nameA, subFolder-이 예제 폴더 이름은 모두 해당 파일이 상주 할 수있는 폴더 또는 패키지를 나타냅니다.


5

SHA id를 사용하여 파일을 복원합니다. 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
사용할 특정 명령을 추가하면 원래 포스터와 향후 방문자에게 도움이됩니다.
Adrian

0

왜 그런지 모르겠지만 코드를 입력하려고하면 이미지로 나타납니다.

여기에 이미지 설명을 입력하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.